使用项目字典发出异步发布请求
Making async posts requests using dictionary of items
我已经构建了一个交易机器人,它会在市场开盘后立即 buy/sell 股票,我正试图加快我的交易 (post) 请求。
我只考虑了大约 350 只股票,但我注意到在发送大量订单 (200-300) 的日子里,我的请求可能需要很长时间 (~1.5min)使用 requests
库。我想尝试使用 asyncio
和 aiohttp
以便更快地发送请求,但是我收到了我无法弄清楚的错误。我对异步方法不是很熟悉,所以我来这里寻求“小帮助”。
下面是用于发出 trade/post 请求的异步函数。我大致基于这个 SO answer 我得到的错误是 TypeError: 'coroutine' object is not iterable
我很确定这与尝试遍历字典有关,但我不确定如何完成我想要的。也许我需要分开买卖订单,所以我只循环遍历 2 个单独的列表而不是一个字典?
任何建议都会有所帮助。
备注:
- 如果重要的话,代码是通过 GCP Cloud Function 执行的。
- 将两个列表传递到函数中是有意的,我需要在进行交易之前计算 buy/sell 统计数据,并认为将它们合并到
make_trades_async
函数中是 easiest/cleanest。
# Example buy/sell lists:
buySymbolsList = ['MMM', 'CLX']
sellSymbolsList = ['A' 'MS']
async def make_trades_async(buySymbolsList, sellSymbolsList, token):
buyDict = dict.fromkeys(buySymbolsList, "BUY")
sellDict = dict.fromkeys(sellSymbolsList, "SELL")
trades_dict = {**sellDict, **buyDict}
url = 'https://api.tdameritrade.com/v1/accounts/{}/orders'.format(config.MARGIN_ACCOUNT)
async with aiohttp.ClientSession() as session:
post_tasks = []
# prepare the coroutines that post
async for ticker, trade_action in trades_dict.items():
post_tasks.append(do_post(session, url, ticker, trade_action, token))
# now execute them all at once
await asyncio.gather(*post_tasks)
async def do_post(session, url, ticker, trade_action, token):
async with session.post(url,
json ={"orderType": "MARKET",
"session": "NORMAL",
"duration": "DAY",
"orderStrategyType": "SINGLE",
"orderLegCollection": [{
"instruction": trade_action,
"quantity": 1,
"instrument": {
"symbol": ticker,
"assetType": "EQUITY"
}
}]
},
headers= {'Authorization': 'Bearer '+ token}
) as response:
if response.status != 201:
print("Failed to make trade for {}".format(ticker))
make_trades_async
函数是 运行 通过执行:
asyncio.run(make_trades_async(buySymbolsList=buySymbolsList,
sellSymbolsList=sellSymbolsList,
token=token))
编辑:环境/包信息:
Python 3.7
asyncio==3.4.3
aiohttp==3.6.2
async-timeout==3.0.1
attrs==19.3.0
chardet==3.0.4
multidict==4.7.6
yarl==1.5.1
您的 for 循环中不需要 async
,您只是将任务同步添加到列表中。当您使用 async for
时,您是在说一些异步代码在生成您的可迭代对象的生成器中 运行。在您的情况下,您的可迭代对象只是字典中的项目列表,因此不需要 async
。
我已经构建了一个交易机器人,它会在市场开盘后立即 buy/sell 股票,我正试图加快我的交易 (post) 请求。
我只考虑了大约 350 只股票,但我注意到在发送大量订单 (200-300) 的日子里,我的请求可能需要很长时间 (~1.5min)使用 requests
库。我想尝试使用 asyncio
和 aiohttp
以便更快地发送请求,但是我收到了我无法弄清楚的错误。我对异步方法不是很熟悉,所以我来这里寻求“小帮助”。
下面是用于发出 trade/post 请求的异步函数。我大致基于这个 SO answer TypeError: 'coroutine' object is not iterable
我很确定这与尝试遍历字典有关,但我不确定如何完成我想要的。也许我需要分开买卖订单,所以我只循环遍历 2 个单独的列表而不是一个字典?
任何建议都会有所帮助。
备注:
- 如果重要的话,代码是通过 GCP Cloud Function 执行的。
- 将两个列表传递到函数中是有意的,我需要在进行交易之前计算 buy/sell 统计数据,并认为将它们合并到
make_trades_async
函数中是 easiest/cleanest。
# Example buy/sell lists:
buySymbolsList = ['MMM', 'CLX']
sellSymbolsList = ['A' 'MS']
async def make_trades_async(buySymbolsList, sellSymbolsList, token):
buyDict = dict.fromkeys(buySymbolsList, "BUY")
sellDict = dict.fromkeys(sellSymbolsList, "SELL")
trades_dict = {**sellDict, **buyDict}
url = 'https://api.tdameritrade.com/v1/accounts/{}/orders'.format(config.MARGIN_ACCOUNT)
async with aiohttp.ClientSession() as session:
post_tasks = []
# prepare the coroutines that post
async for ticker, trade_action in trades_dict.items():
post_tasks.append(do_post(session, url, ticker, trade_action, token))
# now execute them all at once
await asyncio.gather(*post_tasks)
async def do_post(session, url, ticker, trade_action, token):
async with session.post(url,
json ={"orderType": "MARKET",
"session": "NORMAL",
"duration": "DAY",
"orderStrategyType": "SINGLE",
"orderLegCollection": [{
"instruction": trade_action,
"quantity": 1,
"instrument": {
"symbol": ticker,
"assetType": "EQUITY"
}
}]
},
headers= {'Authorization': 'Bearer '+ token}
) as response:
if response.status != 201:
print("Failed to make trade for {}".format(ticker))
make_trades_async
函数是 运行 通过执行:
asyncio.run(make_trades_async(buySymbolsList=buySymbolsList,
sellSymbolsList=sellSymbolsList,
token=token))
编辑:环境/包信息:
Python 3.7
asyncio==3.4.3
aiohttp==3.6.2
async-timeout==3.0.1
attrs==19.3.0
chardet==3.0.4
multidict==4.7.6
yarl==1.5.1
您的 for 循环中不需要 async
,您只是将任务同步添加到列表中。当您使用 async for
时,您是在说一些异步代码在生成您的可迭代对象的生成器中 运行。在您的情况下,您的可迭代对象只是字典中的项目列表,因此不需要 async
。