orderbook

module
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: MIT

README

orderbook

A production-grade central limit order book (CLOB) and matching engine in Go: integer-exact pricing, a zero-allocation hot path, a lock-free single-writer core, and deterministic, replayable execution.

Go Reference CI Go Report Card Live demo

orderbook is an embeddable Go library — go get it into an exchange, a simulator, or a trading tool. The matching core owns the order book, the matching algorithm, order lifecycle, deterministic sequencing, and market-data snapshots, plus a set of opt-in pre-trade risk & anti-manipulation controls; credit, identity, fees, and wire protocols stay in the layers around it, the same boundary production venues draw. Companion packages cover the rest of that boundary — durable WAL persistence (pkg/wal), market-abuse surveillance (pkg/surveillance), an enforcing edge gateway (pkg/gateway), and a uniform-price call auction (pkg/auction). Every defensive control is grounded in a real enforcement case or incident, catalogued in docs/THREAT-MODEL.md. The repository also ships a reproducible market-microstructure research harness and an interactive WebAssembly demo that runs the real engine in the browser.


Highlights

  • Integer-exact pricing. The engine works in int64 ticks and lots; a per-symbol Instrument converts decimals only at the API boundary. No floating-point on the money path.
  • Low latency, zero allocation. O(1) cancel, pooled book nodes and price levels, and a caller-buffer match path that allocates 0 B/op. A realistic cancel-heavy flow runs at p50 83 ns · p99 167 ns · p999 292 ns per operation.
  • Single-writer core. One matching goroutine owns the book with no lock on the hot path (the LMAX model). A Runner fronts it with an MPSC command queue so many producers can submit concurrently.
  • Deterministic and recoverable. The same ordered command stream produces byte-identical trades and book state — enabling command-log replay, durable WAL crash recovery (pkg/wal: write-ahead log + snapshots), and reproducible backtests.
  • Full order surface. Limit, market, stop / stop-limit, iceberg (hidden), post-only, pegged, OCO / bracket, and trailing-stop orders; GTC / IOC / FOK time-in-force; self-trade prevention; a price-band circuit breaker; FIFO or pro-rata allocation.
  • Market integrity & safety. Opt-in pre-trade risk controls — fat-finger and dust caps, per-account order limits, minimum resting time, client-order-id idempotency, mark-price step and depth bounds, a self-output guardrail, and timed band-breach pauses — plus a market-abuse surveillance suite (spoofing, order-to-trade ratio, marking-the-close, ramping, pinging, cross-book), an enforcing gateway (rate limit + speed bump), and a uniform-price call auction. Each maps to a real case in docs/THREAT-MODEL.md.
  • Market data. L1 / L2 / L3 (market-by-order) snapshots with sequence numbers.
  • Tested and benchmarked. Race, fuzz, soak, and replay-recovery suites; microbenchmarks run in CI on every push.

Installation

go get github.com/intrepidkarthi/orderbook/pkg/matching

Requires Go 1.23 or later.


Quickstart

The engine works in integer ticks and lots. Pass them directly, or use an Instrument to convert from decimals at the boundary.

eng := matching.NewEngine(matching.DefaultConfig("BTC-USD"))

// A resting sell, then a crossing buy that trades against it at the maker price.
sell, _ := types.NewOrder("mm", "BTC-USD", types.SideSell, types.OrderTypeLimit, 100, 5, types.TIFGoodTillCancel)
eng.Process(sell)

buy, _ := types.NewOrder("taker", "BTC-USD", types.SideBuy, types.OrderTypeLimit, 101, 3, types.TIFGoodTillCancel)
res := eng.Process(buy) // res.Trades, res.Status, res.RejectionReason

bid, qty, ok := eng.BestBid()

Decimals at the boundary, concurrent submission, and the zero-allocation path:

// Decimals in, int64 ticks/lots out.
inst := types.NewInstrument("BTC-USD", decimal.RequireFromString("0.01"), decimal.RequireFromString("0.001"))
order, _ := inst.NewOrder("alice", types.SideBuy, types.OrderTypeLimit,
    decimal.RequireFromString("30000.50"), decimal.RequireFromString("0.25"), types.TIFGoodTillCancel)

