Google Spreadsheets Get Full Quotes Script

It seems that this week I am on a roll for development.

As I was reading Tim Grittani‘s latest post on his blog, I was drawn to learn how to properly use the available tools at my disposal; one of these tools, as was pointed out by Tim, is spreadsheets used to track stocks and perform statistical analysis.

I found the process to be rather time consuming when it comes to adding stocks and manually entering all the data that is related to it; I’m lazy and that’s why I got an engineering degree: automate it so you don’t have to ever do it again. And so I did.

Below you will find a Google spreadsheets script that gets stock data directly from Yahoo finance through the free YQL interface. I will not go over the installation, but you can check out this post and video that gives you a fairly good idea on how to do it .

Here are some screenshots of the installation process:

01 02 03 04 05 06 07 08 09 10 11 12 13

This will need to be added to every spreadsheet that you want the script active.

For more information, check out my GitHub.

Updated to include Historical data for Date Range (set in script).

/**
 * Created by Jamil on 12/8/2014.
 *
 * Based and improved from https://gist.github.com/markandey/5632923
 *
 *
 */

/********************************************
 * TODO:
 *
 * - Implement keystats data query and add columns - https://developer.yahoo.com/yql/console/?q=show%20tables&env=store://datatables.org/alltableswithkeys#h=SELECT+*+FROM+yahoo.finance.keystats+WHERE+symbol%3D'AAPL'
 *
 *
 ********************************************/

function onOpen() {
    var menu = SpreadsheetApp.getUi().createAddonMenu(); // Or DocumentApp or FormApp.
    menu.addItem('Get Quotes for Active Range', 'pullData');
    menu.addToUi();
}

function pullData(){

    /*************************************
     * Display Titles - Change below
     *************************************/
    var display_titles = true; // true to display titles (default), false to remove titles
    /*************************************
     * Display Titles - Change Above
     *************************************/

    var sheet = SpreadsheetApp.getActiveSheet();
    var range = sheet.getActiveRange();

    var data = range.getValues(); //range.getValues();

    //var data = r1;

    // Query string
    var query = "";
    var lines = [];
    var j=0;

    // Loop through values - get first column only
    for (var i=0; i < data.length; i++){
        symbol = data[i][0];

        // Validate data to be a symbol
        if(symbol.match(/\w{3,5}/)){
            query += "%22"+symbol.capitalize()+"%22%2C"; //Add symbol to query
            lines[j]=i;
            j++;
        }
    }
    query = query.replace(/\%2C$/g,"");

    scol = range.getLastColumn();//cr2.getColumn();
    srow = range.getRow();//cr2.getRow();

    Logger.log(scol);
    Logger.log(srow);

    var url="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("+query+")&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
    var response = UrlFetchApp.fetch(url);
    var json=JSON.parse(response.getContentText());

    var fields = getQuoteFields();

    // Displays the titles above the selected range
    if(display_titles){
        trow = srow - 1;
        if(trow > 0){
            dcol=0;
            for(i=0; i<fields.length; i++){
                sheet.getRange(trow, scol+dcol).setValue(fields[i]);
                sheet.getRange(trow, scol+dcol).setFontWeight("bold");
                sheet.autoResizeColumn(scol+dcol);
                dcol++;
            }
        }
    }

    // Displays the data collected from Yahoo finance YQL for quotes
    var quotes=json.query.results.quote;

    dcol = 0;
    for(i=0;i<quotes.length;i++){
        row = srow+lines[i];

        dcol = 0;
        // Loop Through selected fields
        for(j=0; j<fields.length; j++){
            var val = quotes[i][fields[j]];

            if(typeof(val) == "string" ){
                val = val.replace(/\+/g,"");
            }

            sheet.getRange(row, scol+dcol++).setValue(val);
        }


    }

    // TODO: Get Historical Data from YQL
    startdate = "2014-12-01";
    enddate = "2014-12-05";
    url="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.historicaldata%20where%20symbol%20in%20("+query+")%20and%20startDate%20%3D%20%22"+startdate+"%22%20and%20endDate%20%3D%20%22"+enddate+"%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=";
    response = UrlFetchApp.fetch(url);
    json=JSON.parse(response.getContentText());

    var hist=json.query.results.quote;
    var symbol_count = range.getValues().length;
    var record_count = json.query.count;
    var rec_per_sym = parseInt(record_count/symbol_count);

    //Logger.log("Records per symbol: "+rec_per_sym);

    fields= getHistoricalFields();

    for(i=0; i<symbol_count; i++){
        offset = i+1;

        ecol = dcol;
        for(j=rec_per_sym*i; j< rec_per_sym*offset; j++){
            row = srow+lines[i];



            // Loop Through selected fields
            for(k=0; k<fields.length; k++){

                // add titles on top
                if(i == 0 && display_titles){
                    trow = srow - 1;
                    if(trow > 0){
                        sheet.getRange(trow, scol+ecol).setValue(fields[k]+" for "+hist[j]["Date"]);
                        sheet.getRange(trow, scol+ecol).setFontWeight("bold");
                        sheet.autoResizeColumn(scol+ecol);
                    }

                }

                val = hist[j][fields[k]];
                sheet.getRange(row, scol+ecol++).setValue(val);
            }



        }




    }//

    // TODO: get Key stats data from YQL
}

