A lot of crypto exchanges offer pub/sub API through websocket implementation if you need to grab realtime data such as rates, trades, orderbooks, and even chat and annoucements. Such information is useful when you run your bot and find edges in trades especially for shorter period of time in HFT (High-frequency Trading).
Some crypto exchanges provide their own wrapper to connect the server and subscribe their channel in specific progoramming language, in this article I tested an open source Python library python-socketio to connect the server and retrieve recent executions via websocket.
Aldridge and Krawciw estimated that in 2016 HFT on average initiated 10–40% of trading volume in equities, and 10–15% of volume in foreign exchange and commodities, I guessed that the percentage of HFT would tend to increase higher in crypto exchanges. There is no special co-location close to physical exchange for crypto, so that the internet connection to the given API endpoint is available for everyone equally.
- Use websocket to subscribe transaction channel in bitbank
- Store executions in queue and calculate the mean price
WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection.WebSocket – Wikipedia
The protocol simply enables servers to communicate with clients and send information to clients without being requested from clients. Realtime data can be flowed into client machines on a channel. On specific channel you subscribe, you will be able to receive a stream of messages in WebSocket.
In security and forex, crypto exchanges, people are using WebSocket to receive realtime information such as rates, trades, orderbook, etc. In here I’d want to test obtaining executions data and put data into a queue for later calculations.
Subscribe a channel
Let’s install the library and start receiving bitcoin transactions data in realtime. I followed the document of Client Example to implement.
$ pip install python-socketio
Here’s the example code. If you use decorators for the event-based architecture, the code can look more simpler and shorter. Once a connection is established, emitting an event to join specific channel is only needed, that is
sio.emit('join-room', 'transactions_btc_jpy') in this code.
If you run this code you will see a stream of realtime messages on your console.
I’m keen on how to use obtained information. Let’s assume that we will need to know the mean price of the recent executions for deciding next bid and ask actions. I created a sample code in the next section.
Store data in a queue and calculate the mean price
I confirmed the format of the message. It is JSON and I could extract transactions in a list with the code
transactions = data['message']['data']['transactions'].
Web Socket Streams for Bitbank
transactions are in a list (Python list) and we can iterate this list to get executed prices. The strategy here is to store the executed prices in a queue by using collections.deque with maximized length configuration.
A queue may grow to an arbitrary length. The deque is bounded to the specified maximum length if you configure this option to specific value.
The mean price of the recent 5 executions can be calculated as below when a message comes out. As derived from the variable name, this mean value can be thought a simple moving average of 5 executions in a certain period of time.
The code shows the executed transactions periodically when a message is received in realtime, plus the mean value of the last 5 executions price.
In this case 5 trades were executed at the price 1197219 5 times, so the mean price was also the same 1197219 as a result.
While WebSocket is established and doing realtime works, the application running on the main thread is free to do any work, as this is not going to prevent the functioning of the Socket.IO client. You can refer to the queue and calculate technical indicator values for your trade.
Here’s the example code to collect information from the queue and output the mean price of the last 5 executions every 5 seconds. If you flush the queue every 5 seconds then you would get 5 seconds average price of executions for the last 5 executions. I just refactored the previous code a little in this code.