A limit order book & matching engine,built for production — in Go.

intrepidkarthi.github.io · 2026-07-23 · by Long Nguyen ·generic
A production-grade central limit order book and matching engine written in Go. Integer-exact (int64), deterministic, every real-world order type, with pre-trade risk and anti-manipulation defenses — and it runs live in your browser via WebAssembly.

A limit order book & matching engine,built for production — in Go.

What is this?

`orderbook` is a Go library you drop into your own project to run a central limit order book (CLOB) and matching engine — the core of an exchange, a trading simulator, a game economy, or any system where buyers and sellers meet at a price. It is a focused, dependency-light core you can `go get` today, with a small, stable API.

It’s not a hosted service or a full exchange (no accounts, custody, or settlement) — it’s the engine. Everything you see on this page is powered by that exact engine.

First, what is an order book?

If you’ve never seen one, here it is from the ground up.

1. People post offers. A bid is a buy order (“I’ll buy 5 at 100”). An ask is a sell order (“I’ll sell 3 at 101”). 2. They’re sorted by price. Best bid (highest a buyer will pay) and best ask (lowest a seller will accept) sit in the middle. The gap between them is the spread. 3. Size at each price is depth. Lots of size = a deep, liquid market that’s hard to move. Little size = thin, and prices swing. 4. That whole ladder is the order book — a live list of everyone’s intentions, updating constantly. →

The ladder on the right is a real book from this engine. Best bid/ask are highlighted; the spread is the gap in the middle.

PRICESIZE

spread —mid —

How matching works

When a new order can trade, the engine matches it by price–time priority: best price first, and among equal prices, first-come-first-served. Walk through it — each step runs on the real engine.

PRICESIZE

spread —last —

▶ Start Reset

Press Start to build a book, rest an order, and send a market order that matches.

  • Maker — a limit order that rests and provides liquidity.
  • Taker — a market/crossing order that removes it, paying the spread.
  • Trades print at the maker’s price. Big orders “walk the book” and pay more (slippage).
  • Everything it does

    The order-type and market-integrity surface real venues ship — all in the core.

    Order types

  • Market & Limit
  • Stop & Stop-limit
  • Iceberg (hidden reserve, auto-refill)
  • Post-only (maker-guaranteed)
  • Pegged (to bid / ask / mid + offset)
  • OCO / bracket (one-cancels-other)
  • Trailing stop
  • Matching & priority

  • Price–time priority (FIFO)
  • Pro-rata allocation mode
  • Trades at the maker price
  • Self-trade prevention (5 modes)
  • Time-in-force: GTC · IOC · FOK
  • Call-auction uncross (open/close)
  • Market integrity

  • Pre-trade risk caps (fat-finger, dust, per-account)
  • Anti-spoofing: min resting time, order-to-trade ratio
  • Mark-price step + depth bounds; self-output guardrail
  • Surveillance: marking-close, ramping, pinging, cross-book
  • Halt / cancel-only states; enforcing gateway
  • Grounded in a threat model ↗
  • Market data

  • L1 top-of-book
  • L2 aggregated depth
  • L3 / MBO (order-by-order)
  • Snapshots + sequence numbers
  • Trade tape (time & sales)
  • Why it’s production-grade

    Money is never a float

    Prices and quantities are `int64` ticks and lots — a per-symbol `Instrument` converts decimals only at the boundary. No binary rounding error creeping into balances, and an overflow guard rejects any order whose notional would wrap.

    Deterministic & replayable

    The same ordered input always produces byte-identical trades and state. No wall-clock or RNG in the matching path — so you can record a session and replay it exactly (verified by a record→replay→identical-digest test).

    Fast, with real numbers

    O(1) best bid/ask, O(1) cancel, O(log n) inserts via a map + binary-search price ladder. Measured: 6 ns top-of-book reads, \~2.8M match round-trips/s per core, and 0 allocations on the submit/cancel/match hot path. Benchmarks run in CI on every push.

    Tested hard

    Race, fuzz, soak, and replay-recovery suites under the race detector, plus invariant checks (the book never crosses, quantity is conserved, FIFO holds). Green on every push.

    Embeddable & layered

    The core (`types` · `orderbook` · `matching`) is dependency-light and imports nothing above it. Drop it into your service; add only what you need on top.

    How it handles things

    Each side is a `map[price]→level` plus a sorted price ladder; each level is a FIFO queue (that’s time priority). One writer per book keeps it correct; you scale out across symbols. IDs and timestamps are injected where determinism requires it.

    Use it in your project

    Install:

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

    Create an engine, submit orders, read the book:

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

    // A resting sell (maker) — integer ticks & lots ask, _ := types.NewOrder("alice", "BTC-USD", types.SideSell, types.OrderTypeLimit, 30000, 5, types.TIFGoodTillCancel) eng.Process(ask)

    // A crossing buy (taker) — trades against it bid, _ := types.NewOrder("bob", "BTC-USD", types.SideBuy, types.OrderTypeLimit, 30000, 3, types.TIFGoodTillCancel) res := eng.Process(bid)

    for _, t := range res.Trades { fmt.Printf("%d @ %d\n", t.Quantity, t.Price) // 3 @ 30000 } best, qty, _ := eng.BestAsk() // 30000 x 2 left

    Runnable examples:

    go run ./examples/basic     # place & match
    go run ./examples/signals   # book imbalance + OFI
    go run ./cmd/obdemo         # end-to-end demo

    Docs:

  • Documentation — design, internals, features, benchmarks
  • API reference — pkg.go.dev
  • Order books from scratch
  • Source & issues
⭐ Star it on GitHub

Comments (0)

No comments yet