The order book and price-time priority
The central data structure of the exchange, the two-rule algorithm that runs it, and why the engine is single-threaded on purpose.
In 1.2, Alice's order "rested on the book." This lesson is that book.
A central limit order book (CLOB) is two sorted lists per symbol: bids (buyers, best = highest price) and asks (sellers, best = lowest). Within one price level, orders queue in arrival order.
flowchart LR
subgraph bids["BIDS — buyers, best price on top"]
direction TB
B1["10.01 · 300 shares · 2 orders"]
B2["10.00 · 1,200 shares · 5 orders"]
B3["9.99 · 500 shares · 3 orders"]
B1 --- B2 --- B3
end
MID["spread = 0.02"]
subgraph asks["ASKS — sellers, best price on top"]
direction TB
A1["10.03 · 200 shares · 1 order"]
A2["10.04 · 800 shares · 4 orders"]
A3["10.06 · 400 shares · 2 orders"]
A1 --- A2 --- A3
end
bids ~~~ MID ~~~ asks
Matching is governed by price-time priority, two rules applied in strict order:
- Price first: a better price always trades before a worse one.
- Time second: at the same price, whoever arrived first trades first.
Into the book above arrives: buy 900 ACME, limit 10.04. The engine walks the ask side:
- Best ask is 10.03 (200 shares). 10.03 ≤ 10.04, so it matches: trade 200 @ 10.03. Note: at the seller's resting price — the resting order sets the price; the aggressor pays it.
- Next level 10.04 (800 shares across 4 orders). 10.04 ≤ 10.04, match in time order: trade 700 @ 10.04, filling the oldest orders first; the 4th order at that level fills only partially.
- Buyer's 900 shares are done. Book now shows best ask 10.04 (100 shares remaining), best bid still 10.01. One incoming order produced 5+ trades, 5+ private fill reports, and a burst of public market data.
Now the design consequence. Rule 2 — time priority — means matching is order-sensitive: process two orders in a different sequence and you get different owners of the same fill. So the matching engine for a given set of symbols is a single-threaded event loop: one input at a time, to completion, no locks, no races. This sounds like a bottleneck; it isn't. A tight in-memory loop handles hundreds of thousands to millions of events per second — and buys you determinism, which lesson 1.7 converts into the entire recovery story.
- The book = two price-sorted sides, FIFO queues within each price.
- Price-time priority: better price wins; ties broken by arrival.
- Aggressors trade at resting prices; single-threading is a feature, not a compromise.