Expand description
§nanobook
A deterministic limit order book and matching engine for testing trading algorithms.
§Features
- Order types: Limit, Market, Cancel, Modify
- Time-in-force: GTC (Good-til-cancelled), IOC (Immediate-or-cancel), FOK (Fill-or-kill)
- Price-time priority: FIFO matching at each price level
- Deterministic replay: Record events and replay to reconstruct exact state
- Fixed-point prices: Avoid floating-point errors with integer cents
§Quick Start
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
// Place some resting asks (sell orders)
exchange.submit_limit(Side::Sell, Price(101_00), 100, TimeInForce::GTC);
exchange.submit_limit(Side::Sell, Price(102_00), 200, TimeInForce::GTC);
// Place a bid that crosses — this will match!
let result = exchange.submit_limit(Side::Buy, Price(101_00), 50, TimeInForce::GTC);
assert_eq!(result.filled_quantity, 50);
assert_eq!(result.trades.len(), 1);
assert_eq!(result.trades[0].price, Price(101_00));§Price Representation
Prices are stored as i64 in the smallest unit (e.g., cents):
use nanobook::Price;
let price = Price(100_50); // $100.50
assert_eq!(format!("{}", price), "$100.50");§Time-in-Force
| TIF | Behavior |
|---|---|
| GTC | Rests on book until filled or cancelled |
| IOC | Fill immediately, cancel unfilled remainder |
| FOK | Fill entirely or cancel entirely (no partial fills) |
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
// IOC: Fill what's available, cancel the rest
exchange.submit_limit(Side::Sell, Price(100_00), 30, TimeInForce::GTC);
let result = exchange.submit_limit(Side::Buy, Price(100_00), 100, TimeInForce::IOC);
assert_eq!(result.filled_quantity, 30);
assert_eq!(result.cancelled_quantity, 70);
// FOK: Must fill entirely or nothing happens
exchange.submit_limit(Side::Sell, Price(100_00), 50, TimeInForce::GTC);
let result = exchange.submit_limit(Side::Buy, Price(100_00), 100, TimeInForce::FOK);
assert_eq!(result.filled_quantity, 0); // Rejected: only 50 available
assert!(result.trades.is_empty());§Market Orders
Market orders execute at the best available prices:
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
exchange.submit_limit(Side::Sell, Price(100_00), 50, TimeInForce::GTC);
exchange.submit_limit(Side::Sell, Price(101_00), 50, TimeInForce::GTC);
// Market buy sweeps through price levels
let result = exchange.submit_market(Side::Buy, 75);
assert_eq!(result.trades.len(), 2);
assert_eq!(result.trades[0].price, Price(100_00)); // Best price first
assert_eq!(result.trades[1].price, Price(101_00));§Cancel and Modify
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
let order = exchange.submit_limit(Side::Buy, Price(99_00), 100, TimeInForce::GTC);
// Cancel: removes the order from the book
let cancel = exchange.cancel(order.order_id);
assert!(cancel.success);
// Modify: cancel-and-replace (new order gets new ID, loses time priority)
let order2 = exchange.submit_limit(Side::Buy, Price(99_00), 100, TimeInForce::GTC);
let modify = exchange.modify(order2.order_id, Price(98_00), 150);
assert!(modify.success);
assert_ne!(modify.new_order_id, Some(order2.order_id));§Event Replay
All operations are recorded as events for deterministic replay
(requires the event-log feature, enabled by default):
ⓘ
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
exchange.submit_limit(Side::Sell, Price(101_00), 100, TimeInForce::GTC);
exchange.submit_limit(Side::Buy, Price(100_00), 100, TimeInForce::GTC);
exchange.submit_limit(Side::Buy, Price(101_00), 50, TimeInForce::GTC);
// Save events
let events = exchange.events().to_vec();
// Replay on a fresh exchange — produces identical state
let replayed = Exchange::replay(&events);
assert_eq!(exchange.best_bid_ask(), replayed.best_bid_ask());
assert_eq!(exchange.trades().len(), replayed.trades().len());§Book Snapshots
Get market data snapshots:
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
exchange.submit_limit(Side::Buy, Price(99_00), 100, TimeInForce::GTC);
exchange.submit_limit(Side::Buy, Price(100_00), 200, TimeInForce::GTC);
exchange.submit_limit(Side::Sell, Price(101_00), 150, TimeInForce::GTC);
let snap = exchange.depth(10); // Top 10 levels each side
assert_eq!(snap.best_bid(), Some(Price(100_00)));
assert_eq!(snap.best_ask(), Some(Price(101_00)));
assert_eq!(snap.spread(), Some(100)); // $1.00Re-exports§
pub use multi_exchange::MultiExchange;pub use stop::StopBook;pub use stop::StopOrder;pub use stop::StopStatus;pub use stop::TrailMethod;
Modules§
- multi_
exchange - Multi-symbol exchange: one LOB per symbol.
- stop
- Stop orders: conditional orders triggered by trade price.
Structs§
- Apply
Result - Result of applying an event.
- Book
Snapshot - A snapshot of the order book at a point in time.
- Cancel
Result - Result of cancelling an order.
- Exchange
- The exchange: processes orders and maintains the order book.
- Level
- A queue of orders at a single price level.
- Level
Snapshot - A snapshot of a single price level.
- Match
Result - Result of matching an incoming order against the book.
- Modify
Result - Result of modifying an order.
- Order
- An order in the order book.
- Order
Book - The complete order book.
- OrderId
- Unique order identifier assigned by exchange.
- Price
- Price in smallest units (e.g., cents, basis points).
- Price
Levels - One side of the order book (all bids or all asks).
- Stop
Submit Result - Result of submitting a stop order.
- Submit
Result - Result of submitting an order.
- Symbol
- A fixed-size symbol identifier (e.g., “AAPL”, “MSFT”).
- Trade
- A completed trade between two orders.
- TradeId
- Unique trade identifier assigned by exchange.
Enums§
- Cancel
Error - Errors that can occur when cancelling an order.
- Event
- An event that can be applied to an exchange.
- Modify
Error - Errors that can occur when modifying an order.
- Order
Status - Status of an order in its lifecycle.
- Side
- Side of an order.
- Time
InForce - Time-in-force determines how long an order remains active and how partial fills are handled.
- Validation
Error - Errors returned by validated order submission methods.