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) for the prices and quantities.
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.