Skip to main content

Spot Websockets (v2) Book Checksum

This page describes how to maintain the book and generate the checksum for the websockets v2 book channel. The feed describes the aggregate quantities at each price level.

The checksum verification is optional. It provides an additional check that the client copy has been constructed correctly and is synchronised to the exchange. The checksum can be verified on every update or periodically depending on the throughput / processing requirements of the client.

The checksum is only calculated for the top 10 price levels of the book regardless of the subscription depth.

Maintaining the book Channel

All price level updates in a book message should be processed before the checksum is calculated. An update message may contain many updates to either the bids and/or asks.

An update with "qty": 0 indicates that price level should be removed from your book.

Additionally, after each update, the book should be truncated to your subscribed depth as you won't receive "qty": 0 for price levels that fall out of scope. In other words, if you are subscribed with "depth": 10 and an insert into the middle of the book results in you having 11 bids, you must remove the 11th worst bid.

Checksum Calculation

Checksum logic in websockets v2 is very similar to v1. The price and qty fields are pushed onto the wire containing full precision. To keep the full precision through deserialization and decoding, parse the book message using a decimal or string decoder.

Example code for decoding message with full precision:

    async for bytes in websocket:
message = json.loads(bytes, parse_float=Decimal)
self.on_message(message)

Checksum Steps with Example

This example data below can be used as input to your checksum calculator to confirm correct behaviour and steps.

Example: Generating a book snapshot checksum (using json string decoder):

{
"channel": "book",
"type": "snapshot",
"data": [
{
"symbol": "BTC/USD",
"bids": [
{
"price": "45283.5",
"qty": "0.10000000"
},
{
"price": "45283.4",
"qty": "1.54582015"
},
{
"price": "45282.1",
"qty": "0.10000000"
},
{
"price": "45281.0",
"qty": "0.10000000"
},
{
"price": "45280.3",
"qty": "1.54592586"
},
{
"price": "45279.0",
"qty": "0.07990000"
},
{
"price": "45277.6",
"qty": "0.03310103"
},
{
"price": "45277.5",
"qty": "0.30000000"
},
{
"price": "45277.3",
"qty": "1.54602737"
},
{
"price": "45276.6",
"qty": "0.15445238"
}
],
"asks": [
{
"price": "45285.2",
"qty": "0.00100000"
},
{
"price": "45286.4",
"qty": "1.54571953"
},
{
"price": "45286.6",
"qty": "1.54571109"
},
{
"price": "45289.6",
"qty": "1.54560911"
},
{
"price": "45290.2",
"qty": "0.15890660"
},
{
"price": "45291.8",
"qty": "1.54553491"
},
{
"price": "45294.7",
"qty": "0.04454749"
},
{
"price": "45296.1",
"qty": "0.35380000"
},
{
"price": "45297.5",
"qty": "0.09945542"
},
{
"price": "45299.5",
"qty": "0.18772827"
}
],
"checksum": 3310070434
}
]
}

Generate Checksum String

The checksum is generated by iterating through the top 10 price levels in each side of book to generate a string representation, then passing this string to a CRC32 checksum function. The final checksum is a integer value.

1, Generate formatted string for each price level in the asks (sorted by price from low to high):

  • Remove the decimal character, '.', from the price, i.e. "45285.2" -> "452852".
  • Remove all leading zero characters from the price. i.e. "452852" -> "452852".
  • Remove the decimal character, '.', from the qty, i.e. "0.00100000" -> "000100000".
  • Remove all leading zero characters from the qty. i.e. "000100000" -> "100000".
  • Add the price + qty (452852100000) string to the asks concatenation.
  • Repeat for the remaining 9 price levels.
45285210000045286415457195345286615457110945289615456091145290215890660452918154553491452947445474945296135380000452975994554245299518772827

2, Generate formatted string for each price level in the bids (sorted by price from high to low):

  • Remove the decimal character, '.', from the price, i.e. "45283.5" -> "452835".
  • Remove all leading zero characters from the price. i.e. "452835" -> "452835".
  • Remove the decimal character, '.', from the qty, i.e. "0.10000000" -> "010000000".
  • Remove all leading zero characters from the qty. i.e. "010000000" -> "10000000".
  • Add the price + qty (45283510000000) string to the bids concatenation.
  • Repeat for the remaining 9 price levels.
452835100000004528341545820154528211000000045281010000000452803154592586452790799000045277633101034527753000000045277315460273745276615445238

Generate Integer Value from Checksum String

3, Concatenate the generated asks + bids strings.

45285210000045286415457195345286615457110945289615456091145290215890660452918154553491452947445474945296135380000452975994554245299518772827452835100000004528341545820154528211000000045281010000000452803154592586452790799000045277633101034527753000000045277315460273745276615445238

4, Feed the concatenated string as input to a CRC32 checksum function.

3310070434

This value can now be compared to the checksum received to ensure your local book is accurate.

Optionally, depending on the CRC32 checksum function, the result may need to be cast to unsigned 32-bit integer.