6 · The book Draft
The local book and a worked trade
On this page
The book in our program
When this chapter says “the book” from here on, it means the program’s copy: for each side, the venue’s levels by price, and the quantity at each. It is not the venue’s book, which lives in the matching engine; it is a reconstruction from what the venue publishes, and it is only as good as the publishing and our handling of it.
Venues publish at one of two grains. An L2 feed, also called market by price, publishes each level’s total and nothing about the orders inside it: “6,812,353 now holds 420 lots”. An L3 feed, market by order, publishes every order with its own identifier: “order 81,237,004 for 300 lots joined the ask at 6,812,353”, then “order 81,237,004 traded 250”. From L3 a program can rebuild the queue inside each level and know where its own order stands in it; from L2 it can know only totals. L3 costs more on both ends: the venue sends a message for every order event rather than one per level change, and the receiver keeps an entry per order, hundreds of thousands of them on a busy instrument, rather than one per price. Classic exchanges often publish both. Crypto venues mostly publish L2; Binance’s depth streams, the concrete case in this chapter, are L2. Most strategies need the prices and totals and nothing finer, so the book this chapter builds is L2: a map from price to quantity, one per side, with the best price on each side always at hand.
What it costs
A level in the copy is two integers: a price in ticks, 8 bytes, and a quantity in lots, 8 bytes, 16 bytes in all, four to a 64-byte cache line. A thousand levels a side is 16 KB a side and 32 KB for the whole book, laid end to end. That is about the size of a core’s L1 data cache, 32–48 KB on current parts, which the decoder, the strategy and the stack share with the book, so the whole book does not live in L1 and does not need to. What the hot path touches on nearly every update is the top few levels on each side, ten levels on each side being 320 bytes in all, five cache lines, and those stay in L1 at 1 ns a load. The deeper levels sit in the L2 cache at 4 ns, or L3 at 10–40 ns, and are touched only when they change. A copy of an order-by-order feed is bigger: each order needs at least its identifier, price, quantity and a link to its neighbour in the queue, 32 bytes or more, and 100,000 waiting orders is 3 MB or more, past L2 on most parts. The time an update costs is largely the time it takes to reach its level’s bytes; how the levels are laid out decides whether that is one L1 load or a chain of misses at up to 100 ns each, a tenth of a budget per miss.
Worked example: a market order walks the ask side
At 14:02:17.250 UTC the book is as drawn above, and somebody sends a market order to buy 1.2 BTC, 1,200 lots. The matching engine walks the asks from the best price deeper into the book. At 6,812,348 ticks ($68,123.48) it takes all 350 lots; 850 remain to buy. At 6,812,350 ($68,123.50) it takes all 600; 250 remain. At 6,812,353 ($68,123.53) the level holds 420 lots in two orders, 300 that arrived first and 120 behind them, so the 250 come from the front order, which is left with 50. The buyer receives three fills: 350 lots at 6,812,348, 600 at 6,812,350 and 250 at 6,812,353. In integers the cost is 350 × 6,812,348 + 600 × 6,812,350 + 250 × 6,812,353 = 8,174,820,050 tick-lots, and since one tick-lot is $0.01 × 0.001 BTC = $0.00001, that is $81,748.2005, an average of 6,812,350.04 ticks, $68,123.5004 a bitcoin. The three sellers receive fills too: the orders at the first two levels are filled completely, the front order at the third partially.
The new best ask is 6,812,353 ($68,123.53) with 170 lots, and the spread has widened from 3 ticks to 8. Two levels have gone and a third has shrunk. A program on core 3 copying this book over an L2 feed learns all of it as three level changes on the ask side: 6,812,348 to 0, 6,812,350 to 0, 6,812,353 to 170. On the fastest structure this chapter builds, the first two each empty the best level and make the structure find the next one, 5–20 ns each, and the third costs 2–5 ns: 12–45 ns in all, under 5% of a budget. On a BTreeMap, with two levels removed at 150–500 ns and one changed at 100–300 ns, they cost 0.4–1.3 µs, up to a budget and a third, for one decision by the venue.
Seeing it
A venue shows its book to anyone who asks. curl -s 'https://fapi.binance.com/fapi/v1/depth?symbol=BTCUSDT&limit=5' asks Binance’s futures market, home of the real contract this chapter’s instrument stands for, for the best five levels a side, and prints one JSON object. bids is a list of [price, quantity] pairs written as strings, highest price first, and asks the same, lowest first: the first entry of each is the top of the book, and the difference between their prices is the spread. E and T are the venue’s clock in milliseconds. lastUpdateId is the number of the last change the answer includes, which is where the next section starts. Ask twice a second apart and some quantities will have changed; raise limit to 1,000 and the depth behind the top appears. The real contract’s tick and lot are the venue’s own, published with its other trading rules, and need not be this chapter’s $0.01 and 0.001 BTC.
Read more: Larry Harris, Trading and Exchanges: Market Microstructure for Practitioners (Oxford University Press, 2002), is the standard practitioner’s account of how orders, order types, priority rules and market structures work, written for readers who have not traded; its early chapters on orders and on how markets are organised cover everything in this section at greater depth. Martin D. Gould, Mason A. Porter, Stacy Williams, Mark McDonald, Daniel J. Fenn and Sam D. Howison, “Limit order books” (Quantitative Finance, 2013; arXiv:1012.0349), is a survey that opens with careful definitions of the limit order book, its levels, priority rules and the vocabulary of bid, ask, spread and depth, before turning to models.