# nanobook
[](https://github.com/ricardofrantz/nanobook/actions/workflows/ci.yml)
[](https://crates.io/crates/nanobook)
[](https://docs.rs/nanobook)
[](LICENSE)
[](https://github.com/ricardofrantz/nanobook/actions/workflows/ci.yml)
[](https://github.com/ricardofrantz/nanobook/actions/workflows/ci.yml)
**Production-grade Rust execution infrastructure for automated trading.**
Zero-allocation hot paths. No panics on external input. MIRI-verified memory safety.
Python computes the strategy. nanobook handles everything else.
## Architecture
```
┌─────────────────────────────────────────────────┐
│ Your Python Strategy (private) │
│ Factors · Signals · Sizing · Scheduling │
├─────────────────────────────────────────────────┤
│ nanobook (Rust, open-source) │
│ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ Broker │ Risk │Portfolio │ LOB │ │
│ │ IBKR │ Engine │Simulator │ Engine │ │
│ │ Binance │ PreTrade │ Backtest │ 8M ops/s │ │
│ └──────────┴──────────┴──────────┴──────────┘ │
│ Rebalancer CLI: weights → diff → execute │
└─────────────────────────────────────────────────┘
```
Python computes **what** to trade — factor rankings, signals, target weights.
nanobook executes **how** — order routing, risk checks, portfolio simulation,
and a deterministic matching engine. Clean separation: strategy logic stays
in Python, execution runs in Rust.
## Workspace
| `nanobook` | LOB matching engine, portfolio simulator, backtest bridge |
| `nanobook-broker` | Broker trait with IBKR and Binance adapters |
| `nanobook-risk` | Pre-trade risk engine (position limits, leverage, short exposure) |
| `nanobook-python` | PyO3 bindings for all layers |
| `nanobook-rebalancer` | CLI: target weights → IBKR execution with audit trail |
## Install
**Python:**
```bash
pip install nanobook
```
**Rust:**
```toml
[dependencies]
nanobook = "0.9"
```
**From source:**
```bash
git clone https://github.com/ricardofrantz/nanobook
cd nanobook
cargo build --release
cargo test
# Python bindings
cd python && maturin develop --release
```
## The Bridge: Python Strategy → Rust Execution
The canonical integration pattern — Python computes a weight schedule,
Rust simulates the portfolio and returns metrics:
```python
import nanobook
result = nanobook.py_backtest_weights(
weight_schedule=[
[("AAPL", 0.5), ("MSFT", 0.5)],
[("AAPL", 0.3), ("NVDA", 0.7)],
],
price_schedule=[
[("AAPL", 185_00), ("MSFT", 370_00)],
[("AAPL", 190_00), ("MSFT", 380_00), ("NVDA", 600_00)],
],
initial_cash=1_000_000_00, # $1M in cents
cost_bps=15, # 15 bps round-trip
stop_cfg={"trailing_stop_pct": 0.05},
)
print(f"Sharpe: {result['metrics'].sharpe:.2f}")
print(f"Max DD: {result['metrics'].max_drawdown:.1%}")
print(result["holdings"][-1]) # per-period symbol weights
print(result["stop_events"]) # stop trigger metadata
```
Your optimizer produces weights. `py_backtest_weights()` handles rebalancing,
cost modeling, position tracking, and return computation at compiled speed
with the GIL released.
Clean aliases are also available for new callers:
`backtest_weights`, `capabilities`, `garch_forecast`, `optimize_*`.
### qtrade v0.4 Capability Gating
Use `py_capabilities()` and keep fallback logic in `calc.bridge`:
```python
import nanobook
def has_nanobook() -> bool:
try:
import nanobook as _nb # noqa: F401
return True
except Exception:
return False
def nanobook_version() -> str | None:
return getattr(nanobook, "__version__", None) if has_nanobook() else None
def has_nanobook_feature(name: str) -> bool:
if not has_nanobook():
return False
caps = set(nanobook.py_capabilities()) if hasattr(nanobook, "py_capabilities") else set()
if name in caps:
return True
# Symbol fallback for older builds
symbol_map = {
"backtest_stops": "py_backtest_weights",
"garch_forecast": "py_garch_forecast",
"optimize_min_variance": "py_optimize_min_variance",
"optimize_max_sharpe": "py_optimize_max_sharpe",
"optimize_risk_parity": "py_optimize_risk_parity",
"optimize_cvar": "py_optimize_cvar",
"optimize_cdar": "py_optimize_cdar",
"backtest_holdings": "py_backtest_weights",
}
sym = symbol_map.get(name)
return bool(sym and hasattr(nanobook, sym))
```
## Layer Examples
### LOB Engine (Rust)
```rust
use nanobook::{Exchange, Side, Price, TimeInForce};
let mut exchange = Exchange::new();
exchange.submit_limit(Side::Sell, Price(50_00), 100, TimeInForce::GTC);
let result = exchange.submit_limit(Side::Buy, Price(50_00), 100, TimeInForce::GTC);
assert_eq!(result.trades.len(), 1);
assert_eq!(result.trades[0].price, Price(50_00));
```
### Portfolio + Metrics (Python)
```python
portfolio = nanobook.Portfolio(1_000_000_00, nanobook.CostModel(commission_bps=5))
portfolio.rebalance_simple([("AAPL", 0.6)], [("AAPL", 150_00)])
portfolio.record_return([("AAPL", 155_00)])
metrics = portfolio.compute_metrics(252.0, 0.0)
print(f"Sharpe: {metrics.sharpe:.2f}")
```
### Broker + Risk (Python)
```python
# Pre-trade risk check
risk = nanobook.RiskEngine(max_position_pct=0.25, max_leverage=1.5)
checks = risk.check_order("AAPL", "buy", 100, 185_00,
equity_cents=1_000_000_00,
positions=[("AAPL", 200)])
# Execute through IBKR
broker = nanobook.IbkrBroker("127.0.0.1", 4002, client_id=1)
broker.connect()
oid = broker.submit_order("AAPL", "buy", 100, order_type="limit",
limit_price_cents=185_00)
```
### Rebalancer CLI
```bash
# Build
cargo build -p nanobook-rebalancer --release
# Dry run — show plan without executing
rebalancer run target.json --dry-run
# Execute with confirmation prompt
rebalancer run target.json
# Compare actual vs target positions
rebalancer reconcile target.json
```
## Performance
Single-threaded benchmarks (AMD Ryzen / Intel Core):
| Submit (no match) | 120 ns | 8.3M ops/sec |
| Submit (with match) | ~200 ns | 5M ops/sec |
| BBO query | ~1 ns | 1B ops/sec |
| Cancel (tombstone) | 170 ns | 5.9M ops/sec |
| L2 snapshot (10 levels) | ~500 ns | 2M ops/sec |
Single-threaded throughput is roughly equivalent to Numba (both compile to
LLVM IR). Where Rust wins: zero cold-start, true parallelism via Rayon with
no GIL contention, and deterministic memory without GC pauses.
```bash
cargo bench
```
## Feature Flags
| `event-log` | Yes | Event recording for deterministic replay |
| `serde` | No | Serialize/deserialize all public types |
| `persistence` | No | File-based event sourcing (JSON Lines) |
| `portfolio` | No | Portfolio engine, position tracking, metrics, strategy trait |
| `parallel` | No | Rayon-based parallel parameter sweeps |
| `itch` | No | NASDAQ ITCH 5.0 binary protocol parser |
## Design Constraints
Engineering decisions that keep the system simple and fast:
- **Single-threaded** — deterministic by design; same inputs always produce same outputs
- **In-process** — no networking overhead; wrap externally if needed
- **No compliance layer** — no self-trade prevention or circuit breakers (out of scope)
- **No complex order types** — no iceberg or pegged orders
## Documentation
- **[DOC.md](DOC.md)** — Developer reference: full API, types, patterns, advanced usage
- **[docs.rs](https://docs.rs/nanobook)** — Rust API docs
## License
MIT