我尝试使用polygon.io下载股票代码两个日期之间的所有分钟条。根据他们的API,API限制为50000个结果。
从他们的Github问题中,我发现了以下comment:
聚合端点没有用于分页的next_url。相反,如果响应中的消息超过50,000条,则需要查询较小时间范围的数据。我建议每次查询查询1个月的分钟条。
这是我目前所做的:
返回符号列表:
from polygon import RESTClient
import os.path
from IPython.display import display
import pandas as pd
key = ''
all_tickers = []
df_list = []
final_df = []
from_ = '2021-05-01'
to = '2022-12-01'
def get_tickers():
with RESTClient(key) as client:
next_url = None
while True:
if next_url is None:
tickers = client.reference_tickers_v3(type="CS")
else:
tickers = client._handle_response("ReferenceTickersV3ApiResponse", next_url, {})
all_tickers.extend(tickers.results)
if hasattr(tickers, 'next_url'):
next_url = tickers.next_url
else:
break
file_name = 'tickers.csv'
if not os.path.exists(file_name):
get_tickers()
all_tickers_copy = pd.DataFrame(all_tickers)
all_tickers_copy.to_csv(file_name, index=False)
else:
all_tickers = pd.read_csv(file_name)
all_tickers = all_tickers['ticker']
返回一个列表,其中包含from_
和to
日期之间月份的开始和结束日期:
import pandas as pd
start_date, end_date = from_, to
dtrange = pd.date_range(start=start_date, end=end_date, freq='d')
months = pd.Series(dtrange .month)
starts, ends = months.ne(months.shift(1)), months.ne(months.shift(-1))
df = pd.DataFrame({'month_starting_date': dtrange[starts].strftime('%Y-%m-%d'),
'month_ending_date': dtrange[ends].strftime('%Y-%m-%d')})
# as a list of lists:
months = [df.columns.values.tolist()] + df.values.tolist()
months = pd.DataFrame(months)
然后,我有一个函数循环遍历我的符号,并在from_
和to
之间的每个月发出API请求:
def get_daily_agg(from_, to, ticker):
with RESTClient(key) as client:
folder_name = 'intraday_bars_gapped_new'
final_df = pd.DataFrame([])
try:
# skip the header and loop through the rows
for index, row in months[1:].iterrows():
# save the start and end dates as variables
from_ = row[0]
to = row[1]
print(f'{to} and {from_}')
r = client.stocks_equities_aggregates(ticker, 1, "minute", from_, to, unadjusted=False, limit='50000')
print(f'downloading {ticker} from {from_} to {to}')
df = pd.DataFrame(r.results)
df = df[['t','v','o','c','h','l', 'vw']]
df.columns = ['datetime', 'volume','open','close','high', 'low', 'vwap']
df['datetime'] = pd.to_datetime(df['datetime'],unit='ms')
df['time'] = df['datetime'].dt.strftime("%H:%M:%S")
df['date'] = df['datetime'].dt.strftime("%Y-%m-%d")
final_df.append(df)
except:
print(f'nothing found for {ticker} from {from_} to {to}')
pass
if not os.path.exists(folder_name):
os.makedirs(folder_name)
final_df.to_csv('{}/{}.csv'.format(folder_name, ticker), index=False)
else:
final_df.to_csv('{}/{}.csv'.format(folder_name, ticker), index=False)
import glob
from pathlib import Path
folder = "daily_bars_filtered/*.csv"
for fname in glob.glob(folder)[:20]:
ticker = Path(fname).stem
get_daily_agg(from_, to, ticker)
我的问题是-如何正确分页的结果从polygon.ioAPI?
1条答案
按热度按时间ttcibm8c1#
我认为有两种方法可以处理www.example.com Python RestAPI中缺少“next_url”的问题polygon.io:
按日期范围划分的多个请求
正如你已经注意到的,你可以把你的请求分成不同的日期范围,这样每个请求返回的结果就少于50,000个。这种方法的主要问题是,与使用“next_url”光标相比,它会大大增加你需要发出的请求的数量,特别是考虑到大多数polygon.io帐户都受到他们在给定时间范围内可以发出的请求数量的限制。每月或每两个月提出请求的解决方案是最容易实施的。
一次处理两个月所需的请求数量可能会减少一半。快速查找过去两年的数据,某个月内某个股票的分钟数聚合的最大数据集是股票AAPL,它在2022-03-01到2022-03-31之间有18,956条记录。因此我认为您可以安全地一次收集两个月的数据,并且仍然低于50,000条记录的限制,因此如果您像我上面所做的那样使用rrule,请考虑将interval参数设置为2(2个月)或您正在使用的库的任何等效参数。
但即使一次做两个月,这种方法也是非常低效的。有一些股票代码,你可以在不到3个请求的情况下获得整个2年的数据,但即使一次做两个月,也需要6个请求。
对“next_url”使用普通HTTP请求,而不是面Python库
从您的多边形RESTClient客户端返回的数据。get_aggs请求实际上包括'next_url',只是多边形RESTClient库没有任何功能来检索其值或基于该值进行后续请求。然而,我们可以解析该数据以收集'next_url',然后对该URL进行正常HTTP请求以检索额外数据。
与之前一样,您可以使用多边形客户端的client.get_aggs以常规方式获取第一个记录集合:
然后,解析返回的数据以检索“next_url”,如果存在,则该URL将是数据中的最后一个字符串。有几种方法可以执行此操作,但性能各不相同。
最有吸引力的方法是使用BeautifulSoup这样的JSON解析器并检索'next_url',但这可能效率不高,因为它会解析整个数据,而我们只需要最后一个String。
更快但更难看的是,我们可以从末尾向后迭代数据的字符以检索最后一个字符串,反向以使其恢复正常,并检查它是否包含游标。
如果存在游标,则数据中的最后一个字符串(next_url)将采用以下格式:“https://api.polygon.io/v2/aggs/ticker/the_ticker/range/1/minute/unformatted日期 / 格式化日期 ?游标= 游标ID”
如果没有游标,则数据中的最后一个字符串将为“count”
所以我们可以这样做:
我知道那样会更优雅,但你明白我的意思。
然后,可以使用普通HTTP请求从该游标获取数据,并对每个包含游标的结果重复此操作。
请记住将API_key附加到请求中。您只需将“&apiKey="+附加<your_api_key>到URL中即可。
比如:
当使用普通HTTP请求而不是多边形RESTClient库时,需要记住的一点是,当请求失败时,它不会引发与多边形库相同类型的Python异常。
考虑对www.example.com请求执行try/catchpolygon.io,并在超过每分钟请求数限制时进行处理
您的请求可能会出现许多问题,其中许多问题可以通过重试来解决。例如,您可以考虑将http/API请求放入范围为n的for循环中,然后重试由于某种原因失败的请求。例如,polygon.io帐户有请求/分钟限制,请求将返回一些错误,如“...超过了每分钟的最大请求数...”“您可以通过等待time.sleep()然后重试来自动解决。404找不到有时可能是类似的。