// Many producers, one matching goroutine.
r := matching.NewRunner(matching.RunnerConfig{Engine: matching.DefaultConfig("BTC-USD")})
defer r.Close()
r.SubmitAsync(order) // enqueue without blocking; result arrives on the returned channel

// Zero-allocation hot path: reuse the trade buffer across calls.
buf := make([]types.Trade, 0, 8)
buf, status, _ := eng.Match(order, buf[:0])

Runnable, testable examples render on pkg.go.dev.


Concurrency model

matching.Engine matching.Runner
Contract single writer — drive from one goroutine safe for concurrent producers
Mechanism direct calls, no lock on the hot path MPSC command queue → one matching goroutine
Submit Process (result) · Match (zero-alloc, into a buffer) Process (enqueue + wait) · SubmitAsync (non-blocking)
Reads BestBid / Snapshot / … (book has its own RW-lock) same, delegated to the engine
Use when you own the sequencing loop; benchmarks any multi-goroutine service

The bare Engine has no internal mutex by design; calling its mutating methods from multiple goroutines is a data race. Use a Runner, or serialize to one goroutine. See docs/INTEGRATION.md.


Performance

Core-library microbenchmarks (Apple M-series, Go 1.23, single-threaded):

Benchmark ns/op allocs/op ~ops/sec
Top-of-book read (BestBid) 6.3 0 ~160 M
Cancel (drain) 253 0 ~4 M
Cancel / replace (book) 180 0 ~5.5 M
New price level (churn) 292 0 ~3.4 M
Match round-trip — Match (maker + taker + trade) 352 0 ~2.8 M
Match round-trip — Process (convenience wrapper) 491 4 ~2 M

Tail latency on a realistic ~90%-cancel / 10%-new flow (Match / Cancel): p50 83 ns · p99 167 ns · p999 292 ns, 0 allocs/op — the p999 stays within ~3.5× of the median. Absolute figures include time.Now overhead; the median-to-tail shape is the signal.

Reproduce with make bench. CI runs the benchmarks on every push. Methodology and full results: docs/BENCHMARKS.md.


Architecture

The core is a strictly downward-layered set of packages. Research, simulation, and the web demo depend on the core; the core depends on nothing above it.

web/ (React + TS)  ──▶  cmd/obwasm (Go → WASM)  ─┐
                                                 │
   backtest ▸ strategy ▸ sim ▸ signals ▸ marketdata
                                                 │
        ═══════════════ CORE LIBRARY ════════════▼═══════
           surveillance ▸ matching ▸ orderbook ▸ types
Package Responsibility
pkg/types Order, Trade, Instrument (decimal ⇄ tick boundary), order-type wrappers
pkg/orderbook the CLOB data structure and L1/L2/L3 snapshots
pkg/matching the single-writer Engine and the concurrent Runner
pkg/marketdata record, replay, and digest — deterministic recovery primitives

Documentation

