Skip to content
  • Overview
  • Curriculum
    • FLUMental maths and numerical fluency
    • MKTMarkets and products
    • CSData structures and algorithms
    • PYPython and data for quants
    • NUMNumerical methods
    • SYSSystems and low latency
      • 1Computer architecture

        • Architecture: caches, branch prediction and SIMD
      • 2C++ for trading

        • C++ for trading: RAII, moves and what belongs on the hot path
      • 3Concurrency

        • Concurrency: atomics, memory ordering and lock-free queues
      • 4Networking

        • Networking: multicast market data, kernel bypass and gap recovery
      • 5Measurement

        • Latency, the memory hierarchy and why the tail is the number
      • 6Order book engineering

        • Order book engineering: data structures and the operations they serve

Practise

  • Question bank
  • Mental arithmetic
  • Market simulator
  • Arbitrage trees
  • Horse racing
  • Bid book
  • Screening tests
  • Mock papers

Reference

  • Formula reference
  • Search

Your record

  • Review queue
  • Progress
  • Leaderboard
  • Profile
  • Invite friends
AccountSend feedback
  1. Curriculum
  2. /Quantitative development
  3. /Systems and low latency
  4. /Order book engineering

Order book engineering: data structures and the operations they serve

SYS · Chapter 6·13 min read·Asked at Hudson River Trading, Jump, Optiver, IMC

Assumes Networking: multicast market data, kernel bypass and gap recovery.

After this lesson you should be able to

  • List the operations a book must support and their frequencies.
  • Design a structure that serves all of them.
  • Say what changes between a matching engine and a market-data book.

The limit order book is the canonical systems design question at a trading firm, and it is a good one because the right answer comes entirely from the operation mix. Cancels dominate, the best prices are read constantly, and the price grid is dense and bounded — and those three facts determine the structure.

OperationFrequencyRequired
Cancel by order idHighest — most orders are cancelledO(1)O(1)O(1)
Read best bid and offerEvery decisionO(1)O(1)O(1)
Add at a priceHighO(1)O(1)O(1)
Match against the bookLowerO(1)O(1)O(1) amortised per level
Walk several levels of depthOccasionalO(levels)O(\text{levels})O(levels)
Table 6.1 · The operations, by frequency. Cancels outnumber trades by one or two orders of magnitude on most venues, so a design that makes cancellation cheap at the expense of anything else is usually right.

Proposition 6.2

The standard design

An array of price levels indexed by tick, each holding an intrusive doubly linked list of orders in time priority, plus a hash map from order id to the node. The array gives O(1)O(1)O(1) price access, the list gives FIFO with O(1)O(1)O(1) removal given the node, and the map turns a cancel into a lookup and an unlink.

Holds when

  • Tick grids are dense and bounded around the touch, so an array beats a tree comfortably.
  • Intrusive lists put the pointers inside the order object, so unlinking needs no search and no allocation.
  • Cache the best bid and offer indices and update them on change rather than scanning.
Array indexed by ticks1Balanced tree14Hash map, then re-sort10,000
Figure 6.3 · One price-level update, ten thousand levels. The book is updated far more often than it is walked, so the structure should be chosen for the update. Indexing an array by tick makes it a single write — the cost is memory proportional to the price range, which is why the trick works for equities and not for a sparse options chain.

Why an array beats a tree here. The textbook answer is a balanced tree keyed on price, and it is the right answer for a sparse, unbounded key space. A tick grid is neither: prices move by single ticks, the active range is a few hundred levels wide, and the mapping from price to index is arithmetic. So the tree’s O(log⁡n)O(\log n)O(logn) with a cache miss per level loses to an array’s O(1)O(1)O(1) with one contiguous access — and the array is simpler. The general lesson is that asymptotic reasoning chooses the tree and the actual key distribution chooses the array.

Proposition 6.4

When the array does not work

Some instruments have very wide or unbounded price ranges — long-dated options, crypto, anything without a tick size. A flat array would be enormous and mostly empty, so the usual answer is a circular buffer covering a window around the touch, shifted as the market moves, with a fallback structure for the tails.

Holds when

  • The window must be wide enough that a fast move does not fall out of it.
  • Shifting costs a bounded amount of work, done off the critical path where possible.
  • A flat hash map plus a separately maintained best-price cache is the simple alternative.

The rest of this lesson is in Premium

You have read the opening. 11 more sections follow, including 4 worked examples and 3 quick checks.

Start the free 7-day trialSign in

Nothing is charged for 7 days, and you can cancel before then. Or read Complexity: reading it off, and deriving it in full, free.

← Latency, the memory hierarchy and why the tail is the numberBack to Systems and low latency →
On this page
  • The operations, by frequency
  • The standard design
  • One price-level update, ten thousand levels
  • When the array does not work

QuantMax · 141 lessons · 1342 questions · c5c0caa

  • Premium
  • Arbitrage trees
  • Horse racing
  • Invite friends
  • Account
  • About QuantMax
  • Terms
  • Privacy

Firm names identify publicly reported question patterns and nothing more. QuantMax is not affiliated with, endorsed by, or recruiting for any firm named in the curriculum. Everything you do in lessons and the question bank is kept to your account.