Home > Net >  Requesting and reading JSON from Yahoo Finance with a generic function
Requesting and reading JSON from Yahoo Finance with a generic function

Time:04-11

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:

  1. How can the code (probably in getMatchingValues()?) be updated to make this happen?
  2. 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;
  }
}
  • Related