My knowledge of javascript is limited. However, with much reading I was able to hack together the functions below. The goal is to define a generic function with which I can extract certain data from Yahoo finance.
In the example below, I'm pulling in A LOT of JSON data for any ticker (example link at the bottom). From the returned JSON, I select which values I'm interested in (here only dividendRate and paypoutRatio. If you call this function in a cell (I use Google Sheets), it will return 2 cells with the requested information:
=yFinance("KO")
------
| 1.76 |
------
| 0.75 |
------
Link used: Yahoo Finance JSON for Coca Cola
What I need, however, is to have the data formatted not in 2 cells BELOW each other, but NEXT TO each other:
=yFinance("KO")
------ ------
| 1.76 | 0.75 |
------ ------
I have two questions:
- How can the code (probably in
getMatchingValues()
?) be updated to make this happen? - Is there any way to simplify these functions?
Any help is greatly appreciated, also because I feel that a generic function like this would benefit many people in the future. I have seen many posts about extracting a single value from Yahoo Finance, mostly by parsing the HTML (tables) using Google Sheets INDEX()
function, but I believe via the JSON is faster and more resistent to future front-end changes at Yahoo.
function yFinance(symbol) {
const url = 'https://query2.finance.yahoo.com/v10/finance/quoteSummary/' encodeURI(symbol)
'?modules=price,assetProfile,summaryDetail,incomeStatementHistory,'
'balanceSheetHistory,defaultKeyStatistics,financialData,calendarEvents,'
'recommendationTrend,upgradeDowngradeHistory,majorHoldersBreakdown'
;
const response = UrlFetchApp.fetch(url, {muteHttpExceptions: true});
const responseCode = response.getResponseCode();
if (responseCode === 200) {
const quote = JSON.parse(response.getContentText());
const paths = [
'summaryDetail/dividendRate/raw',
'summaryDetail/payoutRatio/raw'
];
return getMatchingValues(getPath(quote, 'quoteSummary/result/0'), paths);
}
else
{
return -1;
}
}
function getPath( obj, path ) {
if (!path || !obj) {
return null;
}
const parts = path.split('/');
const currentPath = parts[0];
const nextPath = parts.slice(1).join('/');
const currentObj = obj[currentPath];
// final path, exit here
if (nextPath.length === 0) {
return currentObj;
}
if (Array.isArray( currentObj )) {
// does an element exit at the next level
if ( currentObj[parts[1]] ) {
// will continue reading for 1 element
return getPath( currentObj, nextPath );
}
// return all the subpaths, skip the ones that are falsy
return currentObj.map( item => getPath( item, nextPath ) ).filter( v => v );
}
// get the next part of the object
return getPath( currentObj, nextPath );
}
function getMatchingValues( obj, paths ) {
return paths.flatMap( path => getPath( obj, path ));
}
CodePudding user response:
If you want to get side by side values, modify by adding brackets as follows
return [getMatchingValues(getPath(quote, 'quoteSummary/result/0'), paths)];
You can simplify the code as follows
function yFinance_new(symbol) {
const url = 'https://query2.finance.yahoo.com/v10/finance/quoteSummary/' encodeURI(symbol)
'?modules=price,assetProfile,summaryDetail,incomeStatementHistory,'
'balanceSheetHistory,defaultKeyStatistics,financialData,calendarEvents,'
'recommendationTrend,upgradeDowngradeHistory,majorHoldersBreakdown'
;
const response = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
const responseCode = response.getResponseCode();
if (responseCode === 200) {
const quote = JSON.parse(response.getContentText());
return [[
quote.quoteSummary.result[0].summaryDetail.dividendRate.raw,
quote.quoteSummary.result[0].summaryDetail.payoutRatio.raw
]];
}
else {
return -1;
}
}