Free preview

Why this matters: real venues surround this exact core with order-type zoos, market-data feeds, and latency budgets measured in microseconds — and interviewers pull extensions from that surrounding ring. The pattern to demonstrate is the same one the core was built on: each demand lands at a seam, and a well-shaped match loop absorbs most of them without changing.

IOC and FOK: order types as policy, not new engines

Two order types appear in nearly every follow-up. Immediate-or-cancel (IOC): match what crosses right now, cancel the remainder instead of resting it. Fill-or-kill (FOK): execute the entire quantity immediately or do nothing at all.

IOC is almost free: it's the existing match loop with the final rest(...) replaced by a cancel — one branch on a policy field. FOK is the interesting one, because "all or nothing" means you must know the answer before filling anything: walk the opposite side's best levels summing available quantity (the cached per-level totals from lesson 02 earn their keep here — no order-by-order scan) until you reach the target or run out of crossing levels; only then run the normal loop. The design sentence worth saying: order types are parameters of the same match loop — when to stop, whether to rest, whether to pre-check — not new engines. If a proposed type can't be expressed that way, that's a sign to re-examine the core.

Top-of-book market data

Everyone outside the engine wants to know the best bid and ask. The clean shape: after each operation, if the best price or its total quantity changed on either side, emit a top-of-book event (best bid price/qty, best ask price/qty, sequence number). Two design points carry the answer. First, events are derived after the operation completes, never interleaved mid-match — consumers see only consistent states. Second, the sequence number ties each event to its position in the input stream, so consumers can order and de-duplicate. The seam is the operation boundary; the engine's core loop never knows subscribers exist.

Self-trade prevention: a pre-match check at a seam

Venues typically stop a participant from trading with themselves — accidental self-trades distort volume and can look like manipulation. The requirement arrives as: incoming order would match a resting order from the same participant — what happens? The policies are cancel-newest (kill the incoming remainder), cancel-oldest (pull the resting order and keep matching), or decrement both. The design answer matters more than the policy choice: this is a check between selecting the resting counterparty and executing the fill — one guard at the top of the fill step, consulting owner ids, dispatching on policy. It's the matching engine's version of the pre-dispatch pause check from the scheduler chapter: a seam the loop already has, if you wrote the loop as select, check, fill.

Many instruments: shard by symbol, share nothing

The single-instrument scope was real, and here's why it scales anyway: books for different instruments share no state — an order for one symbol never touches another's book. So the multi-instrument design is an engine per instrument, each single-threaded with its own sequenced input, routed by symbol upstream.

orders in --> router (by symbol) --> sequencer A --> engine A (own book)
                                 --> sequencer B --> engine B (own book)
                                 --> sequencer C --> engine C (own book)

Sketch-level is the right depth in a round: the point is that the single-threaded decision composes — parallelism lives between books, where no ordering is required, and never inside one, where it is.

Latency engineering: the hot path allocates nothing

The worst-case latency bar from lesson 01 eventually turns into a memory conversation. A hot path that allocates per order invites the allocator — and, in managed runtimes, the garbage collector — into the middle of matching; a collection pause during a burst is exactly the worst-case spike the requirement forbade. The standard discipline: pre-allocate pools of order and level objects at startup, recycle them on fill and cancel, and keep the steady-state hot path allocation-free. Notice this is the fixed-size-class thinking from the arena-allocator chapter pointed at a new problem — that chapter is the natural companion read here. Add the supporting cast — arrays over pointer-chasing structures where possible, integer ticks (never floating point for prices, both for exactness and speed) — and you're describing a real engine's shape.

Key takeaway

The extensions all land on seams the core already has: IOC and FOK are stop/rest/pre-check parameters of the one match loop, top-of-book events derive at operation boundaries, self-trade prevention is a guard between selecting a counterparty and filling, multi-instrument is share-nothing engines behind a symbol router, and the latency bar becomes object pools and an allocation-free hot path. Naming the seam before the interviewer does is the trade-offs act.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue