使用项目字典发出异步发布请求

Making async posts requests using dictionary of items

我已经构建了一个交易机器人,它会在市场开盘后立即 buy/sell 股票,我正试图加快我的交易 (post) 请求。

我只考虑了大约 350 只股票,但我注意到在发送大量订单 (200-300) 的日子里,我的请求可能需要很长时间 (~1.5min)使用 requests 库。我想尝试使用 asyncioaiohttp 以便更快地发送请求,但是我收到了我无法弄清楚的错误。我对异步方法不是很熟悉,所以我来这里寻求“小帮助”。

下面是用于发出 trade/post 请求的异步函数。我大致基于这个 SO answer 我得到的错误是 TypeError: 'coroutine' object is not iterable

我很确定这与尝试遍历字典有关,但我不确定如何完成我想要的。也许我需要分开买卖订单,所以我只循环遍历 2 个单独的列表而不是一个字典?

任何建议都会有所帮助。

备注:

  1. 如果重要的话,代码是通过 GCP Cloud Function 执行的。
  2. 将两个列表传递到函数中是有意的,我需要在进行交易之前计算 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