SkillAgentSearch skills...

OrderBook Rs

A high-performance, thread-safe limit order book implementation written in Rust. This project provides a comprehensive order matching engine designed for low-latency trading systems, with a focus on concurrent access patterns and lock-free data structures.

Install / Use

npx skills add joaquinbejar/OrderBook-rs

Installs into whichever agent you are using.

About this skill

Quality Score

0/100

Category

Design

Supported Platforms

Universal

README

Dual License Crates.io Downloads Stars Issues PRs

Build Status Coverage Dependencies Documentation

High-Performance Lock-Free Order Book Engine

A high-performance, thread-safe limit order book implementation written in Rust. This project provides a comprehensive order matching engine designed for low-latency trading systems, with a focus on concurrent access patterns and lock-free data structures.

Key Features

  • Lock-Free Architecture: Built using atomics and lock-free data structures to minimize contention and maximize throughput in high-frequency trading scenarios.

  • Multiple Order Types: Support for various order types including standard limit orders, iceberg orders, post-only, fill-or-kill, immediate-or-cancel, good-till-date, trailing stop, pegged, market-to-limit, and reserve orders with custom replenishment logic.

  • Thread-Safe Price Levels: Each price level can be independently and concurrently modified by multiple threads without blocking.

  • Advanced Order Matching: Efficient matching algorithm for both market and limit orders, correctly handling complex order types and partial fills.

  • Performance Metrics: Built-in statistics tracking for benchmarking and monitoring system performance.

  • Memory Efficient: Designed to scale to millions of orders with minimal memory overhead.

Design Goals

This order book engine is built with the following design principles:

  1. Correctness: Ensure that all operations maintain the integrity of the order book, even under high concurrency.
  2. Performance: Optimize for low latency and high throughput in both write-heavy and read-heavy workloads.
  3. Scalability: Support for millions of orders and thousands of price levels without degradation.
  4. Flexibility: Easily extendable to support additional order types and matching algorithms.

Use Cases

  • Trading Systems: Core component for building trading systems and exchanges
  • Market Simulation: Tool for back-testing trading strategies with realistic market dynamics
  • Research: Platform for studying market microstructure and order flow
  • Educational: Reference implementation for understanding modern exchange architecture

What's New in Version 0.12.0

