market-microstructure
What happens inside an exchange between “buy” and “filled”?
A limit order book in C++20 that ingests NASDAQ's actual binary feed format (ITCH 5.0), keeps the book current in nanoseconds, and detects four kinds of market manipulation in the same process.
// why this exists
The problem I gave myself
Most of my work is measured in milliseconds — a slow API call, a lagging pipeline. I wanted to understand the world where a microsecond is slow. Where picking the wrong container or calling malloc at the wrong moment is the difference between competitive and irrelevant.
So I chose the hardest self-contained version of that world: rebuild NASDAQ's order book from the raw message feed, then detect spoofing the way an exchange's surveillance team would. No framework, no library doing the interesting part — just the feed, the book, and the detectors.
$ ./build/benchmark
[bench] add_order : 672.7 ns/op (1.5M ops/sec)
[bench] cancel_order : 29.1 ns/op (34.3M ops/sec)
[bench] snapshot : 1.0 ns/op
[test_order_book] all tests passed
[test_itch_parser] all tests passed
[test_detector] all tests passed
What this shows
- • I can write C++ that holds up under a benchmark, not just compiles
- • I know what a cache line is and why alignas(64) matters
- • I can parse a binary wire protocol byte by byte — and test it byte by byte
- • I understand how exchange matching actually works, not just the theory
Honest engineering notes
- • First benchmark claimed 45ns/add. Real measured number: 673ns. The map rehashing was invisible until I measured properly — the README tells that story.
- • The parser passed every “looks right” check and was off by 2 bytes on every field. Byte-level tests caught it.
// the surveillance layer
Four manipulation patterns, caught in-process
Spoofing
A huge bid appears to fake demand, never trades, and vanishes in under 500ms.
Track each order's size against book depth. Flag oversized cancels inside the time window.
Layering
Four or more orders stacked at adjacent prices on one side, creating fake depth.
Rolling window over open orders per symbol; flag clusters within a few ticks.
Momentum ignition
A burst of aggressive one-sided fills meant to start a price move.
Count same-direction fills in a 2-second sliding window.
Quote stuffing
Flooding the feed with 10,000+ messages a second to slow competitors down.
Message-rate counter per symbol per second. Simple and effective.
// design decisions
The parts I'd defend in a review
Pool allocator
Orders live in a pre-allocated flat array with a free list. After warmup, add and cancel never call malloc. The pool doubles if it fills — in practice it doesn't.
Fixed-point prices
All prices are int64 in 1/10000-dollar units, exactly as they arrive on the wire. No floating-point equality bugs in price level lookups.
Cache-line alignment
Order is alignas(64). If this ever goes multi-threaded, two threads on adjacent orders won't invalidate each other's cache lines.
The tests are the spec
14 tests including byte-level parser cases. The off-by-two bug I mentioned above is now a permanent regression test.