Reputation: 711
I've built a trading bot that will buy/sell stocks as soon as the market opens and I'm trying to speed up my trade (post) requests.
I only consider about 350 stocks, but I've noticed that on days when I'm sending in a large number of orders (200-300) my requests can take quite a long time (~1.5min) when using the requests
library. I wanted to try to use asyncio
and aiohttp
in order to send in the requests faster, however I'm getting and error I can't figure out. I'm not super familiar with async methods so I'm coming to SO for a 'lil help.
Below are the async functions for making the trade/post requests. I loosely based it on this SO answer (python async post requests) The error I'm getting is TypeError: 'coroutine' object is not iterable
I'm pretty sure this has to do with trying to iterate through the dictionary, but i'm not sure how to accomplish what I want. Perhaps I need to separate the buy and sell orders so I just loop through a 2 separate lists instead of a one dictionary?
Any suggestions would be helpful.
Notes:
make_trades_async
function.# 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))
The make_trades_async
function is run by executing:
asyncio.run(make_trades_async(buySymbolsList=buySymbolsList,
sellSymbolsList=sellSymbolsList,
token=token))
Edit: Environment / Package information:
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
Upvotes: 1
Views: 892
Reputation: 395
You don't need async
in your for loop, you are merely adding tasks to a list synchronously. When you use async for
, you are saying that some asynchronous code is running inside the generator that is producing your iterable. In your case, your iterable is just the list of items in the dictionary, so there's no async
required.
Upvotes: 1