I'm trying to get historical stock prices from the Polygon.io endpoint on the ex-dividend and the day before the ex-dividend date and map those values to new columns in a panda's dataframe.
I have a separate class that populates the prior business day in events when the prior business date falls within a trading holiday as (BDay).
I am also removing instances where the response object from Polygon does not have two results.
When running the code below, I get a TypeError: 'NoneType' object is not iterable on the zip await portion of the code. I've tried printing the results of the calls and see that I am correctly getting float values from the asynchronous function. I've also tried printing the types to confirm that the nonetype isn't being set before the main function attempts to extract the data from the tuple. What am I doing wrong?
Full disclosure, I'm new to using asych. Also, the majority of this work is in a Jupyter notebook so I'm not sharing the full code base here, just the section that is generating the error.
from datetime import datetime
from pandas.tseries.offsets import BDay
async def get_history(ticker, prior_business_date, ex_dividend_date):
'''
Receives the ticker, prior business date and ex-dividend date from the caller as a string
First checks to see if the prior business date (date before Ex-Dividend is a holidy
If the date is a holiday, subtracts one day from prior business date
Function then assigns to value x the prior candlestick date for the corrected date
If the date IS NOT a holiday, the function gets the prior candlestick data based on the prior business date
Function also returns candlestick data on the ex-dividend date before returning asynchronously to the caller
'''
if prior_business_date in get_trading_close_holidays(int(prior_business_date.split('-')[0])):
#set the prior_business date to datetime object
#deduct 1 day from prior_business_date to get useable data
prior_business_date = datetime.strftime(datetime.strptime(prior_business_date,'%Y-%m-%d').date() - BDay(1), '%Y-%m-%d')
#print(prior_business_date) #debug
url = 'https://api.polygon.io/v2/aggs/ticker/{}/range/1/day/{}/{}?sort=dsc&limit=10'.format(ticker, prior_business_date, ex_dividend_date)
r = requests.get(url, headers=headers).json()
#print(r['ticker'], r['queryCount']) #debug
if (r['queryCount'] < 2) or (r == None):
pass
else:
#print(type(r)) #debug
x = r['results'][0]['c'] #first data set in results is prior date; get only close
y = r['results'][1]['c'] #second data set in results is ex-dividend date get only close
#print(type(x),type(y)) #debug
return x, y
async def main():
high_volume['prior_biz_close'], high_volume['xdiv_close'] = zip(*await asyncio.gather(*map(get_history,high_volume['ticker'], high_volume['prior_business_date'], high_volume['ex_dividend_date'])))
asyncio.run(main())
Here is the response I receive when attempting to run the code:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In [52], line 56
53 high_volume['prior_biz_close'], high_volume['xdiv_close'] = zip(*await asyncio.gather(*map(get_history,high_volume['ticker'], high_volume['prior_business_date'], high_volume['ex_dividend_date'])))
54 #*(get_history(x,y,z) for x,y,z in (df['ticker'], df['prior_business_date'], df['ex_dividend_date']))))
---> 56 asyncio.run(main())
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/nest_asyncio.py:35, in _patch_asyncio.<locals>.run(main, debug)
33 task = asyncio.ensure_future(main)
34 try:
---> 35 return loop.run_until_complete(task)
36 finally:
37 if not task.done():
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/nest_asyncio.py:90, in _patch_loop.<locals>.run_until_complete(self, future)
87 if not f.done():
88 raise RuntimeError(
89 'Event loop stopped before Future completed.')
---> 90 return f.result()
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/futures.py:201, in Future.result(self)
199 self.__log_traceback = False
200 if self._exception is not None:
--> 201 raise self._exception
202 return self._result
File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/tasks.py:256, in Task.__step(***failed resolving arguments***)
252 try:
253 if exc is None:
254 # We use the `send` method directly, because coroutines
255 # don't have `__iter__` and `__next__` methods.
--> 256 result = coro.send(None)
257 else:
258 result = coro.throw(exc)
Cell In [52], line 53, in main()
52 async def main():
---> 53 high_volume['prior_biz_close'], high_volume['xdiv_close'] = zip(*await asyncio.gather(*map(get_history,high_volume['ticker'], high_volume['prior_business_date'], high_volume['ex_dividend_date'])))
TypeError: 'NoneType' object is not iterable
!!!!SOLVED!!!!
I resolved this by aggregating the data the I was sending to the asynchronous function into one data set and then parsing that data within the function instead of trying to send multiple parameters from async main.
Here's what I did:
I recognize I didn't provide a great deal of context on my earlier ask, yet here's my code in the event it helps anyone else.
from datetime import datetime
from pandas.tseries.offsets import BDay
prior_biz_close = []
xdiv_close = []
to_drop = []
'''
to_drop likely includes many days where the business day provided falls on a weekend. Need to update to
allow for conversion of incorrect days to working days.
'''
async def get_history(data, idx):
'''
Receives the ticker, prior business date and ex-dividend date from the caller as a string
First checks to see if the prior business date (date before Ex-Dividend is a holidy
If the date is a holiday, subtracts one day from prior business date
Function then assigns to value x the prior candlestick date for the corrected date
If the date IS NOT a holiday, the function gets the prior candlestick data based on the prior business date
Function also returns candlestick data on the ex-dividend date before returning asynchronously to the caller
'''
#print(data)
if data[1] in get_trading_close_holidays(int(data[1].split('-')[0])):
#set the prior_business date to datetime object
#deduct 1 day from prior_business_date to get useable data
data[1] = datetime.strftime(datetime.strptime(data[1],'%Y-%m-%d').date() - BDay(1), '%Y-%m-%d')
url = 'https://api.polygon.io/v2/aggs/ticker/{}/range/1/day/{}/{}?sort=dsc&limit=10'.format(data[0], data[1], data[2])
r = requests.get(url, headers=headers).json()
if (r['queryCount'] < 2) or (r == None):
to_drop.append(idx)
pass
else:
#print(type(r))
prior_biz_close.append(r['results'][0]['c']) #first data set in results is prior date; get only close
xdiv_close.append(r['results'][1]['c']) #second data set in results is ex-dividend date get only close
#print(type(x),type(y))
async def main():
result = [(ticker, prior_business_date, ex_dividend_date) for (ticker, prior_business_date, ex_dividend_date) in zip(high_volume['ticker'], high_volume['prior_business_date'], high_volume['ex_dividend_date'])]
for i in result:
await get_history(list(i), result.index(i))
asyncio.run(main())