Quantcast
Channel: ListenData
Viewing all articles
Browse latest Browse all 97

Get Historical Data From Yahoo Finance into Google Sheets

$
0
0

This tutorial explains how to import historical stock prices from Yahoo Finance into Google Sheets.

How to Use the File : First make a copy by selecting File > Make a copy. While running the script, Google will ask you to authorize Appscript once.

Then enter the tickers for which you want to download historical information, starting from cell A10.

Specify period, start and end date and then hit "Pull Data" button.
Get Historical Data From Yahoo Finance into Google SheetsOutput of Historical Data from Yahoo Finance

In this tool, you have flexibility to play around with the following arguments -

  • Interval You can select the frequency of historical data for stocks - Minute, Hourly, Daily, Weekly, Monthly.
  • Starting Date Date on which you want historical data starts from
  • End Date Date on which you want historical data ends with. Please note that the end date is not included in the range.
How to Get Real Time Data From Yahoo Finance into Google Sheets

There are two ways to get the real-time price of a stock.

  1. Set start and end date blank. Make sure period is set as 'Daily'.
  2. Set the latest date as the Starting Date and (latest date + 1) as the End Date. For example If you want data for 22nd February, specify 23rd February in the "End Date" argument and 22nd February in the "Starting Date" argument.
How to Get Minute Time Frame Stock Data in Google Sheets

In cell B6, specifying 5 means five-minute time frame when interval is "Minute". In cell B7, specifying 2 means that two days of data are required for a 'minute' or 'hourly' interval.

Please note that the start date and end date arguments are not considered when the interval is set to either "Minute" or "Hourly".
Get Minute Time Frame Stock Data in Google Sheets

In the output, we will have stock data with a five-minute time frame presented in tabular format.

Please note that the macro returns time in local timezone.

Check out this link to download Historical Dividends Data
Fetch Historical Data for Non-US Stocks

For US Stocks Yahoo Finance does not require any suffix added in symbols or tickers. You can use it directly. However suffix needs to be entered for non US stocks. See some of the examples below.

Canadian StocksIndian Stocks
DOL.TORELIANCE.NS
ENGH.TOTCS.NS
AC.TOHCLTECH.NS

Table below shows a complete list of stock exchanges across world and corresponding suffix used for fetching stock quotes from Yahoo Finance.

CountryMarketSuffix
ArgentinaBuenos Aires Stock Exchange (BYMA).BA
AustriaVienna Stock Exchange.VI
AustraliaAustralian Stock Exchange (ASX).AX
BelgiumEuronext Brussels.BR
BrazilSao Paolo Stock Exchange (BOVESPA).SA
CanadaCanadian Securities Exchange.CN
CanadaNEO Exchange.NE
CanadaToronto Stock Exchange (TSX).TO
CanadaTSX Venture Exchange (TSXV).V
ChileSantiago Stock Exchange.SN
ChinaShanghai Stock Exchange.SS
ChinaShenzhen Stock Exchange.SZ
Czech RepublicPrague Stock Exchange Index.PR
DenmarkNasdaq OMX Copenhagen.CO
EgyptEgyptian Exchange Index (EGID).CA
EstoniaNasdaq OMX Tallinn.TL
EuropeEuronext.NX
FinlandNasdaq OMX Helsinki.HE
FranceEuronext Paris.PA
GermanyBerlin Stock Exchange.BE
GermanyBremen Stock Exchange.BM
GermanyDusseldorf Stock Exchange.DU
GermanyFrankfurt Stock Exchange.F
GermanyHamburg Stock Exchange.HM
GermanyHanover Stock Exchange.HA
GermanyMunich Stock Exchange.MU
GermanyStuttgart Stock Exchange.SG
GermanyDeutsche Boerse XETRA.DE
GreeceAthens Stock Exchange (ATHEX).AT
Hong KongHong Kong Stock Exchange (HKEX)***.HK
HungaryBudapest Stock Exchange.BD
IcelandNasdaq OMX Iceland.IC
IndiaBombay Stock Exchange.BO
IndiaNational Stock Exchange of India.NS
IndonesiaIndonesia Stock Exchange (IDX).JK
IrelandEuronext Dublin.IR
IsraelTel Aviv Stock Exchange.TA
ItalyEuroTLX.TI
ItalyItalian Stock Exchange.MI
JapanTokyo Stock Exchange.T
LatviaNasdaq OMX Riga.RG
LithuaniaNasdaq OMX Vilnius.VS
MalaysiaMalaysian Stock Exchange.KL
MexicoMexico Stock Exchange (BMV).MX
NetherlandsEuronext Amsterdam.AS
New ZealandNew Zealand Stock Exchange (NZX).NZ
NorwayOslo Stock Exchange.OL
PortugalEuronext Lisbon.LS
QatarQatar Stock Exchange.QA
RussiaMoscow Exchange (MOEX).ME
SingaporeSingapore Stock Exchange (SGX).SI
South AfricaJohannesburg Stock Exchange.JO
South KoreaKorea Stock Exchange.KS
South KoreaKOSDAQ.KQ
SpainMadrid SE C.A.T.S..MC
Saudi ArabiaSaudi Stock Exchange (Tadawul).SAU
SwedenNasdaq OMX Stockholm.ST
SwitzerlandSwiss Exchange (SIX).SW
TaiwanTaiwan OTC Exchange.TWO
TaiwanTaiwan Stock Exchange (TWSE).TW
ThailandStock Exchange of Thailand (SET).BK
TurkeyBorsa İstanbul.IS
United KingdomLondon Stock Exchange.L
VenezuelaCaracas Stock Exchange.CR
Apps Script

