I built a near real-time crypto trading application, and here's what I learned.
cross posted on medium http://bit.ly/dmatrading
Live Order Book
This is one of the hardest parts to get right. When you connect to a WSS stream from CoinbasePro you will see up ~120 orders per second. Your application needs to handle this stream of data properly or your application will crash, your browser may crash, and your operating system may crash. Once you've figured out how to handle this data safely, the next thing to figure out is how to display this data for the user. I've seen poor implementations where the user was given a stream of feeds. In order for them to select an order to fill, the implementer provided a UI to allow them to pause the stream. A popular way to handle this, as is exhibited by over 30 cryptocurrency exchanges, is to provide a list of asks and bids, and update the sizes of the orders while keeping your best bid and offer as anchors.
from the CoinbasePro | API Reference (An algorithm to maintain an up-to-date level 3 order book)
- Send a subscribe message for the product(s) of interest and the full channel.
- Queue any messages received over the websocket stream.
- Make a REST request for the order book snapshot from the REST feed.
- Playback queued messages, discarding sequence numbers before or equal to the snapshot sequence number.
- Apply playback messages to the snapshot as needed (see below).
- After playback is complete, apply real-time stream messages as they arrive.
There are a number of charting solutions available for viewing asset prices, but there is only one that really stands out. The chart will load every time you switch cryptocurrencies. In a future release I will show the chart depending on which exchange is selected. Not very difficult but I prioritized other features.
Market Depth Chart
I wanted a market depth chart, that had some interaction, was regularly updated, and easy to use. I created a server endpoint that updates the orderbook every second. Not real-time, but still useful. When the user selects a new exchange, the app will load the order book for that exchange, for the given selected pair.
Top Exchanges by Trading Volume for Market
The other solutions that let you trade digital assets across exchanges, start with selected an exchange, then filtering by market. I wanted to be able to select a market first, then view exchanges where I can trade this market. The fiat currency is USD, so when I select a market, the app will show me the top exchanges by trading volume, for the given pair. Selecting an exchange, will show the exchange profile, and will also show the orderbook for that exchange. Later I will add the ability to switch fiat currencies.
Top Cryptocurrencies by Market Cap
This feature will show me a list of the top cryptocurrencies by market cap. This shows the coin logo, the symbol, full name, and the trading price. This price is updated every 30s. This implementation is done with a websocket, so it will be easy to update the websocket server and push updated prices more often, in a future release.
Thie ticker at the top of the page, displays the current trading price at Coinbase, the bid, ask, and volume. This is a stream coming from Coinbase. When the data streams in, it will update the ticker right away. This can happen more than once per second. in a future release i can stream the feeds from other exchanges, where available.
Best Bid or Offer
I wanted a way to see the best bid and offer at multiple exchanges, in a near real-time manner. This feature streams the best bid or offer from different exchanges, as the order is placed. presently it's just showing three exchanges and showing just bitcoin. in a future release this will show BBO from the selected exchange for the selected market.
Select an Order to Match
A common feature, is to be able to select an order from the book, and have that price and size immediately fill the order form. All that's left to do is click to place the order. This is a convenient function when you want to match an order instantly. in a future release this will have more functionality.
To create this application, I used a few technologies.
- FIX (Financial Information Exchange) is a protocol used to enter/cancel orders and receive fills. An alternative to REST, FIX establishes a secure connection and can allow faster execution. [didn't get around to doing this but high on my wish list]
Serverless vs. Colocation
I hosted the application on AWS and used serverless with GraphQL. This allowed me to use DynamoDB for my data storage needs. I decided to move the application to the Digital Ocean Cloud, because this will make it easier for me to co-locate my code closer to the exchanges I am targeting.
I used React, Typescript, and GraphQL for my UI, and I used Node and GraphQL on my server. I used Apollo Subscriptions send data from my server to my client and Apollo Queries and Mutations when making requests to my server from my client. I created websocket clients when connecting to exchange feeds, and websocket servers when fetching REST APIs and opening a connection to my client. I used the CCXT library when REST was all I needed, but I went straight to the exchanges when I needed a websocket feed, because this isn't supported in ccxt.
Managing State in the Application
This application shares state in the client and on the server. Keeping a connection open between the client and server makes subsequent requests for data more performant, but establishing the connection can take some time. The most performant way is to do both. This is done for the "Top Crypto by Market Cap" list. The initial load is a GraphQL query that will use a GraphQL to fetch the data via HTTP, while subsequent requests will use GraphQL to fetch the data via WS.
About the Author
Brian has built trading applications and trading products for various asset classes, with Galaxy Digital Trading, JP Morgan, and Tradeweb.