A low-latency, in-memory limit order book in C++20, built around two complementary cores that share the same cache-friendly primitives:
- Book reconstruction — decode a real NASDAQ ITCH 5.0 feed and rebuild the resting L2/L3 book with strict price-time priority.
- Matching engine — cross incoming orders against the book, generating fills with price-time priority and GTC / IOC / FOK time-in-force.
It sustains ~20 M book operations/sec and decodes + reconstructs an ITCH feed end-to-end at ~24 M messages/sec (Apple M4 Pro — see benchmarks).
- Real market-data path. Spec-correct ITCH 5.0 decoding (big-endian, full message-length table), a synthetic feed generator, and a replay engine that reconstructs books and reports throughput + Prometheus-format metrics.
- Price-time priority matching with limit/market orders, IOC/FOK, fills at the maker price (price improvement), and multi-level sweeps.
- Engineered for predictable latency. Intrusive FIFO lists at each price
level and an object pool eliminate per-operation heap allocation — measured
2.5–3× faster than
std::list/new+delete. - Correctness first. A full invariant checker, an independent reference-book differential fuzzer (~400k ops/run), and a clean bill under ASan + UBSan in CI.
- Benchmarked. Throughput and p50/p99/p99.9 latency for every operation, plus head-to-head data-structure comparisons.
cmake -S . -B build # Release by default, tuned with -mcpu/-march=native
cmake --build build -j
ctest --test-dir build # unit + fuzz + itch + matching suitesRun the demos:
./build/ob_demo # book reconstruction walkthrough
./build/ob_match_demo # matching engine: fills, IOC, market ordersEnd-to-end ITCH pipeline (no proprietary data needed):
./build/ob_itch_gen --out feed.itch --messages 5000000 --symbols 16
./build/ob_replay --file feed.itch --metrics-out ob.promBenchmarks:
./build/ob_bench # engine throughput + latency percentiles
./build/ob_bench_alloc # pool vs new/delete, intrusive list vs std::listExample matching output:
BUY 250 @ 50.0100 (GTC) -> filled 250, resting 0
fill: 100 shares @ 50.0000 (maker #1) <- price improvement
fill: 150 shares @ 50.0100 (maker #2)
book: bid 49.9900 x150 | ask 50.0100 x50
| metric | result |
|---|---|
| mixed book ops | 20.5 M ops/s (~49 ns/op) |
| ITCH decode + reconstruct | 23.7 M msgs/s (42 ns/msg) |
| add / cancel / execute p99 | 167 / 209 / 250 ns |
top() / depth(10) |
O(1) / O(depth), at the timer floor |
pool vs new+delete |
3.0× |
intrusive list vs std::list |
2.5× |
Full methodology and tables: docs/BENCHMARKS.md.
ITCH 5.0 feed ──▶ decode (typed, big-endian) ──▶ events ──▶ OrderBook ──▶ L2/L3 book
MatchingEngine ──▶ fills
shared primitives: std::map price levels · intrusive FIFO Level · OrderPool
Design rationale, complexity table, and correctness strategy: docs/DESIGN.md.
include/ob/ core headers (book, level, order, pool, matching engine)
include/ob/ingest/ ITCH 5.0 decode/encode, SoupBinTCP, replay
src/ implementations + CLI tools (demo, gen, replay, ingest)
bench/ microbenchmarks (engine, allocator)
tests/ framework + unit, fuzz, itch, matching suites
docs/ design & benchmark notes
| option | default | effect |
|---|---|---|
CMAKE_BUILD_TYPE |
Release |
Debug / RelWithDebInfo also supported |
OB_NATIVE |
ON |
tune for the host CPU (-mcpu/-march=native) |
OB_WERROR |
OFF |
treat warnings as errors (CI uses ON) |
OB_SANITIZE |
OFF |
build with AddressSanitizer + UBSan |
OB_BUILD_BENCH |
ON |
build the benchmark executables |
ob_itch_ingest speaks SoupBinTCP for live/file ITCH sources. Copy
.env.example to .env to set OB_HOST, OB_PORT, OB_USER, OB_PASS,
OB_SESSION, etc.
./build/ob_itch_ingest --file /path/to/ITCH_5.0.bin
./build/ob_itch_ingest --host HOST --port PORT --user U --pass P --session S --frames 5 --verbose