pandas 通过异步API调用将excel功能移植到BLPAPI/xbbg

ttvkxqim  于 2023-04-28  发布在  其他
关注(0)|答案(1)|浏览(117)

您好-我正在尝试将一些Excel工作表移植到一个可以即时运行的Python脚本中。我正在查询Bloomberg数据,本质上我想做的是在特定日期获取历史出价并询问特定ISIN的价格。我正在使用xbbg库查询API并在Jupyter Notebook中工作。数据存储在Pandas dataframe中。
这是我正在尝试建模的非常简单的Excel功能:
Excel Functionality Screenshot
我没有问题拉这个数据为个别行项目.然而,我试图运行这个为25,000指数成分股/日期(在Excel中,你可以只需拖放公式)。我有代码允许并返回正确的数据,然而,运行这么多线路需要几个小时。我相信这是因为代码在继续下一个标识符之前等待每个API调用解析。
我一直在寻找这个问题的解决方案,即使用一个名为asyncio的库。我确实有代码片段可以使用语法,但它仍然花费了太多时间。下面是我的asyncio版本的代码来提取这些数据:

async def bbg_data(isin, start_date, end_date):
    isin = '/isin/' + isin + '@BVAL'
    previous_close_date = pd.to_datetime(end_date).strftime('%Y%m%d')
    px_bid = blp.bdh(tickers=isin, flds=['PX_BID'], start_date=previous_close_date, end_date=previous_close_date)
    if not px_bid.empty:
        px_bid = px_bid.iloc[0][0]
    else:
        px_bid = "N/A"
    px_ask = blp.bdh(tickers=isin, flds=['PX_ASK'], start_date=previous_close_date, end_date=previous_close_date)
    if not px_ask.empty:
        px_ask = px_ask.iloc[0][0]
    else:
        px_ask = "N/A"
    return px_bid, px_ask

async def main():
    tasks = [asyncio.create_task(bbg_data(isin, start_date, end_date)) for isin, start_date, end_date in ttd_sample[['ISIN', 'PreviousClose', 'PreviousClose']].values]
    results = await asyncio.gather(*tasks)
    ttd_sample['previous_bid_price'] = [result[0] for result in results]
    ttd_sample['previous_ask_price'] = [result[1] for result in results]

await main()

关于这个问题,我有几个问题,希望有BLPAPI/asyncio经验的人:
1.我对xbbg库的依赖是否让我头疼?我是否可以使用blpapi一次性解决这个问题?如果是这样,有没有适合初学者的教程?
1.我写asyncio代码的方式有问题吗?我想我很接近了,但我不确定它是否真的是异步的。
如能就如何处理这一问题提出任何建议,将不胜感激。

yyhrrdl8

yyhrrdl81#

每个bdh()请求的设置成本很高。获取一个日期范围,然后选择您想要的日期可能会更快。例如,这里只有一个调用bdh(),而不是10个:

from xbbg import blp
from datetime import date
import pandas as pd

pairs = [['DE0001102325 Govt',date(2023,4,3)],
         ['DE0001134922 Govt',date(2023,3,15)],
         ['DE0001134922 Govt',date(2023,4,19)],
         ['DE0001102358 Govt',date(2023,2,14)],
         ['DE0001102366 Govt',date(2023,4,12)] ]

tickers = [p[0] for p in pairs]
dates = [p[1] for p in pairs]

fields = ['PX_BID','PX_ASK']

min_date = min(dates)
max_date = max(dates)

df = blp.bdh(set(tickers),fields,min_date,max_date)
   
data=[]
index=[]
for [ticker,dt] in pairs:
    data.append([df[ticker].loc[dt][f] for f in fields])
    index.append((ticker,dt))

dfResult = pd.DataFrame(data,index=index,columns=fields)

print(dfResult)

使用输出:

PX_BID   PX_ASK
(DE0001102325 Govt, 2023-04-03)   99.xxx   99.xxx
(DE0001134922 Govt, 2023-03-15)  102.xxx  103.xxx
(DE0001134922 Govt, 2023-04-19)  102.xxx  102.xxx
(DE0001102358 Govt, 2023-02-14)   98.xxx   98.xxx
(DE0001102366 Govt, 2023-04-12)   97.xxx   97.xxx

备注:通过使用set仅将不同的报价单传递给bdh()调用,可以在不同的日期重复报价单。根据min_datemax_date之间的差异,将大量的报价单分成具有更窄日期范围的较小块可能更有效。25,000可能太多了,无法在一个调用中发送(您可能会冒连接超时的风险),所以也许可以从100个isin-date对的块开始。

相关问题