简体   繁体   中英

How to make yahoo finance YQL query more than 1 year stock data?

I'm using a tableau web connector to download stock price. The source code is following:

<html>
<meta http-equiv="Cache-Control" content="no-store" />
<head>
  <title>Stock Quote Connector-Tutorial</title>
  <script src="https://connectors.tableau.com/libs/tableauwdc-1.1.1.js" type="text/javascript"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>

  <script type="text/javascript">
  (function() {

    function buildUri(tickerSymbol, startDate, endDate) {
      var startDateStr = getFormattedDate(startDate);
      var endDateStr   = getFormattedDate(endDate);
      var queryStatement = 'select * from yahoo.finance.historicaldata where symbol = "' +
                            tickerSymbol +
                           '" and startDate = "' + startDateStr +
                           '" and endDate = "' + endDateStr + '"';
      var uri = 'http://query.yahooapis.com/v1/public/yql?q=' +
                encodeURIComponent(queryStatement) +
                "&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json";
      return uri;
    }

    function getFormattedDate(date) {
        // Return a date in the format YYYY-MM-DD
        return date.getUTCFullYear()  +
               '-' +
               makeTwoDigits(date.getUTCMonth() + 1) +
               '-' +
               makeTwoDigits(date.getUTCDate());
    }

    function makeTwoDigits(num) {
       // Pad a digit to be two digits with leading zero
       return num <= 9 ? "0" + num.toString() : num.toString();
    }

    var myConnector = tableau.makeConnector();

    myConnector.getColumnHeaders = function() {
        var fieldNames = ['Ticker', 'Day', 'Close'];
        var fieldTypes = ['string', 'date', 'float'];
        tableau.headersCallback(fieldNames, fieldTypes);
    }

    myConnector.getTableData = function(lastRecordToken) {
        var dataToReturn = [];
        var hasMoreData = false;

        // Get parameter values and build YQL query
        var ticker = tableau.connectionData;
        var endDate = new Date();
        var startDate = new Date();
        startDate.setYear(endDate.getFullYear() - 1);
        //startDate.setYear(startDate.getFullYear() - 1);
        //startDate.setYear(startDate.getFullYear() - 1);
        //startDate.setYear(startDate.getFullYear() - 1);
        var connectionUri = buildUri(ticker, startDate, endDate);

        var xhr = $.ajax({
          url: connectionUri,
          dataType: 'json',
          success: function (data) {
              if (data.query.results) {
                var quotes = data.query.results.quote;
                var ii;
                for (ii = 0; ii < quotes.length; ++ii) {
                    var entry = {'Ticker': quotes[ii].Symbol,
                                 'Day': quotes[ii].Date,
                                 'Close': quotes[ii].Close};
                    dataToReturn.push(entry);
                }
                tableau.dataCallback(dataToReturn, lastRecordToken, false);
              }
              else {
                  tableau.abortWithError("No results found for ticker symbol: " + ticker);
              }
          },
          error: function (xhr, ajaxOptions, thrownError) {
              tableau.log("Connection error: " + xhr.responseText + "\n" + thrownError);
              tableau.abortWithError("Error while trying to connect to the Yahoo stock data source.");
          }
        });
      }
      tableau.registerConnector(myConnector);
  })();

  $(document).ready(function() {
    $("#submitButton").click(function() {
      var tickerSymbol = $('#ticker').val().trim();
      if (tickerSymbol) {
        tableau.connectionName = "Stock Data for " + tickerSymbol;
        tableau.connectionData = tickerSymbol;
        tableau.submit();
      }
    });
  });
</script>
</head>
<body>
  <p>Enter a stock ticker symbol: <input type="text" id="ticker" /></p>
  <p><button type="button" id="submitButton">Get the Data</button></p>
  </body>
</html>

The code is workable when we just want to download 1 year data, but if we change the time longer than 1 year( enddate.year - startdate.year > 1 ), it is not workable. After debugging the code, I found the issue comes from YQL query:

http://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.historicaldata where symbol = "AAPL" and startDate = "2014-08-24" and endDate = "2016-11-23"&env=http%3A%2F%2Fdatatables.org%2Falltables.env&format=json

when startDate = "2014-08-24" and endDate = "2016-11-23" is longer than 15 month, YQL will return null. I'm trying to fix this issue. If it is python or java, the problem is not hard, first check whether the duration is longer than 1 year, if so, get 1 year result and do the same for rest n-1 year. But this tableau code makes me stuck with it. I have to make the code workable with tableau, which makes me unable to proceed due to lack of knowledge about both js and tableau.

Can any one advise on this issue? My objective is to make the code workable for >10 years for stock symbol like AAPL.

Thanks in advance.

I don't believe YQL supports queries for longer than 15 months or so. Limits like these are fairly common when working with APIs. What you want to do from a web data connector standpoint is to implement paging.

The high level idea is that your getTableData function of your WDC will execute multiple times, and each time, it will gather a single page of data, which is then passed to Tableau. For example, here's how you could get multiple years worth of data in your example:

myConnector.getTableData = function(lastRecordToken) {
    var dataToReturn = [];
    var hasMoreData = false;

    // Get parameter values and build YQL query
    var ticker = tableau.connectionData;
    var endDate = new Date();
    var startDate = new Date();

    var maxYear = 5;        
    var yearOffset = lastRecordToken || 0;
    endDate.setYear(endDate.getFullYear() - (yearOffset));
    startDate.setYear(endDate.getFullYear() - 1);

    var connectionUri = buildUri(ticker, startDate, endDate);

    var xhr = $.ajax({
      url: connectionUri,
      dataType: 'json',
      success: function (data) {
          if (data.query.results) {
            var quotes = data.query.results.quote;
            var ii;
            for (ii = 0; ii < quotes.length; ++ii) {
                var entry = {'Ticker': quotes[ii].Symbol,
                             'Day': quotes[ii].Date,
                             'Close': quotes[ii].Close};
                dataToReturn.push(entry);
            }

            var hasMoreData = !(yearOffset == maxYear);
            tableau.dataCallback(dataToReturn, yearOffset + 1, hasMoreData)
          }
          else {
              tableau.abortWithError("No results found for ticker symbol: " + ticker);
          }
      },
      error: function (xhr, ajaxOptions, thrownError) {
          tableau.log("Connection error: " + xhr.responseText + "\n" + thrownError);
          tableau.abortWithError("Error while trying to connect to the Yahoo stock data source.");
      }
    });
  }
  tableau.registerConnector(myConnector);
  })();

This example uses the two extra parameters of the dataCallback function to implement paging. The documentation for paging in v1 of the web data connector API can be found here: http://onlinehelp.tableau.com/current/api/wdc/en-us/help.htm#WDC/wdc_paging.htm%3FTocPath%3DAdditional%2520Concepts%7C_____2

Additionally, if you are able to use v2 of the WDC API (usable in Tableau 10 and later), I would highly recommend it. The paging model in V2 is more flexible and easier to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM