This tool is comprised of a few parts. All of the code used in these posts can be purchased in a single spreadsheet if you’d like link to SMA Screener in store
- Part I: Pulling stock ticker lists: S&P 500 & Dow Jones Industrial Average Tickers
- Part II: Pulling OHLC data from Yahoo Finance
- Part III: Generating Buy/Sell Signals Using Technical Indicators
- Part IV: Scheduling & Part V: Notifications
We are going to pull OHLC (open, high, low, close) data using Yahoo Finance for a list of tickers. The code below pulls the data for the past 10 days by ticker. This code will leverage another function fetchStockData() that will be used a few times with this tool
function fetchStockData(symbol, startDate, endDate) {
var startDateUnix = Math.floor(startDate.getTime() / 1000); // Convert to Unix timestamp in seconds
var endDateUnix = Math.floor(endDate.getTime() / 1000); // Convert to Unix timestamp in seconds
var url =
"https://query1.finance.yahoo.com/v7/finance/chart/" +
symbol +
"?period1=" +
startDateUnix +
"&period2=" +
endDateUnix +
"&interval=1d&indicators=quote&includeTimestamps=true";
var response = UrlFetchApp.fetch(url);
var data = JSON.parse(response.getContentText());
if (data.chart.result.length === 0) {
return []; // Return an empty array if no data is available
}
var timestamps = data.chart.result[0].timestamp;
var ohlcData = data.chart.result[0].indicators.quote[0];
var stockData = [];
for (var i = 0; i < timestamps.length; i++) {
var date = new Date(timestamps[i] * 1000);
var open = ohlcData.open[i].toFixed(2);
var high = ohlcData.high[i].toFixed(2);
var low = ohlcData.low[i].toFixed(2);
var close = ohlcData.close[i].toFixed(2);
stockData.push({ date: date, open: open, high: high, low: low, close: close });
}
return stockData;
}
function pullOHLCData() {
var startTime = new Date(); // Record the start time
var ss = SpreadsheetApp.getActiveSpreadsheet();
var stockListSheet = ss.getSheetByName("Stock List");
var stockList = stockListSheet.getRange("A:A").getValues().flat().filter(Boolean);
var ohlcSheet = ss.getSheetByName("OHLC");
if (!ohlcSheet) {
ohlcSheet = ss.insertSheet("OHLC");
} else {
ohlcSheet.clear();
}
var startDate = new Date();
startDate.setDate(startDate.getDate() - 200); // 10 days
startDate.setHours(0, 0, 0, 0); // Set the time to the beginning of the day
var headerRow = ["Symbol", "Date", "Open", "High", "Low", "Close"];
ohlcSheet.getRange(1, 1, 1, headerRow.length).setValues([headerRow]);
// Apply formatting to the first row
var firstRowRange = ohlcSheet.getRange(1, 1, 1, headerRow.length);
firstRowRange.setFontWeight("bold");
firstRowRange.setHorizontalAlignment("center");
// Freeze the first row
ohlcSheet.setFrozenRows(1);
var ohlcData = [];
for (var i = 0; i < stockList.length; i++) {
var symbol = stockList[i];
try {
var stockData = fetchStockData(symbol, startDate, new Date());
Logger.log(stockData);
for (var j = 0; j < stockData.length; j++) {
var date = stockData[j].date;
var open = stockData[j].open;
var high = stockData[j].high;
var low = stockData[j].low;
var close = stockData[j].close;
ohlcData.push([symbol, date, open, high, low, close]);
}
} catch (error) {
console.error("Error fetching OHLC data for symbol:", symbol, error);
}
}
if (ohlcData.length > 0) {
var range = ohlcSheet.getRange(2, 1, ohlcData.length, ohlcData[0].length);
range.setValues(ohlcData);
}
var endTime = new Date(); // Record the end time
var elapsedTime = (endTime - startTime) / 1000; // Calculate the elapsed time in seconds
Logger.log("Time taken: " + elapsedTime + " seconds");
// Select the "OHLC" sheet
ss.setActiveSheet(ohlcSheet);
}
Sample Output

Please note: Google Apps Script has a limitation that it can’t run for more than 6 mins. The process above will run fine for the tickers in the Dow Jones Industrial Averages, but hits the time limit when running for the S&P 500.