The following script assumes that the period (Daily/Weekly/Monthly) is specified in cell B3, with the start and end dates for which you want stock data in cells B4 and B5. In cells B6 and B7, it is assumed that the time frame and data duration are provided for either a 'minute' or 'hourly' interval data requirement. The tickers should start from cell A10.


function getData() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var inputControls = ss.getSheetByName("Sheet1");
  var outputData = ss.getSheetByName("HistoricalData");
  var symbol;
  var startDate;
  var endDate;
  var period;
  var timeframe;
  var rng;
  var lastRow;

  // Disable screen updating and alerts
  SpreadsheetApp.flush(); // Refresh the spreadsheet

  // Sheet Names
  lastRow = inputControls.getLastRow();

  // Arguments
  var b4Value = inputControls.getRange("B4").getValue();
  var c4Value = inputControls.getRange("B5").getValue();
  var startDate = isNaN(new Date(b4Value).getTime()) ? NaN : Math.floor(new Date(b4Value).getTime() / 1000);
  var endDate = isNaN(new Date(c4Value).getTime()) ? NaN : Math.floor(new Date(c4Value).getTime() / 1000);

  period = inputControls.getRange("B3").getValue();
  timeframe = inputControls.getRange("B6").getValue();
  rng = inputControls.getRange("B7").getValue();
  
  var dateDifference = (new Date(inputControls.getRange("B5").getValue()).getTime() - new Date(inputControls.getRange("B4").getValue()).getTime()) / (1000 * 3600 * 24);

  if (period === "Minute" || period === "Hourly") {
    if (!timeframe || !rng) {
      SpreadsheetApp.getUi().alert("Cells B6 and B7 cannot be empty when Interval is 'Minute' or 'Hourly'");
      return;
    }
  } else {
    if (inputControls.getRange("B4").getValue() && inputControls.getRange("B5").getValue() && dateDifference < 1) {
      SpreadsheetApp.getUi().alert("Date difference must be at least one.");
      return;
    }
  }

  // Period conversion
  switch (period) {
    case "Daily":
      period = "1d";
      break;
    case "Weekly":
      period = "1wk";
      break;
    case "Monthly":
      period = "1mo";
      break;
    case "Minute":
      period = timeframe + "m";
      break;
    case "Hourly":
      period = timeframe + "h";
      break;
  }

  outputData.getRange("A2:H").clearContent();

  // Loop over multiple symbols
  for (var i = 10; i <= lastRow; i++) {
    symbol = inputControls.getRange("A" + i).getValue();
    var offsetCounter = 1;
    extractData(symbol, startDate, endDate, period, rng, offsetCounter, outputData);
  }

  if (outputData) {
    ss.setActiveSheet(outputData); // Set the OutputData sheet as active
    
    // Auto resize columns A to D (1 to 4)
    outputData.autoResizeColumns(1, 4);
  }

}

function extractData(symbols, startDate, endDate, period, rng, offsetCounter, outputData) {
  var tickerURL;

  if ((period.endsWith("m") || period.endsWith("h")) && rng > 0) {
    tickerURL = "https://query2.finance.yahoo.com/v8/finance/chart/" + symbols + "?interval=" + period + "&range=" + rng + "d";
  } else {
    tickerURL = "https://query2.finance.yahoo.com/v8/finance/chart/" + symbols + "?period1=" + startDate + "&period2=" + endDate + "&interval=" + period;
  }

  if (period.endsWith("d") && (isNaN(startDate) && isNaN(endDate))) {
    tickerURL = "https://query2.finance.yahoo.com/v8/finance/chart/" + symbols + "?interval=1d";
  }

  var response = fetchWithRetry(tickerURL, 4);
  var json = JSON.parse(response.getContentText());
  
  if (!json.chart.result || json.chart.result.length === 0) {
    Logger.log("No data found for: " + symbols);
    return; // No data found for the given symbol
  }
  
  var meta = json.chart.result[0].meta;
  var quote = json.chart.result[0].indicators.quote[0];
  var timestamps = json.chart.result[0].timestamp;
  var adjCloseData = json.chart.result[0].indicators.adjclose ? json.chart.result[0].indicators.adjclose[0].adjclose : [];

  var combinedData = [];
  
  for (var i = 0; i < quote.open.length; i++) {
    var row = [];
    row[0] = new Date(timestamps[i] * 1000).toLocaleString("en-US", {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      hour12: false,
    }).replace(",", "").replace(/\//g, "-");

    row[1] = quote.open[i];
    row[2] = quote.high[i];
    row[3] = quote.low[i];
    row[4] = quote.close[i];
    row[5] = adjCloseData.length > 0 ? adjCloseData[i] : ""; // Use adjCloseData if available
    row[6] = quote.volume[i];
    combinedData.push(row);
  }

  // Find the last row and write data
  var lastRow = outputData.getLastRow();
  outputData.getRange(lastRow + 1, 1, combinedData.length, combinedData[0].length).setValues(combinedData);
  outputData.getRange(lastRow + 1, 8, combinedData.length, 1).setValue(symbols); // Add the symbol in column H
}

function fetchWithRetry(tickerURL, maxRetries) {
  var attempts = 0;
  var success = false;
  var response;

  while (attempts < maxRetries && !success) {
    try {
      response = UrlFetchApp.fetch(tickerURL); // Attempt to fetch the URL
      success = true; // If fetch is successful, exit the loop
    } catch (error) {
      attempts++;
      Logger.log("Attempt " + attempts + " failed: " + error.message);

      // Optionally, introduce a delay between retries (e.g., 2 seconds)
      Utilities.sleep(2000);
    }
  }

  if (success) {
    return response;
  } else {
    throw new Error("Failed to fetch after " + maxRetries + " attempts.");
  }
}

Viewing all articles
Browse latest Browse all 97

Latest Images

Trending Articles



Latest Images