function getQuoteFields(){

    i=0;
    fields = [];

    /******************************************
     *
     *  Select the desired fields below
     *  add "//" in front to disable a field as such:
     *  // fields[i++] = "symbol"; // symbol
     *
     *  Fields can be reordered as required by cutting and pasting at a higher/lower position
     *
     *  These are all the fields available on yahoo YQL.
     *  For more info: https://developer.yahoo.com/yql/console/?q=show%20tables&env=store://datatables.org/alltableswithkeys#h=select+*+from+yahoo.finance.quotes+where+symbol+in+(%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22)
     *
     ******************************************/

    fields[i++] = "symbol"; // symbol
    fields[i++] = "Ask"; // Ask
    fields[i++] = "AverageDailyVolume"; // AverageDailyVolume
    fields[i++] = "Bid"; // Bid
    fields[i++] = "AskRealtime"; // AskRealtime
    fields[i++] = "BidRealtime"; // BidRealtime
    fields[i++] = "BookValue"; // BookValue
    fields[i++] = "Change_PercentChange"; // Change_PercentChange
    fields[i++] = "Change"; // Change
    fields[i++] = "Commission"; // Commission
    fields[i++] = "Currency"; // Currency
    fields[i++] = "ChangeRealtime"; // ChangeRealtime
    fields[i++] = "AfterHoursChangeRealtime"; // AfterHoursChangeRealtime
    fields[i++] = "DividendShare"; // DividendShare
    fields[i++] = "LastTradeDate"; // LastTradeDate
    fields[i++] = "TradeDate"; // TradeDate
    fields[i++] = "EarningsShare"; // EarningsShare
    fields[i++] = "ErrorIndicationreturnedforsymbolchangedinvalid"; // ErrorIndicationreturnedforsymbolchangedinvalid
    fields[i++] = "EPSEstimateCurrentYear"; // EPSEstimateCurrentYear
    fields[i++] = "EPSEstimateNextYear"; // EPSEstimateNextYear
    fields[i++] = "EPSEstimateNextQuarter"; // EPSEstimateNextQuarter
    fields[i++] = "DaysLow"; // DaysLow
    fields[i++] = "DaysHigh"; // DaysHigh
    fields[i++] = "YearLow"; // YearLow
    fields[i++] = "YearHigh"; // YearHigh
    fields[i++] = "HoldingsGainPercent"; // HoldingsGainPercent
    fields[i++] = "AnnualizedGain"; // AnnualizedGain
    fields[i++] = "HoldingsGain"; // HoldingsGain
    fields[i++] = "HoldingsGainPercentRealtime"; // HoldingsGainPercentRealtime
    fields[i++] = "HoldingsGainRealtime"; // HoldingsGainRealtime
    fields[i++] = "MoreInfo"; // MoreInfo
    fields[i++] = "OrderBookRealtime"; // OrderBookRealtime
    fields[i++] = "MarketCapitalization"; // MarketCapitalization
    fields[i++] = "MarketCapRealtime"; // MarketCapRealtime
    fields[i++] = "EBITDA"; // EBITDA
    fields[i++] = "ChangeFromYearLow"; // ChangeFromYearLow
    fields[i++] = "PercentChangeFromYearLow"; // PercentChangeFromYearLow
    fields[i++] = "LastTradeRealtimeWithTime"; // LastTradeRealtimeWithTime
    fields[i++] = "ChangePercentRealtime"; // ChangePercentRealtime
    fields[i++] = "ChangeFromYearHigh"; // ChangeFromYearHigh
    fields[i++] = "PercebtChangeFromYearHigh"; // PercebtChangeFromYearHigh
    fields[i++] = "LastTradeWithTime"; // LastTradeWithTime
    fields[i++] = "LastTradePriceOnly"; // LastTradePriceOnly
    fields[i++] = "HighLimit"; // HighLimit
    fields[i++] = "LowLimit"; // LowLimit
    fields[i++] = "DaysRange"; // DaysRange
    fields[i++] = "DaysRangeRealtime"; // DaysRangeRealtime
    fields[i++] = "FiftydayMovingAverage"; // FiftydayMovingAverage
    fields[i++] = "TwoHundreddayMovingAverage"; // TwoHundreddayMovingAverage
    fields[i++] = "ChangeFromTwoHundreddayMovingAverage"; // ChangeFromTwoHundreddayMovingAverage
    fields[i++] = "PercentChangeFromTwoHundreddayMovingAverage"; // PercentChangeFromTwoHundreddayMovingAverage
    fields[i++] = "ChangeFromFiftydayMovingAverage"; // ChangeFromFiftydayMovingAverage
    fields[i++] = "PercentChangeFromFiftydayMovingAverage"; // PercentChangeFromFiftydayMovingAverage
    fields[i++] = "Name"; // Name
    fields[i++] = "Notes"; // Notes
    fields[i++] = "Open"; // Open
    fields[i++] = "PreviousClose"; // PreviousClose
    fields[i++] = "PricePaid"; // PricePaid
    fields[i++] = "ChangeinPercent"; // ChangeinPercent
    fields[i++] = "PriceSales"; // PriceSales
    fields[i++] = "PriceBook"; // PriceBook
    fields[i++] = "ExDividendDate"; // ExDividendDate
    fields[i++] = "PERatio"; // PERatio
    fields[i++] = "DividendPayDate"; // DividendPayDate
    fields[i++] = "PERatioRealtime"; // PERatioRealtime
    fields[i++] = "PEGRatio"; // PEGRatio
    fields[i++] = "PriceEPSEstimateCurrentYear"; // PriceEPSEstimateCurrentYear
    fields[i++] = "PriceEPSEstimateNextYear"; // PriceEPSEstimateNextYear
    fields[i++] = "Symbol"; // Symbol
    fields[i++] = "SharesOwned"; // SharesOwned
    fields[i++] = "ShortRatio"; // ShortRatio
    fields[i++] = "LastTradeTime"; // LastTradeTime
    fields[i++] = "TickerTrend"; // TickerTrend
    fields[i++] = "OneyrTargetPrice"; // OneyrTargetPrice
    fields[i++] = "Volume"; // Volume
    fields[i++] = "HoldingsValue"; // HoldingsValue
    fields[i++] = "HoldingsValueRealtime"; // HoldingsValueRealtime
    fields[i++] = "YearRange"; // YearRange
    fields[i++] = "DaysValueChange"; // DaysValueChange
    fields[i++] = "DaysValueChangeRealtime"; // DaysValueChangeRealtime
    fields[i++] = "StockExchange"; // StockExchange
    fields[i++] = "DividendYield"; // DividendYield
    fields[i++] = "PercentChange"; // PercentChange
    //*/
    return fields;

}

function getHistoricalFields(){

    i=0;
    fields = [];

    /******************************************
     *
     *  Select the desired fields below
     *  add "//" in front to disable a field as such:
     *  // fields[i++] = "symbol"; // symbol
     *
     *  Fields can be reordered as required by cutting and pasting at a higher/lower position
     *
     *  These are all the fields available on yahoo YQL.
     *  For more info: https://developer.yahoo.com/yql/console/?q=show%20tables&env=store://datatables.org/alltableswithkeys#h=select+*+from+yahoo.finance.historicaldata+where+symbol+%3D+%22AAPL%22+and+startDate+%3D+%222014-12-01%22+and+endDate+%3D+%222014-12-05%22
     *
     ******************************************/

    //fields[i++] = "Symbol"; // Symbol
    //fields[i++] = "Date"; // Date
    fields[i++] = "Open"; // Open
    fields[i++] = "High"; // High
    fields[i++] = "Low"; // Low
    fields[i++] = "Close"; // Close
    fields[i++] = "Volume"; // Volume
    fields[i++] = "Adj_Close"; // Adj_Close
    //*/

    return fields;


}




String.prototype.capitalize = function() {
    return this.replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
};

 

XSLT Plugin by BMI Calculator