-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
a possible fix to historical quotes #48
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,9 @@ | |
# py2 | ||
from urllib2 import Request, urlopen | ||
from urllib import urlencode | ||
from datetime import datetime, timedelta | ||
import json | ||
import re | ||
|
||
|
||
def _request(symbol, stat): | ||
|
@@ -470,32 +473,32 @@ def get_historical_prices(symbol, start_date, end_date): | |
Returns a nested dictionary (dict of dicts). | ||
outer dict keys are dates ('YYYY-MM-DD') | ||
""" | ||
epoch = datetime(1970, 1, 1) | ||
p1 = datetime.strptime(start_date, '%Y-%m-%d') | ||
p2 = datetime.strptime(end_date, '%Y-%m-%d') | ||
params = urlencode({ | ||
's': symbol, | ||
'a': int(start_date[5:7]) - 1, | ||
'b': int(start_date[8:10]), | ||
'c': int(start_date[0:4]), | ||
'd': int(end_date[5:7]) - 1, | ||
'e': int(end_date[8:10]), | ||
'f': int(end_date[0:4]), | ||
'g': 'd', | ||
'ignore': '.csv', | ||
'period1': int((p1 - epoch).total_seconds()), | ||
'period2': int((p2 - epoch + timedelta(days=1)).total_seconds()), | ||
'frequency': '1d', | ||
'filter': 'history', | ||
}) | ||
url = 'http://real-chart.finance.yahoo.com/table.csv?%s' % params | ||
url = 'https://finance.yahoo.com/quote/%s/history?%s' % (symbol, params) | ||
req = Request(url) | ||
resp = urlopen(req) | ||
content = str(resp.read().decode('utf-8').strip()) | ||
daily_data = content.splitlines() | ||
content = resp.read() | ||
quotes = re.findall('{"date":\d+[^}]+}', content) | ||
hist_dict = dict() | ||
keys = daily_data[0].split(',') | ||
for day in daily_data[1:]: | ||
day_data = day.split(',') | ||
date = day_data[0] | ||
hist_dict[date] = \ | ||
{keys[1]: day_data[1], | ||
keys[2]: day_data[2], | ||
keys[3]: day_data[3], | ||
keys[4]: day_data[4], | ||
keys[5]: day_data[5], | ||
keys[6]: day_data[6]} | ||
for quote in quotes: | ||
j = json.loads(quote) | ||
for k in ('open', 'close', 'high', 'low', 'unadjclose'): | ||
j[k] = "%.2f" % j[k] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. starforever I do not get that error either in my own tests or running the test suite. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm using Python 2.7. I'm not sure if you are using the exact same arguments. It only happens for some specific symbol and time ranges. I haven't got time to dive deep on this. So no idea how it happens. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm guessing it doesn't throw the error in the tests since the specific arguments are not used in tests. I silently caught the exception and it worked fine then. But I think this is only a quick fix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok I see the issue, when the quote/date range includes a split or dividend the pattern match pulls it in but there is no 'open', 'close' etc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yahoo's current data does not include un-adjusted prices anymore |
||
d = timedelta(seconds=j["date"]) | ||
# these keys are for backwards compatibility | ||
for key in j.keys(): | ||
j[key.capitalize()] = j[key] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im getting an error running the tests on this line. not sure what you are trying to do here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please take a look at #52 |
||
# in the old api "Close" was the unadj close | ||
j['Close'] = j['unadjclose'] | ||
j['Adj Close'] = j['close'] | ||
date = epoch + d | ||
hist_dict[date.date().isoformat()] = j | ||
return hist_dict |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you would need to call
.decode()
oncontent
before passing it tore.findall
.It seems that you would also have to check if it's Python 3 and call
.decode()
only if it's Python 3. There may be other, more elegant, way of doing this -- I'm not used to port Python code.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes adding
.decode('utf-8').strip()
seems to get past this