Last active
February 28, 2021 02:03
-
-
Save fcfort/ad20f4119e781ad4a6b5582f4666695f to your computer and use it in GitHub Desktop.
Custom function for Google Spreadsheets App Scripts for querying NYSaves.org prices
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _ = Underscore.load(); | |
var NYSaves = {}; | |
NYSaves.currentPriceUrlBase = 'https://www.nysaves.org/nytpl/fund/details.cs?fundId='; | |
NYSaves.historyUrl = 'https://www.nysaves.org/nytpl/fund/priceHistorySearch.cs'; | |
/** | |
* NOTE: NySaves will not return prices for weekend dates. | |
* @private | |
*/ | |
function _getPriceForRange(tickerId, startDate, endDate) { | |
// POST data: fundId=1003014&startDate=05%2F03%2F2016&endDate=05%2F03%2F2016 | |
var response = _fetchUrlWithCookies(NYSaves.historyUrl, { | |
method: 'post', | |
payload: { | |
'fundId': tickerId + "", | |
'startDate': _dateToStringNySaves(startDate), | |
'endDate': _dateToStringNySaves(endDate) | |
} | |
}); | |
var textContent = response.getContentText(); | |
Logger.log('Found textContent %s', textContent); | |
// And return the first price. | |
var found = textContent.match(/\$\d+.\d+/g); | |
// Strip $ symbol | |
found = _.map(found, function(price) { | |
return price.replace('$',''); | |
}); | |
Logger.log('Found prices %s', found); | |
return found; | |
} | |
/** | |
* Looks five days back from the supplied date and returns the | |
* latest price found. This is so that if there is a holiday or weekend, we | |
* still return a price (albeit potentially stale) for that date. | |
*/ | |
NYSaves.getLatestPriceForDate = function(tickerId, date) { | |
return _.last(_getPriceForRange(tickerId, Util.getDaysAgo(date, 5), date)); | |
} | |
/** | |
* @private | |
*/ | |
function _dateToStringNySaves(date) { | |
var mon = Util.padDate(date.getMonth()+1); | |
var day = Util.padDate(date.getDate()); | |
return mon + '/' + day + '/' + date.getYear(); | |
} | |
/** | |
* Gets current price of NYSaves.org ticker | |
* @private | |
*/ | |
function _getNySavesPrice(tickerId) { | |
var url = NYSaves.currentPriceUrlBase + tickerId; | |
// We make another request to get the page content with the cookie detection cookie. | |
var response = _fetchUrlWithCookies(url, {followRedirects: false}); | |
var textContent = response.getContentText(); | |
// And return the first price, stripping $ symbol. | |
return textContent.match(/\$\d+.\d+/)[0].replace('$',''); | |
} | |
/** | |
* Makes two requests to a URL. The first request is to check for a cookie | |
* and then store it. The second request is to the same URL with that cookie | |
* in the header. This is a workaround for sites (like NYSaves.org) with | |
* cookie detection. | |
* @private | |
*/ | |
function _fetchUrlWithCookies(url, data) { | |
// We need to make an initial request because NYSaves.org has a dumb cookie | |
// detection system. | |
var initialResponse = UrlFetchApp.fetch(url, data); | |
var headers = initialResponse.getHeaders(); | |
var cookies = headers['Set-Cookie']; | |
data['headers'] = {Cookie: cookies}; | |
// We make another request to get the page content with the cookie detection cookie. | |
return UrlFetchApp.fetch(url, data); | |
} | |
/** | |
* Returns the latest price of a NY Saves ticker ID. | |
* | |
* @param {String} tickerId NYSaves.org ticker ID | |
* @customfunction | |
*/ | |
function NYSAVES_PRICE(tickerId) { | |
return _getNySavesPrice(tickerId); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment