The advantage of async processing is that we don’t need to block on I/O which is every action that we make when we interact with the Binance servers.
By not blocking execution we can continue processing data while we wait for responses or new data from websockets.
Simple async example
Save this as a python file to run.
asyncio runs with an event loop, we call
run_until_complete at the start on our main function. This is a
general pattern for asyncio programs. This will finish when the main function finishes, and we can control
this especially if we are listening to websockets.
async keyword in front of the function defines it as a coroutine. If you call a coroutine directly
the function isn’t executed, you just get the coroutine back.
To actually execute the coroutine we use the
await keyword, as we have done with the
get_all_tickers functions from the Binance client.
Now if we run this we do get both the exchange info and all tickers, however we haven’t actually leveraged any advantages of asyncio here at all. Each request will actually run one after the other.
So how do we improve this? We use asyncio.gather, let’s update our main function to the following
How does this help?
What we are doing here is collecting coroutines that we want executed, and then pass them together to asyncio to execute concurrently.
res will be a list of responses, ordered the same as the coroutines we pass to gather.
Making requests is great but acting on realtime information is the foundation of any bot strategy.
So how would we listen to realtime websocket data while also making API requests?
Here we import the BinanceSocketManager and add a coroutine to listen to the 1 minute BNBBTC kline stream.
You may be familiar with
with in python and context managers, so here we are interacting with an
asynchronous context manager.
We update the main function to call this coroutine.
When we run this we see that it doesn’t exit after the first message but continues. We accomplished that
while True: within the asynchronous context manager making sure that it didn’t exit.
Now we’ve moved from API requests to websocket listening, so let’s add in an API Request.
After every 5th websocket response we fetch and display the order book. This request could be placing an order, but for our purposes the result is the same.
Now this may look like we are done, but what is actually happening here is similar to our first example.
When we fetch the order book we are actually blocking the websocket
recv function from being called.
So what can we do here to remove this block? We can leverage the asyncio.call_soon which schedules a coroutine to be run at the next loop interval. Which translates to as soon as possible and it breaks us out of this current loop to avoid blocking.
Now we can listen to the websocket, react to events and call API requests without blocking.
I would recommend reading the python asyncio docs to learn more.