Documentation Index
Fetch the complete documentation index at: https://mintlify.com/dhir1007/nanoARB/llms.txt
Use this file to discover all available pages before exploring further.
Overview
NanoARB implements a high-performance limit order book (LOB) designed for HFT applications. The order book maintains up to 20 price levels on each side (bid/ask) with efficient O(log n) update complexity using Rust’s BTreeMap data structure.
Core Design
The order book is implemented in nano-lob/src/orderbook.rs:48 and consists of:
- Bid side: Stored in descending order by price (highest bid = best bid)
- Ask side: Stored in ascending order by price (lowest ask = best ask)
- Maximum 20 levels per side (configurable via
MAX_BOOK_LEVELS)
- Fast updates: O(log n) insert/delete operations
pub struct OrderBook {
instrument_id: u32,
bids: BTreeMap<i64, BookLevel>,
asks: BTreeMap<i64, BookLevel>,
timestamp: Timestamp,
sequence: u32,
exponent: i8,
update_count: u64,
}
Book Levels
Each price level contains detailed market depth information:
pub struct BookLevel {
pub price: Price, // Price at this level
pub quantity: Quantity, // Total quantity available
pub order_count: u32, // Number of orders
pub last_update: Timestamp, // Last update time
}
Applying Updates
The order book processes market data updates from CME MDP 3.0 and other feeds:
Snapshot Processing
Snapshots rebuild the entire book state:
pub fn apply_snapshot(&mut self, snapshot: &Snapshot) {
self.bids.clear();
self.asks.clear();
self.sequence = snapshot.rpt_seq;
self.exponent = snapshot.exponent;
for entry in &snapshot.entries {
let level = BookLevel::new(
Price::from_raw(entry.price),
Quantity::new(entry.quantity.max(0) as u32),
entry.num_orders as u32,
self.timestamp,
);
match entry.entry_type {
EntryType::Bid | EntryType::ImpliedBid => {
self.bids.insert(entry.price, level);
}
EntryType::Offer | EntryType::ImpliedOffer => {
self.asks.insert(entry.price, level);
}
_ => {}
}
}
self.trim_levels();
}
Incremental Updates
Supports multiple update actions:
- New/Change/Overlay: Add or update a price level
- Delete: Remove a specific price level
- DeleteThru: Remove all levels through a price
- DeleteFrom: Remove all levels from a price
match entry.action {
UpdateAction::New | UpdateAction::Change | UpdateAction::Overlay => {
if quantity.value() > 0 {
book_side.insert(price, level);
} else {
book_side.remove(&price);
}
}
UpdateAction::Delete => {
book_side.remove(&price);
}
UpdateAction::DeleteThru => {
if is_bid {
book_side.retain(|&p, _| p > price);
} else {
book_side.retain(|&p, _| p < price);
}
}
}
Accessing Book Data
Best Bid/Ask (BBO)
// Get the best bid and ask
let (bid_price, bid_qty) = book.best_bid()?;
let (ask_price, ask_qty) = book.best_ask()?;
// Calculate mid price
let mid = book.mid_price()?;
// Calculate spread
let spread = book.spread()?;
Level Access
Access specific depth levels (0 = best):
// Get second-best bid (index 1)
if let Some(level) = book.bid_level(1) {
println!("L2 bid: {} @ {}", level.quantity, level.price);
}
// Iterate all bid levels (best to worst)
for level in book.bid_levels() {
println!("{} @ {}", level.quantity, level.price);
}
Depth Calculation
Calculate total quantity across multiple levels:
// Get total bid quantity for top 5 levels
let total_bid = book.total_bid_quantity(5);
// Get total ask quantity for top 5 levels
let total_ask = book.total_ask_quantity(5);
VWAP Calculation
Volume-weighted average price for market impact estimation:
// Calculate VWAP for buying 150 contracts
let vwap = book.vwap(Side::Buy, Quantity::new(150))?;
// This walks through ask levels:
// 100 @ 10000 + 50 @ 10010 = VWAP of 10003
From nano-lob/src/orderbook.rs:300:
pub fn vwap(&self, side: Side, quantity: Quantity) -> Option<Price> {
let levels: Vec<_> = match side {
Side::Buy => self.ask_levels().collect(),
Side::Sell => self.bid_levels().collect(),
};
let mut remaining = quantity.value();
let mut total_value: i64 = 0;
let mut total_qty: u32 = 0;
for level in levels {
if remaining == 0 { break; }
let fill_qty = remaining.min(level.quantity.value());
total_value += level.price.raw() * i64::from(fill_qty);
total_qty += fill_qty;
remaining -= fill_qty;
}
if total_qty > 0 {
Some(Price::from_raw(total_value / i64::from(total_qty)))
} else {
None
}
}
Time Complexity
- Insert/Update: O(log n) via BTreeMap
- Delete: O(log n)
- Best bid/ask access: O(1) amortized
- Level iteration: O(k) for k levels
Memory Efficiency
- Maximum 20 levels × 2 sides = 40 price levels
- Each
BookLevel is ~32 bytes
- Total memory per book: ~1.5 KB
Update Rate
The order book can handle:
- 1M+ updates/second on modern hardware
- Sub-microsecond update latency
- Suitable for CME market data (100K+ messages/sec)
Book Validation
Several validation methods ensure book integrity:
// Check if book has any data
if book.is_empty() {
// No bids or asks
}
// Check if book is valid (has both sides)
if book.is_valid() {
// Has at least one bid and one ask
}
// Check if book is crossed (bid >= ask)
if book.is_crossed() {
// Invalid state, needs investigation
}
Integration Example
use nano_lob::OrderBook;
use nano_feed::messages::BookUpdate;
let mut book = OrderBook::new(instrument_id);
// Apply market data updates
for update in feed.updates() {
book.apply_book_update(&update);
// Access current state
if let Some((bid, ask)) = book.quote() {
let spread_bps = (ask.price.raw() - bid.price.raw()) * 10000
/ bid.price.raw();
println!("Spread: {} bps", spread_bps);
}
}