v0.12.0 — pricelevel 0.9 hardening bump; upsize demotion survives snapshot restore (#205)

  • pricelevel 0.8.4 → 0.9.1. Major upstream hardening release: level admission validates before mutating (duplicate id, counter capacity, price/side topology), PostOnly / fill-or-kill decisions are atomic with the sweep, execution statistics are torn-read-safe, and level snapshots materialize orders in queue-consumption order. 0.9.1 fixes the MatchResult bincode round-trip (PriceLevel#135), keeping the bincode feature's trade-event round-trip intact.
  • The upsize queue-priority demotion now survives a snapshot round-trip (#205). Restoring a snapshot rebuilds each level's queue exactly as matching would consume it, so an order demoted by a quantity increase keeps its back-of-queue position after restore_from_snapshot_package. Locked in by a proptest regression (tests/unit/props_quantity_update_priority.rs). Snapshots captured with pricelevel < 0.9 restore demoted orders at their old (timestamp, seq) position — re-snapshot to pin the corrected order.
  • Breaking (semver-minor under 0.x): get_bt_bids / get_bt_asks now return Result<BTreeMap<u128, PriceLevel>, OrderBookError> (snapshot-to-level conversion is validating and fallible upstream), and the re-exported pricelevel surface changed — PriceLevel::add_order returns Result, matchable_quantity takes the taker id, PriceLevelError gained DuplicateOrderId.
  • Atomic PostOnly / multi-level FOK (#209). PostOnly submits thread TakerKind::PostOnly into every per-level match, making it structurally impossible for a post-only order to take liquidity under any interleaving; fill-or-kill submits hold a new book-level submit gate exclusively across feasibility + sweep, so multi-level all-or-nothing can no longer partially execute against concurrent cancels. Other mutating entry points take the gate's uncontended read side; the matching core stays lock-free. Full 0.11.0 → 0.12.0 HDR tail-latency comparison in BENCH.md: every scenario's median is unchanged by this release's book-level work; the one median shift (stp_sweep, from the pricelevel 0.9 hardening) is documented there with its bisection.
  • Atomic, observable mutation failures (#211). UpdateQuantity is validate-first (projected tick / lot / min-max / representability / risk before touching the level), propagates upstream PriceLevelErrors instead of returning Ok(None), and updates risk counters on success; a taker whose residual cannot rest is rejected before the sweep trades; a failed racy admission cleans up any empty level it created.
  • Two-tranche quantity conservation (#210). An aggressive iceberg's residual rests with exactly the unmatched total distributed across tranches (visible = min(display, remainder), rest hidden) instead of inflating the book, and a visible + hidden overflow is rejected at admission with the new typed OrderBookError::QuantityOverflow before any trade or mutation. Conservation (executed + resting == submitted) is property-tested.
  • snapshots_match compares full maker state and FIFO (#208). The replay oracle now checks every level's order vector in queue-consumption order (ids, variants, users, quantities, timestamps, TIF, type-specific fields) and the deterministic statistics counters including stats_degraded; only the wall-time statistics aggregates (first_arrival_time, last_execution_time, sum_waiting_time — see the snapshots_match docs for why each is inherently divergent) and the capture timestamp stay excluded. Contract tightening: aggregate-equal books with reversed FIFO or different maker identity no longer certify as replay-equal.
  • Failure-atomic snapshot restore (#207). restore_from_snapshot and restore_from_snapshot_package validate every level (and reject cross-level duplicate order ids with DuplicateOrderId) against off-book structures before clearing the live book, so a failed restore leaves the pre-restore state — orders, indices, config, risk, kill-switch, engine sequence — completely untouched.
  • Snapshot package format v3 (#206). Pricelevel 0.9 statistics can serialize a stats_degraded field that 0.8 readers reject, so newly written packages are stamped ORDERBOOK_SNAPSHOT_FORMAT_VERSION = 3. Reads accept ORDERBOOK_SNAPSHOT_MIN_READ_VERSION (2)..=3 — legacy v2 packages still restore — while 1 and future versions stay rejected with the existing typed error.

What's New in Version 0.11.0

v0.11.0 — replay reproduces the trade-ID stream: namespace in ReplayBookConfig (#200)

  • ReplayBookConfig.trade_id_namespace: Option<Uuid>. v0.10.5 (#199) made the trade-ID namespace injectable on OrderBook, but every ReplayEngine::replay_from* entry point still built its book with a random namespace, so trade IDs produced through the shipped replay API were not reproducible. The config now carries the live book's namespace and applies it via OrderBook::set_trade_id_namespace before any journal events are replayed; a *_with_config replay under an injected Clock then reproduces the live trade-ID stream byte-identically. ReplayBookConfig::new keeps its six structural parameters (namespace defaults to None) — chain the new with_trade_id_namespace(namespace) builder to set it. Without a namespace the fresh book keeps a random one, as before.
  • Suffix replays with a namespace are rejected. Applying a namespace restarts the trade-ID counter at 0, so a namespace-carrying config with from_sequence != 0 would mint wrong or duplicate IDs; the *_with_config entry points return the new typed ReplayError::NamespaceRequiresFullReplay instead. Namespace-free suffix replay keeps working.
  • Breaking (semver-minor under 0.x): ReplayBookConfig gained a public field, so exhaustive struct literals no longer compile — add trade_id_namespace: None or use ..Default::default(); and ReplayError gained the NamespaceRequiresFullReplay variant, so exhaustive matches need a new arm. ReplayBookConfig::new(...) callers are unaffected. No journal or snapshot format change, no ORDERBOOK_SNAPSHOT_FORMAT_VERSION bump.

What's New in Version 0.10.5

v0.10.5 — injectable trade-ID namespace (#199)

  • OrderBook::set_trade_id_namespace(&mut self, namespace: Uuid). Every constructor used to mint the trade-ID namespace internally with Uuid::new_v4(), so trade IDs differed bet

Related Skills

View on GitHub
GitHub Stars503
CategoryDesign
Updated19h ago
Forks89

Languages

Rust

Security Score

100/100

Audited on Aug 7, 2026

No findings