Document Contents
API reference Generated Go documentation for every package, with runnable examples, on pkg.go.dev.
INTEGRATION.md Embedding the engine: reference architecture, single-writer vs concurrent, WAL and recovery, market-data fan-out, observability, multi-symbol scaling, and a production checklist.
CONFIG.md Every configuration knob — Instrument, engine policy, time-in-force, order types — with defaults, validation, and the core-vs-layer boundary.
THREAT-MODEL.md Attacks hackers and market manipulators run against order books — spoofing, wash trading, marking the close, quote stuffing, oracle manipulation, and more — each mapped to a real enforcement case and to what the engine does (and doesn't) defend.
EXCHANGE-ARCHITECTURE.md How real venues (MetaTrader, Binance, Coinbase, Nasdaq/LMAX/CME/IEX, dYdX/Hyperliquid) implement matching, and the incidents that shaped this design.
SPEC.md Architecture, the order model, core design decisions, and performance targets.
BENCHMARKS.md Performance results, methodology, and how to reproduce.
LEARN.md Order books and market making from first principles.
research-roadmap.md The microstructure research agenda: OFI, Kyle's λ, Avellaneda–Stoikov, delta/CVD.
CHANGELOG.md Release history (v0.1.0 → the unreleased market-integrity set) with breaking-change notes.

Beyond the engine

The same core powers two additional layers, kept strictly above the library:

  • Research harness — order-flow-imbalance and book-imbalance signals, a deterministic exchange simulator, an Avellaneda–Stoikov market-making backtest, and a reproducible study of OFI's contemporaneous-versus-predictive power. Market-abuse surveillance (spoofing/layering and rate limits) and call-auction uncrossing are included.
  • Interactive demo — the engine compiled to WebAssembly, running live in the browser to visualize matching and market making.
go run ./examples/basic         # place two orders and watch them match
go run ./examples/eventfeed     # consume the event stream as an exec-report + position feed
go run ./examples/gateway       # edge controls: enforcing rate gate, speed bump, audit trail
go run ./examples/marketmaker   # backtest an Avellaneda–Stoikov maker
go run ./cmd/obdemo             # end-to-end matching demonstration
go run ./cmd/l2capture          # live order-flow imbalance on Coinbase data

Status

Actively developed. Releases follow semantic versioning; the public API uses integer ticks/lots and a single-writer engine as of v0.3.0. Breaking changes are gated behind minor-version bumps until a v1.0.0 API freeze.

Provenance

The design is informed by the author's prior production matching engine — price–time priority, the map-plus-ladder book structure, and the matching algorithm. This repository is a clean, independent re-implementation for research and education, not a copy of that stack.

License

MIT © Karthikeyan NG

Topics: order-book · matching-engine · limit-order-book · clob · market-making · avellaneda-stoikov · order-flow-imbalance · market-microstructure · backtesting · algorithmic-trading · quantitative-finance · webassembly · golang · exchange · price-time-priority

Directories

Path Synopsis
cmd
l2capture command
Command l2capture polls a public exchange's live level-2 order book and computes order-flow imbalance (OFI) and book imbalance in real time using pkg/signals — the same code the simulator study uses, now on real market data.
Command l2capture polls a public exchange's live level-2 order book and computes order-flow imbalance (OFI) and book imbalance in real time using pkg/signals — the same code the simulator study uses, now on real market data.
obdemo command
Command obdemo is a small end-to-end demonstration of the matching engine: it seeds a book with resting liquidity, then sends a crossing limit order and a market sweep, printing the ladder and the trade tape at each step.
Command obdemo is a small end-to-end demonstration of the matching engine: it seeds a book with resting liquidity, then sends a crossing limit order and a market sweep, printing the ladder and the trade tape at each step.
obmm command
Command obmm runs an Avellaneda–Stoikov market maker through the backtest harness against synthetic noise flow and prints its scorecard.
Command obmm runs an Avellaneda–Stoikov market maker through the backtest harness against synthetic noise flow and prints its scorecard.
obwasm command
Command obwasm compiles the matching engine to WebAssembly and exposes a small JSON API to JavaScript, so the browser demo runs the *real* engine rather than a reimplementation (docs/DEMO-SPEC.md §3).
Command obwasm compiles the matching engine to WebAssembly and exposes a small JSON API to JavaScript, so the browser demo runs the *real* engine rather than a reimplementation (docs/DEMO-SPEC.md §3).
ofistudy command
Command ofistudy runs the order-flow-imbalance experiment and prints whether OFI's link to price is contemporaneous or predictive.
Command ofistudy runs the order-flow-imbalance experiment and prints whether OFI's link to price is contemporaneous or predictive.
surveil command
Command surveil replays a scripted order-flow scenario — a genuine trader, a spoofer layering and pulling large orders, and a quote-stuffer — through the surveillance monitor and prints the alerts it raises.
Command surveil replays a scripted order-flow scenario — a genuine trader, a spoofer layering and pulling large orders, and a quote-stuffer — through the surveillance monitor and prints the alerts it raises.
examples
basic command
Basic example: create an engine, rest a sell order, then cross it with a buy and observe the trade and the resulting book.
Basic example: create an engine, rest a sell order, then cross it with a buy and observe the trade and the resulting book.
eventfeed command
Command eventfeed shows how a downstream adapter consumes the engine's ordered event stream — the integration seam a FIX/OUCH gateway, a market-data publisher, or drop copy would sit on.
Command eventfeed shows how a downstream adapter consumes the engine's ordered event stream — the integration seam a FIX/OUCH gateway, a market-data publisher, or drop copy would sit on.
gateway command
Command gateway shows the pkg/gateway edge controls that belong in the layer *above* the pure matching core (docs/THREAT-MODEL.md §6): an enforcing per-account rate gate that rejects (not just alerts), an asymmetric speed bump on liquidity-taking orders, and a CAT-style audit export off the engine's sequenced event stream.
Command gateway shows the pkg/gateway edge controls that belong in the layer *above* the pure matching core (docs/THREAT-MODEL.md §6): an enforcing per-account rate gate that rejects (not just alerts), an asymmetric speed bump on liquidity-taking orders, and a CAT-style audit export off the engine's sequenced event stream.
marketmaker command
Market-maker example: backtest an Avellaneda–Stoikov quoter against synthetic order flow and print its scorecard.
Market-maker example: backtest an Avellaneda–Stoikov quoter against synthetic order flow and print its scorecard.
signals command
Signals example: compute book imbalance and order-flow imbalance (OFI) from two consecutive book snapshots.
Signals example: compute book imbalance and order-flow imbalance (OFI) from two consecutive book snapshots.
pkg
auction
Package auction implements a call-auction uncross: given resting buy and sell interest, it finds the single clearing price that maximises executed volume and reports how much trades there.
Package auction implements a call-auction uncross: given resting buy and sell interest, it finds the single clearing price that maximises executed volume and reports how much trades there.
backtest
Package backtest runs a market-making strategy against synthetic order flow in a real matching engine and reports its performance.
Package backtest runs a market-making strategy against synthetic order flow in a real matching engine and reports its performance.
gateway
Package gateway provides the pre-trade edge controls that belong in the layer *above* the pure matching core (docs/THREAT-MODEL.md §6): an enforcing per-account rate limit that rejects (not merely alerts), an asymmetric speed bump on liquidity-taking orders, and cancels that are never gated.
Package gateway provides the pre-trade edge controls that belong in the layer *above* the pure matching core (docs/THREAT-MODEL.md §6): an enforcing per-account rate limit that rejects (not merely alerts), an asymmetric speed bump on liquidity-taking orders, and cancels that are never gated.
marketdata
Package marketdata models the input side of a market — order flow — and the tools to record and replay it deterministically.
Package marketdata models the input side of a market — order flow — and the tools to record and replay it deterministically.
matching
Package matching implements a lean, deterministic matching engine over the price–time-priority order book in package orderbook.
Package matching implements a lean, deterministic matching engine over the price–time-priority order book in package orderbook.
orderbook
Package orderbook implements a central limit order book (CLOB) with price–time priority.
Package orderbook implements a central limit order book (CLOB) with price–time priority.
signals
Package signals computes market-microstructure signals from order-book snapshots: book imbalance and order-flow imbalance (OFI) to start.
Package signals computes market-microstructure signals from order-book snapshots: book imbalance and order-flow imbalance (OFI) to start.
sim
Package sim is a deterministic exchange simulator.
Package sim is a deterministic exchange simulator.
strategy
Package strategy implements market-making strategies over the core engine.
Package strategy implements market-making strategies over the core engine.
study
Package study contains reproducible microstructure experiments that put the popular trading claims to the test on controllable, deterministic data.
Package study contains reproducible microstructure experiments that put the popular trading claims to the test on controllable, deterministic data.
surveillance
Package surveillance detects abusive trading patterns from a stream of order-book events.
Package surveillance detects abusive trading patterns from a stream of order-book events.
types
Package types defines the core domain values shared across the order book and matching engine: orders, trades, and the small set of errors they raise.
Package types defines the core domain values shared across the order book and matching engine: orders, trades, and the small set of errors they raise.
wal
Package wal provides durable, append-only write-ahead logging and snapshot persistence for the matching engine — the crash-recovery storage backend.
Package wal provides durable, append-only write-ahead logging and snapshot persistence for the matching engine — the crash-recovery storage backend.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL