Research: YU13-limit-order-book
Why a crossing book replaces the price-triggered policyβ
The inherited matcher filled an order unilaterally whenever the security's last market price
satisfied its limit (isInTheMoney), with a threshold policy half-filling large orders. That
policy has no counterparty: quantity appears from nowhere, the book only ever grows on one side,
and depth means nothing. Every downstream consumer this system has grown; the risk engine
marking positions, the trade bridge feeding the DB and UI, the throughput bench counting booked
trades; becomes more meaningful when a fill is two orders agreeing on a price. Crossing is also
the only policy under which "book depth" and "best bid/ask" are real quantities the edge can
serve.
Why array-indexed levels with intrusive listsβ
The book's hot operations are: find the best opposite level, take the FIFO head, reduce or
unlink it, append a new resting order, and unlink a canceled order. With price levels as array
slots on a fixed grid and orders as intrusive doubly-linked nodes (links live inside the pooled
RestingOrder), every one of these is O(1) with zero allocation; the same discipline the
engine's dense ordersByRef index and pooled entries already follow. Tree- or map-based books
put a comparison structure and its allocation churn on the hottest path; the array trades a
bounded, lazily-allocated band of memory for constant-time access and cache-friendly scans.
Best-price maintenance uses per-side occupancy bitmaps: clearing the last order at the best
level scans word-wise toward the next occupied level.
Why a 0.001 grid and a banded windowβ
Prices travel the system as long ticks at the x1e6 Px scale, rounded to 3dp HALF_UP at every
edge. The book grid is therefore 0.001; every price an edge can produce is exactly on-grid, and
grid rejection (INVALID) only ever fires for raw sub-0.001 ingress that no edge emits. With
level price == resting limit price exactly, execution at the level price can never violate
either side's limit.
A full-range array at 0.001 granularity would be gigabytes; the band makes it megabytes. Each
security's window (default 1<<17 ticks = $131.07) anchors mid-band on its first limit price; the warm-start seed data and the bench flow both trade each security in a narrow range around
one price, and a limit outside Β±$65.5 of the anchor is exactly what an exchange price collar
rejects. The band width and grid are config-identity values (like the output ring size): read
once at engine construction, identical on every member, and carried in the snapshot header so a
restored member adopts the geometry its state was built with.
Why time priority needs no timestampsβ
Order references are assigned by the cluster service in committed-log order, so ascending reference IS arrival order IS time priority. This has two consequences the design leans on: FIFO within a level is maintained by plain tail-append at arrival; and the snapshot needs no book-structure records at all beyond the band anchors; open rows serialized in ascending reference order re-append on restore into exactly the original per-level FIFO.
Why the last price becomes an outputβ
With a crossing book the execution price is discovered by matching, not read from a reference
feed. The mark (lastPxBySecurity) is therefore written by trades and only seeded by market-data
ticks while no trade has printed; the seed lets an unpriced security bootstrap (trade-ticket
bookings and market-order risk validation need a reference before the first cross). Risk
price-freshness state continues to consume every tick unchanged, so staleness checks and collar
inputs are unaffected.
Why egress acks carry a correlation classβ
The gateway's offer/ack accounting relies on acks being FIFO per session. The inherited design documented its own limit: async updates for resting orders would interleave and skew the count. A crossing book makes counterparty updates the common case; every cross emits an update for a resting order that belongs to no in-flight offer. One spare byte in the fixed 24-byte ack now classes each order-lifecycle ack as direct or resting-update; correlation and batch accounting consume only direct acks. Ack length and all existing fields are unchanged, so a client ignoring the byte sees the previous wire shape.
What the throughput number means nowβ
A booked-fill event counts each SIDE of a cross: one match step books two trades (two trade sequence numbers, one per account). The bench's booked/s numerator therefore counts filled-order events exactly as before, but the flow generating them must be genuinely two-sided and marketable; numbers measured against the auto-fill engine are not comparable and are not carried forward (NFR-LOB03).