Rust-backed Python package for target-weight backtests, portfolio metrics, deterministic order-book simulation, and pre-trade risk checks
Project description
nanobook
Rust execution layer for Python trading strategies.
nanobook is for traders and researchers who already generate signals or target weights in Python, but want execution mechanics handled by compiled, deterministic Rust code: portfolio accounting, transaction costs, stops, limit-order-book simulation, pre-trade risk checks, and optional IBKR rebalancing.
Keep factor research, sizing, and scheduling in Python. Use nanobook for the stateful execution layer around it.
Architecture
┌─────────────────────────────────────────────────┐
│ Your Python Strategy (private) │
│ Factors · Signals · Sizing · Scheduling │
├─────────────────────────────────────────────────┤
│ nanobook (Rust, open-source) │
│ ┌──────────┬──────────┬──────────┬──────────┐ │
│ │ Broker │ Risk │Portfolio │ LOB │ │
│ │ IBKR │ Engine │Simulator │ Engine │ │
│ │ Binance │ PreTrade │ Backtest │ 6M ops/s │ │
│ └──────────┴──────────┴──────────┴──────────┘ │
│ Rebalancer CLI: weights → diff → execute │
└─────────────────────────────────────────────────┘
Use Cases
- Backtest target-weight strategies from Python with Rust portfolio accounting.
- Simulate rebalances, transaction costs, fixed/trailing stops, and portfolio metrics.
- Test limit-order-book behavior with deterministic matching and event logs.
- Run pre-trade risk checks for concentration, leverage, and short exposure.
- Rebalance an IBKR account from a target-weight file with dry-run and audit logs.
What nanobook is NOT
- Not a full trading platform. For venue breadth, calendars, and operator UIs, see NautilusTrader or LEAN.
- Not a connector zoo. For broad crypto exchange coverage, see CCXT or Hummingbot.
- Not a research framework. For vectorized backtests and factor research, see vectorbt or Riskfolio-Lib.
- Not FIX. No FIX 4.4 / 5.0 adapter and none is planned.
- Not an OMS (yet). Event-sourced OMS with deterministic replay is on the v1.0 roadmap.
nanobook is a compact Rust execution kernel for Python strategies: limit-order-book matching, portfolio simulation, broker abstraction, pre-trade risk, and rebalancer, all in one MIT-licensed workspace.
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
| Crate | Description |
|---|---|
nanobook |
Core Rust crate: deterministic LOB, portfolio simulator, metrics, backtest bridge, GARCH, optimizers |
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:
pip install nanobook
Rust:
[dependencies]
nanobook = "0.9.3"
From source:
git clone https://github.com/ricardofrantz/nanobook
cd nanobook
cargo build --release
cargo test
# Python bindings
cd python && maturin develop --release
# Binance adapter (feature-gated, not in PyPI wheels)
cd python && maturin develop --release --features binance
The Bridge: Python Strategy → Rust Execution
The canonical integration pattern — Python computes a weight schedule, Rust simulates the portfolio and returns metrics:
import nanobook
result = nanobook.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. backtest_weights() handles rebalancing,
cost modeling, position tracking, and return computation at compiled speed
with the GIL released.
v0.9 additions: fixed-parameter EWMA-style GARCH forecasting, portfolio optimizers (min-variance, max-Sharpe, risk-parity, inverse CVaR, inverse CDaR), and trailing/fixed stop-loss simulation — all accessible from Python.
Optimizer Example
import nanobook
import numpy as np
# Daily returns matrix (T × N)
returns = np.random.randn(252, 5) * 0.01
weights = nanobook.optimize_max_sharpe(returns, risk_free_rate=0.0)
print(dict(zip(["A","B","C","D","E"], weights)))
Layer Examples
LOB Engine (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)
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)
# 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
# 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 (macOS arm64, v0.10.0, stock clocks):
| Operation | Latency | Throughput |
|---|---|---|
| Submit (no match) | ~155 ns | ~6.4M ops/sec |
| Submit (with match) | ~197 ns | ~5M ops/sec |
| BBO query | ~1.1 ns | ~900M ops/sec |
| Cancel (tombstone, deep queue) | ~385 ns | ~2.6M ops/sec |
| L2 snapshot (10 levels) | ~255 ns | ~4M ops/sec |
Numbers are criterion medians measured with cargo bench --bench throughput.
Hardware, build flags, and background load all move these ±10-20 %. See
benches/README.md for the methodology and benches/v0.10-comparison.md
for the v0.9.3 → v0.10.0 delta (the v0.10.0 submit path pays a ~20 ns cost
for the new self-trade-prevention field even with STP off — a future
revision will lift the off-path check out of the matching loop).
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.
cargo bench
Feature Flags
| Feature | Default | Description |
|---|---|---|
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
- Full developer reference is merged below in this README (
## Full Reference (Merged from DOC.md)). - docs.rs — Rust API docs
License
MIT
Full Reference (Merged from DOC.md)
Developer Reference — Full API documentation for the nanobook workspace.
Table of Contents
- Quick Start
- Core Concepts
- Exchange API
- Types Reference
- Book Snapshots
- Stop Orders & Trailing Stops
- Event Replay
- Symbol & MultiExchange
- Portfolio Engine
- Strategy Trait
- Backtest Bridge
- Broker Abstraction
- Risk Engine
- Rebalancer CLI
- Python Bindings
- Book Analytics
- Persistence & Serde
- CLI Reference
- Performance
- Comparison with Other Rust LOBs
- Design Constraints
Quick Start
[dependencies]
nanobook = "0.9"
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));
Core Concepts
Prices
Prices are integers in the smallest currency unit (cents for USD), avoiding floating-point errors.
let price = Price(100_50); // $100.50
assert!(Price(100_00) < Price(101_00));
Display formats as dollars: Price(10050) prints as $100.50.
Constants: Price::ZERO, Price::MAX (market buys), Price::MIN (market sells).
Quantities and Timestamps
Quantity = u64— shares or contracts, always positive.Timestamp = u64— monotonic nanosecond counter (not system clock), guaranteeing deterministic ordering.
Determinism
No randomness anywhere. Same sequence of operations always produces identical trades. Event replay reconstructs exact state.
Exchange API
Exchange is the main entry point, wrapping an OrderBook with order submission, cancellation, modification, and queries.
Order Submission
// Limit order — matches against opposite side, remainder handled by TIF
let result = exchange.submit_limit(Side::Buy, Price(100_00), 100, TimeInForce::GTC);
// Market order — IOC semantics at Price::MAX (buy) or Price::MIN (sell)
let result = exchange.submit_market(Side::Buy, 500);
Order Management
// Cancel — O(1) via tombstones
let result = exchange.cancel(order_id); // CancelResult { success, cancelled_quantity, error }
// Modify — cancel + replace (loses time priority, gets new OrderId)
let result = exchange.modify(order_id, Price(101_00), 200);
Queries
let (bid, ask) = exchange.best_bid_ask(); // L1 — O(1)
let spread = exchange.spread(); // Option<i64>
let snap = exchange.depth(10); // L2 — top 10 levels
let full = exchange.full_book(); // L3 — everything
let order = exchange.get_order(OrderId(1)); // Option<&Order>
let trades = exchange.trades(); // &[Trade]
Memory Management
exchange.clear_trades(); // Clear trade history
exchange.clear_order_history(); // Remove filled/cancelled orders
exchange.compact(); // Reclaim tombstone memory
Input Validation
The try_submit_* methods validate inputs before processing:
let err = exchange.try_submit_limit(Side::Buy, Price(0), 100, TimeInForce::GTC);
assert_eq!(err.unwrap_err(), ValidationError::ZeroPrice);
Time-in-Force Semantics
| TIF | Partial Fill? | Rests on Book? | No Liquidity |
|---|---|---|---|
| GTC | Yes | Yes (remainder) | Rests entirely |
| IOC | Yes | No (remainder cancelled) | Cancelled |
| FOK | No | No (all-or-nothing) | Cancelled |
Types Reference
| Type | Definition | Description | Display |
|---|---|---|---|
Price |
struct Price(pub i64) |
Price in smallest units (cents) | $100.50 |
Quantity |
type Quantity = u64 |
Number of shares/contracts | — |
OrderId |
struct OrderId(pub u64) |
Unique order identifier | O42 |
TradeId |
struct TradeId(pub u64) |
Unique trade identifier | T7 |
Timestamp |
type Timestamp = u64 |
Nanosecond counter (not wall clock) | — |
Result Types
pub struct SubmitResult {
pub order_id: OrderId,
pub status: OrderStatus, // New | PartiallyFilled | Filled | Cancelled
pub trades: Vec<Trade>,
pub filled_quantity: Quantity,
pub resting_quantity: Quantity,
pub cancelled_quantity: Quantity,
}
pub struct Trade {
pub id: TradeId,
pub price: Price, // Resting order's price (aggressor gets price improvement)
pub quantity: Quantity,
pub aggressor_order_id: OrderId,
pub passive_order_id: OrderId,
pub aggressor_side: Side,
pub timestamp: Timestamp,
}
Enums
| Enum | Variants | Key Methods |
|---|---|---|
Side |
Buy, Sell |
opposite() |
TimeInForce |
GTC, IOC, FOK |
can_rest(), allows_partial() |
OrderStatus |
New, PartiallyFilled, Filled, Cancelled |
is_active(), is_terminal() |
Book Snapshots
pub struct BookSnapshot {
pub bids: Vec<LevelSnapshot>, // Highest price first
pub asks: Vec<LevelSnapshot>, // Lowest price first
pub timestamp: Timestamp,
}
pub struct LevelSnapshot {
pub price: Price,
pub quantity: Quantity,
pub order_count: usize,
}
| Method | Returns |
|---|---|
snap.best_bid() / best_ask() |
Option<Price> |
snap.spread() |
Option<i64> |
snap.mid_price() |
Option<f64> |
snap.total_bid_quantity() / total_ask_quantity() |
Quantity |
snap.imbalance() |
Option<f64> — [-1.0, 1.0], positive = buy pressure |
snap.weighted_mid() |
Option<f64> — leans toward less liquid side |
Stop Orders & Trailing Stops
Stop Orders
// Stop-market: triggers market order when last trade price hits stop
exchange.submit_stop_market(Side::Sell, Price(95_00), 100);
// Stop-limit: triggers limit order at limit_price when stop hits
exchange.submit_stop_limit(Side::Sell, Price(95_00), Price(94_50), 100, TimeInForce::GTC);
| Side | Triggers When |
|---|---|
| Buy stop | last_trade_price >= stop_price |
| Sell stop | last_trade_price <= stop_price |
Key behaviors: immediate trigger if price already past stop, cascade up to 100 iterations, cancel via exchange.cancel(stop_id).
Trailing Stops
Three trailing methods — stop price tracks the market and only moves in the favorable direction:
// Fixed: triggers if price drops $2.00 from peak
exchange.submit_trailing_stop_market(Side::Sell, Price(98_00), 100, TrailMethod::Fixed(200));
// Percentage: trail by 5% from peak
exchange.submit_trailing_stop_market(Side::Sell, Price(95_00), 100, TrailMethod::Percentage(0.05));
// Adaptive trail: 2x simple moving average of |Δ price| over the last
// 14 trades. NOT Wilder's ATR (no OHLC available at the stop module);
// for true Wilder ATR, pre-compute via `indicators::atr` on bar data
// and pass the result as `TrailMethod::Fixed(offset_cents)`.
exchange.submit_trailing_stop_market(Side::Sell, Price(95_00), 100,
TrailMethod::SmaAbsChange { multiplier: 2.0, period: 14 });
Trailing stop-limit variant: submit_trailing_stop_limit() — same parameters plus limit_price and TimeInForce.
Event Replay
Feature flag: event-log (enabled by default)
Every operation is recorded as an Event. Replaying events on a fresh exchange produces identical state.
// Save events
let events = exchange.events().to_vec();
// Reconstruct exact state
let replayed = Exchange::replay(&events);
assert_eq!(exchange.best_bid_ask(), replayed.best_bid_ask());
Event types: SubmitLimit, SubmitMarket, Cancel, Modify.
Disable for max performance:
nanobook = { version = "0.9", default-features = false }
Symbol & MultiExchange
Symbol
Fixed-size instrument identifier. [u8; 8] inline — Copy, no heap allocation, max 8 ASCII bytes.
let sym = Symbol::new("AAPL");
assert!(Symbol::try_new("TOOLONGNAME").is_none());
MultiExchange
Independent per-symbol order books:
let mut multi = MultiExchange::new();
let aapl = Symbol::new("AAPL");
multi.get_or_create(&aapl).submit_limit(Side::Sell, Price(150_00), 100, TimeInForce::GTC);
for (sym, bid, ask) in multi.best_prices() {
println!("{sym}: bid={bid:?} ask={ask:?}");
}
Portfolio Engine
Feature flag: portfolio
Tracks cash, positions, costs, returns, and equity over time.
use nanobook::portfolio::{Portfolio, CostModel};
let cost = CostModel { commission_bps: 5, slippage_bps: 3, min_trade_fee: 1_00 };
let mut portfolio = Portfolio::new(1_000_000_00, cost);
// Rebalance to target weights
portfolio.rebalance_simple(&[(Symbol::new("AAPL"), 0.6)], &[(Symbol::new("AAPL"), 150_00)]);
// Record period return and compute metrics
portfolio.record_return(&[(Symbol::new("AAPL"), 155_00)]);
let metrics = compute_metrics(portfolio.returns(), 252.0, 0.0);
Execution Modes
- SimpleFill — instant at bar prices:
portfolio.rebalance_simple(targets, prices) - LOBFill — route through
Exchangematching engines:portfolio.rebalance_lob(targets, exchanges)
Position
Per-symbol tracking with VWAP entry price and realized PnL:
let mut pos = Position::new(Symbol::new("AAPL"));
pos.apply_fill(100, 150_00); // buy 100 @ $150
pos.apply_fill(-50, 160_00); // sell 50 @ $160 → $500 realized PnL
Financial Metrics
compute_metrics(&returns, periods_per_year, risk_free) returns: total_return, cagr, volatility, sharpe, sortino, max_drawdown, calmar, num_periods, winning_periods, losing_periods.
Parallel Sweep
Feature flag: parallel (implies portfolio)
use nanobook::portfolio::sweep::sweep;
let results = sweep(¶ms, 12.0, 0.0, |&leverage| {
vec![0.01 * leverage, -0.005 * leverage]
});
Strategy Trait
Feature flag: portfolio
Implement compute_weights() for batch-oriented backtesting:
impl Strategy for MomentumStrategy {
fn compute_weights(
&self,
bar_index: usize,
prices: &[(Symbol, i64)],
_portfolio: &Portfolio,
) -> Vec<(Symbol, f64)> {
if bar_index < self.lookback { return vec![]; }
let w = 1.0 / prices.len() as f64;
prices.iter().map(|(sym, _)| (*sym, w)).collect()
}
}
let result = run_backtest(&strategy, &price_series, 1_000_000_00, CostModel::zero(), 12.0, 0.0);
Built-in: EqualWeight strategy. Parallel variant: sweep_strategy().
Backtest Bridge
The bridge between Python strategy code and Rust execution. Python computes a weight schedule, Rust simulates the portfolio at compiled speed.
Rust API
use nanobook::backtest_bridge::backtest_weights;
let result = backtest_weights(
&weight_schedule, // &[Vec<(Symbol, f64)>] — target weights per period
&price_schedule, // &[Vec<(Symbol, i64)>] — prices per period
1_000_000_00, // initial cash in cents
15, // cost in basis points
252.0, // periods per year
0.0, // risk-free rate per period
);
Returns BacktestBridgeResult:
| Field | Type | Description |
|---|---|---|
returns |
Vec<f64> |
Per-period returns |
equity_curve |
Vec<i64> |
Equity at each period (cents) |
final_cash |
i64 |
Ending cash balance |
metrics |
Option<Metrics> |
Sharpe, Sortino, max drawdown, etc. |
holdings |
Vec<Vec<(Symbol, f64)>> |
Per-period holdings weights |
symbol_returns |
Vec<Vec<(Symbol, f64)>> |
Per-period close-to-close symbol returns |
stop_events |
Vec<BacktestStopEvent> |
Stop trigger metadata (index, symbol, price, reason) |
Python API
result = nanobook.py_backtest_weights(
weight_schedule=[[("AAPL", 0.5), ("MSFT", 0.5)], ...],
price_schedule=[[("AAPL", 185_00), ("MSFT", 370_00)], ...],
initial_cash=1_000_000_00,
cost_bps=15,
periods_per_year=252.0,
risk_free=0.0,
stop_cfg={"trailing_stop_pct": 0.05},
)
# result["returns"], result["equity_curve"], result["metrics"],
# result["holdings"], result["symbol_returns"], result["stop_events"]
GIL is released during computation for maximum throughput.
Clean aliases (no py_ prefix) are exported for new integrations:
backtest_weights, capabilities, garch_ewma_forecast,
inverse_cvar_weights, inverse_cdar_weights, and other optimizer helpers.
qtrade v0.4 Bridge Pattern
Capability probing contract used by calc.bridge:
import nanobook
def has_nanobook_feature(name: str) -> bool:
caps = set(nanobook.py_capabilities()) if hasattr(nanobook, "py_capabilities") else set()
if name in caps:
return True
symbol_map = {
"backtest_stops": "py_backtest_weights",
"garch_ewma_forecast": "py_garch_ewma_forecast",
"optimize_min_variance": "py_optimize_min_variance",
"optimize_max_sharpe": "py_optimize_max_sharpe",
"optimize_risk_parity": "py_optimize_risk_parity",
"inverse_cvar_weights": "py_inverse_cvar_weights",
"inverse_cdar_weights": "py_inverse_cdar_weights",
"backtest_holdings": "py_backtest_weights",
}
sym = symbol_map.get(name)
return bool(sym and hasattr(nanobook, sym))
Broker Abstraction
Crate: nanobook-broker
Generic trait over brokerages with concrete adapters for IBKR and Binance.
Broker Trait
pub trait Broker {
fn connect(&mut self) -> Result<(), BrokerError>;
fn disconnect(&mut self) -> Result<(), BrokerError>;
fn positions(&self) -> Result<Vec<Position>, BrokerError>;
fn account(&self) -> Result<Account, BrokerError>;
fn submit_order(&self, order: &BrokerOrder) -> Result<OrderId, BrokerError>;
fn order_status(&self, id: OrderId) -> Result<BrokerOrderStatus, BrokerError>;
fn cancel_order(&self, id: OrderId) -> Result<(), BrokerError>;
fn quote(&self, symbol: &Symbol) -> Result<Quote, BrokerError>;
}
Key Types
pub struct Position {
pub symbol: Symbol,
pub quantity: i64, // Positive = long, negative = short
pub avg_cost_cents: i64,
pub market_value_cents: i64,
pub unrealized_pnl_cents: i64,
}
pub struct Account {
pub equity_cents: i64,
pub buying_power_cents: i64,
pub cash_cents: i64,
pub gross_position_value_cents: i64,
}
pub struct BrokerOrder {
pub symbol: Symbol,
pub side: BrokerSide, // Buy or Sell
pub quantity: u64,
pub order_type: BrokerOrderType, // Market or Limit(Price)
}
pub struct Quote {
pub symbol: Symbol,
pub bid_cents: i64,
pub ask_cents: i64,
pub last_cents: i64,
pub volume: u64,
}
IBKR Adapter
Feature: ibkr
Connects to TWS/Gateway via the ibapi crate (blocking API).
let mut broker = IbkrBroker::new("127.0.0.1", 4002, 1); // 4002 = paper, 4001 = live
broker.connect()?;
let positions = broker.positions()?;
let quote = broker.quote(&Symbol::new("AAPL"))?;
Binance Adapter
Feature: binance
REST API via reqwest::blocking. Converts nanobook symbols (e.g., "BTC") to Binance pairs (e.g., "BTCUSDT").
let mut broker = BinanceBroker::new(api_key, secret_key, true); // testnet
broker.connect()?;
Python
broker = nanobook.IbkrBroker("127.0.0.1", 4002, client_id=1)
broker.connect()
positions = broker.positions() # List[Dict] with symbol, quantity, avg_cost_cents, ...
oid = broker.submit_order("AAPL", "buy", 100, order_type="limit", limit_price_cents=185_00)
quote = broker.quote("AAPL") # Dict with bid_cents, ask_cents, last_cents, volume
broker = nanobook.BinanceBroker(api_key, secret_key, testnet=True, quote_asset="USDT")
Risk Engine
Crate: nanobook-risk
Pre-trade risk validation for single orders and rebalance batches.
RiskConfig
pub struct RiskConfig {
pub max_position_pct: f64, // Max single position as fraction of equity (default 0.25)
pub max_order_value_cents: i64, // Max single order value
pub max_batch_value_cents: i64, // Max rebalance batch value
pub max_leverage: f64, // Max gross exposure / equity (default 1.5)
pub max_drawdown_pct: f64, // Circuit breaker threshold (default 0.20)
pub allow_short: bool, // Allow short positions (default true)
pub max_short_pct: f64, // Max short exposure fraction (default 0.30)
pub min_trade_usd: f64,
pub max_trade_usd: f64, // Max single trade USD (default 100,000)
}
Notes:
max_drawdown_pctis validated at engine construction and preserved in config, but not yet used in execution-time checks.
Single Order Check
let engine = RiskEngine::new(RiskConfig::default());
let report = engine.check_order(
&Symbol::new("AAPL"),
BrokerSide::Buy,
100, // quantity
185_00, // price in cents
&account,
¤t_positions,
);
if report.has_failures() {
// Order violates risk limits — position concentration, short selling, etc.
}
Batch Check
Validates a full rebalance against position limits, leverage, and short exposure:
let report = engine.check_batch(
&orders, // &[(Symbol, BrokerSide, u64, i64)]
&account,
¤t_positions,
&target_weights, // &[(Symbol, f64)]
);
RiskReport
pub struct RiskReport {
pub checks: Vec<RiskCheck>,
}
pub struct RiskCheck {
pub name: &'static str,
pub status: RiskStatus, // Pass | Warn | Fail
pub detail: String,
}
impl RiskReport {
pub fn has_failures(&self) -> bool;
pub fn has_warnings(&self) -> bool;
}
Python
risk = nanobook.RiskEngine(max_position_pct=0.25, max_leverage=1.5)
# Single order
checks = risk.check_order("AAPL", "buy", 100, 185_00,
equity_cents=1_000_000_00,
positions=[("AAPL", 200)])
# Batch (full rebalance)
checks = risk.check_batch(
orders=[("AAPL", "buy", 100, 185_00), ("MSFT", "sell", 50, 370_00)],
equity_cents=1_000_000_00,
positions=[("AAPL", 200), ("MSFT", 100)],
target_weights=[("AAPL", 0.6), ("MSFT", 0.2)],
)
# Each check: {"name": "...", "status": "Pass|Warn|Fail", "detail": "..."}
Rebalancer CLI
Crate: nanobook-rebalancer
CLI tool that bridges target weights to IBKR execution with risk checks, rate limiting, and audit trail.
Pipeline
- Read target weights from
target.json(output of your optimizer) - Connect to IBKR Gateway for live positions, prices, account data
- Compute CURRENT → TARGET diff (share quantities, limit prices)
- Run pre-trade risk checks (position limits, leverage, short exposure)
- Show plan, confirm (or
--forcefor automation) - Execute limit orders with rate limiting and timeout-based cancellation
- Reconcile and log to JSONL audit trail
Commands
rebalancer status # Check IBKR connection
rebalancer positions # Show current positions
rebalancer run target.json # Plan → confirm → execute
rebalancer run target.json --dry-run # Plan only
rebalancer run target.json --force # Skip confirmation (cron/automation)
rebalancer reconcile target.json # Compare actual vs target
target.json
{
"timestamp": "2026-02-08T15:30:00Z",
"targets": [
{ "symbol": "AAPL", "weight": 0.40 },
{ "symbol": "MSFT", "weight": 0.30 },
{ "symbol": "SPY", "weight": -0.10 },
{ "symbol": "QQQ", "weight": 0.20 }
],
"constraints": {
"max_position_pct": 0.40,
"max_leverage": 1.5
}
}
Positive weights are long, negative are short. Symbols absent from the target but present in the account get closed. See rebalancer/config.toml.example for the full configuration reference.
Python Bindings
Install: pip install nanobook or cd python && maturin develop --release
Exchange
ex = nanobook.Exchange()
result = ex.submit_limit("buy", 10050, 100, "gtc")
result = ex.submit_market("sell", 50)
ex.cancel(result.order_id)
bid, ask = ex.best_bid_ask()
snap = ex.depth(10)
Stop Orders
ex.submit_stop_market("sell", 9500, 100)
ex.submit_stop_limit("buy", 10500, 10600, 100, "gtc")
ex.submit_trailing_stop_market("sell", 9500, 100, "percentage", 0.05)
Portfolio
portfolio = nanobook.Portfolio(1_000_000_00, nanobook.CostModel(commission_bps=10))
portfolio.rebalance_simple([("AAPL", 0.6)], [("AAPL", 150_00)])
portfolio.record_return([("AAPL", 155_00)])
metrics = portfolio.compute_metrics(252.0, 0.0)
Strategy Callback
result = nanobook.run_backtest(
strategy=lambda bar, prices, portfolio: [("AAPL", 0.5), ("GOOG", 0.5)],
price_series=[{"AAPL": 150_00, "GOOG": 280_00}] * 252,
initial_cash=1_000_000_00,
cost_model=nanobook.CostModel.zero(),
)
ITCH Parser
events = nanobook.parse_itch("data/sample.itch")
Book Analytics
Imbalance
let snap = exchange.depth(10);
if let Some(imb) = snap.imbalance() {
// [-1.0, 1.0]: positive = buy pressure
println!("Imbalance: {imb:.4}");
}
Weighted Midpoint
if let Some(wmid) = snap.weighted_mid() {
println!("Weighted mid: {wmid:.2}");
}
VWAP
if let Some(vwap) = Trade::vwap(exchange.trades()) {
println!("VWAP: {vwap}");
}
Persistence & Serde
Persistence
Feature flag: persistence (includes serde and event-log)
// Exchange — JSON Lines event sourcing
exchange.save(Path::new("orders.jsonl")).unwrap();
let loaded = Exchange::load(Path::new("orders.jsonl")).unwrap();
// Portfolio — JSON
portfolio.save_json(Path::new("portfolio.json")).unwrap();
let loaded = Portfolio::load_json(Path::new("portfolio.json")).unwrap();
Serde
Feature flag: serde
All public types derive Serialize/Deserialize: Price, OrderId, TradeId, Symbol, Side, TimeInForce, OrderStatus, Order, Trade, Event, SubmitResult, CancelResult, ModifyResult, BookSnapshot, LevelSnapshot, StopOrder, Position, CostModel, and more.
CLI Reference
Interactive REPL for the order book:
cargo run --bin lob
| Command | Example |
|---|---|
buy <price> <qty> [ioc|fok] |
buy 100.50 100 |
sell <price> <qty> [ioc|fok] |
sell 101.00 50 ioc |
market <buy|sell> <qty> |
market buy 200 |
stop <buy|sell> <price> <qty> |
stop buy 105.00 100 |
cancel <order_id> |
cancel 3 |
book / trades |
Show book or trade history |
save <path> / load <path> |
Persistence (requires feature) |
Performance
Benchmarks
Single-threaded (AMD Ryzen / Intel Core):
| Operation | Latency | Throughput | Complexity |
|---|---|---|---|
| Submit (no match) | ~155 ns | ~6.4M ops/sec | O(log P) |
| Submit (with match) | ~197 ns | ~5M ops/sec | O(log P + M) |
| BBO query | ~1.1 ns | ~900M ops/sec | O(1) |
| Cancel (tombstone, deep queue) | ~385 ns | ~2.6M ops/sec | O(1) |
| L2 snapshot (10 levels) | ~255 ns | ~4M ops/sec | O(D) |
Where P = price levels, M = orders matched, D = depth. Numbers are from
benches/v0.10-comparison.md on macOS arm64; expect ±10-20 % across
hardware and build flags.
Time Breakdown (Submit, No Match)
submit_limit() ~155 ns:
├── FxHashMap insert ~30 ns order storage
├── BTreeMap insert ~30 ns price level (O(log P))
├── VecDeque push ~5 ns FIFO queue
├── Event recording ~10 ns (optional, for replay)
├── STP branch ~20 ns `owner` field + policy read (Off path)
└── Overhead ~60 ns struct creation, dispatch, etc.
Optimizations
- O(1) cancel — Tombstone-based, 350x faster than linear scan
- FxHash — Non-cryptographic hash for OrderId lookups (+25% vs std HashMap)
- Cached BBO — Best bid/ask cached for O(1) access
- Optional event logging — disable
event-logfeature for max throughput
Rust vs Numba
Single-threaded throughput is roughly equivalent (both compile to LLVM IR). Where Rust wins: zero cold-start (vs Numba's ~300 ms JIT), true parallelism via Rayon with no GIL contention, and deterministic memory without GC pauses.
Comparison with Other Rust LOBs
| Library | Throughput | Order Types | Deterministic | Use Case |
|---|---|---|---|---|
| nanobook | ~6M ops/sec | Limit, Market, Stops, GTC/IOC/FOK | Yes | Strategy backtesting |
| limitbook | 3-5M ops/sec | Limit, Market | No | General purpose |
| lobster | ~300K ops/sec | Limit, Market | No | Simple matching |
| OrderBook-rs | 200K ops/sec | Many (iceberg, peg, etc.) | No | Production HFT |
Design Constraints
Engineering decisions that keep the system simple and fast:
| Constraint | Rationale |
|---|---|
| Single-threaded | Deterministic by design — same inputs always produce same outputs |
| In-process | No networking overhead; wrap externally if needed |
| No compliance | No self-trade prevention or circuit breakers (out of scope) |
| No complex orders | No iceberg or pegged orders |
| Integer prices | Fixed-point arithmetic avoids floating-point rounding |
| Statistics in Python | Spearman/IC/t-stat belong in scipy/Polars — proven, mature |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nanobook-0.10.0.tar.gz.
File metadata
- Download URL: nanobook-0.10.0.tar.gz
- Upload date:
- Size: 340.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2393ba4afedc1fc105a7d028a399efe13bcb6444262b1efd74ea5a316c15e48
|
|
| MD5 |
668b747f66f272c80c03f01394bef72a
|
|
| BLAKE2b-256 |
2e4a6c46c13b9e6ae077902ec6bc4634b48ea70deebfe9c347e2de83e7fe4392
|
Provenance
The following attestation bundles were made for nanobook-0.10.0.tar.gz:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0.tar.gz -
Subject digest:
f2393ba4afedc1fc105a7d028a399efe13bcb6444262b1efd74ea5a316c15e48 - Sigstore transparency entry: 1357060526
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 983.3 kB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f32d8c2a8d46f6aa0a7671b61765b990ada9e493290636953adf9ff997d9203a
|
|
| MD5 |
39af15e93894b42ce50756267075ca2d
|
|
| BLAKE2b-256 |
73cb23e590e3d71535e7270e56d24315bab31347a57875e6a580c5954d2350c5
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp314-cp314-win_amd64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp314-cp314-win_amd64.whl -
Subject digest:
f32d8c2a8d46f6aa0a7671b61765b990ada9e493290636953adf9ff997d9203a - Sigstore transparency entry: 1357060540
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0543fa741ea2c18ec835d9881afe1456f68034e4b4d2e79a5c3ed8f555224d5e
|
|
| MD5 |
43d843b041d3a99703987d433fafbdd3
|
|
| BLAKE2b-256 |
f4a909cda8a4985067faf846479b90070a5b55df8a92619c5a31a04d29f3a71f
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
0543fa741ea2c18ec835d9881afe1456f68034e4b4d2e79a5c3ed8f555224d5e - Sigstore transparency entry: 1357060577
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bc2d0c42e161e1f4283a32c6cc91ff06e59fb328269d4c7b78323d07c82625b
|
|
| MD5 |
8a094ab3ac1cb4d3ffb644317ca5b6eb
|
|
| BLAKE2b-256 |
c656a951da1ce8c39300c53f2943969dc80f8c4df2c42c73400e8767f286182b
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
8bc2d0c42e161e1f4283a32c6cc91ff06e59fb328269d4c7b78323d07c82625b - Sigstore transparency entry: 1357060568
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: nanobook-0.10.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.2 MB
- Tags: CPython 3.14, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c13da59e991b479df1472e158c5e518c38b40974f38aa2b01d6c84035d1b9a7a
|
|
| MD5 |
952f85aa15368f7bc853ca7d053297e8
|
|
| BLAKE2b-256 |
bfbda1ba59c72a68d9f25404d79a414dace268e6e47f8ffa744c378f74e9e072
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
c13da59e991b479df1472e158c5e518c38b40974f38aa2b01d6c84035d1b9a7a - Sigstore transparency entry: 1357060548
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddb48f3c33128483cc028413e49b79c042d3af12e4d5eeb68ba67dcd8adc7c85
|
|
| MD5 |
498074d18016fc5027a26080a484138f
|
|
| BLAKE2b-256 |
9cdbfe25107134eee19ca289ca62f570f6cf080d0b5b3b9252e6e45812ec664f
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
ddb48f3c33128483cc028413e49b79c042d3af12e4d5eeb68ba67dcd8adc7c85 - Sigstore transparency entry: 1357060586
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
35f88a6d2f55e22747b703863a3a94471218ce880c39d4894b0f1fb105b2dfd0
|
|
| MD5 |
bbfe546c69475964a49ade230ca2b3fd
|
|
| BLAKE2b-256 |
201dbe7e121caed0a1aeaab32520f8dadd25f7985d475d0e8eae2ba33b56bd07
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
35f88a6d2f55e22747b703863a3a94471218ce880c39d4894b0f1fb105b2dfd0 - Sigstore transparency entry: 1357060552
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: nanobook-0.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.2 MB
- Tags: CPython 3.13, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
279ae0b0db8a76e296e12c07e1d3c7e2c91779d9f440e252a223090f13be1f8d
|
|
| MD5 |
ceccf0637057325884b3f2f13f9a5581
|
|
| BLAKE2b-256 |
609528440731a61a15b64b173aee06beceb44f3012e380b8720f830558607281
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
279ae0b0db8a76e296e12c07e1d3c7e2c91779d9f440e252a223090f13be1f8d - Sigstore transparency entry: 1357060535
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
baf670d0011553c0e657b2c5a768124765fa26310949024c3f34a9796ddb0099
|
|
| MD5 |
a66c3f22909f69780a0e38edbff65de7
|
|
| BLAKE2b-256 |
ad832e4eefe362e8a9837a91794dd0efe63bb165064fa17f60aa01a0e1ad7c74
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
baf670d0011553c0e657b2c5a768124765fa26310949024c3f34a9796ddb0099 - Sigstore transparency entry: 1357060560
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb28a74a71d520d1aec8b5a36d1cd274c3957136a6b855bed2aa6be25bb21812
|
|
| MD5 |
8fa85851e85128b701366f6e1b84bcce
|
|
| BLAKE2b-256 |
150227b12b9aafa0cd0eecbff4502c4657bb7e3ff276efa667b6f1c6964e7484
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
fb28a74a71d520d1aec8b5a36d1cd274c3957136a6b855bed2aa6be25bb21812 - Sigstore transparency entry: 1357060531
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: nanobook-0.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.2 MB
- Tags: CPython 3.12, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e75311081892c3fa478877a0d978f4489d038eedd418e5231870de8b65072f42
|
|
| MD5 |
8606b621bd17a42027cd10ea60008ae3
|
|
| BLAKE2b-256 |
73cd76434fefa5731b9c7ba7b31807c611c9d5d2857b1c25f49d6cc12bcf33ea
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
e75311081892c3fa478877a0d978f4489d038eedd418e5231870de8b65072f42 - Sigstore transparency entry: 1357060571
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e0a0c07aeca6c0771a8ae8632b3967a14761e0bc753482ad23bcc0b40b443f6
|
|
| MD5 |
b2e112ad02a1bfac25cf43b313cee1eb
|
|
| BLAKE2b-256 |
63900decae0201ae10cdcb1585f87f05e8a4a863737f05edc7a1e1bf244a92d2
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
6e0a0c07aeca6c0771a8ae8632b3967a14761e0bc753482ad23bcc0b40b443f6 - Sigstore transparency entry: 1357060545
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: nanobook-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ed5de4de95792b77b07e621be1930ddebb9759ceb4d6d1ffb05dd85c638edee
|
|
| MD5 |
35765e1f5227db796a8f1035a810d966
|
|
| BLAKE2b-256 |
e3b8dc0411c4f2a12ecd7e7207ed6ebe9d026b9e0aa64d418f7a5bbb8b741e66
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
3ed5de4de95792b77b07e621be1930ddebb9759ceb4d6d1ffb05dd85c638edee - Sigstore transparency entry: 1357060590
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type:
File details
Details for the file nanobook-0.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: nanobook-0.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.2 MB
- Tags: CPython 3.11, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0921f37a09c9ea4032fde98413f00356554b07f8d1adaaa5679c221922941a8
|
|
| MD5 |
5080719bbef7b6822e3eace08f83655b
|
|
| BLAKE2b-256 |
d478d687ce3d419fa57e560569933be80639cb13b528daa9173b10aa6f05d6ea
|
Provenance
The following attestation bundles were made for nanobook-0.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:
Publisher:
wheels.yml on ricardofrantz/nanobook
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nanobook-0.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
a0921f37a09c9ea4032fde98413f00356554b07f8d1adaaa5679c221922941a8 - Sigstore transparency entry: 1357060562
- Sigstore integration time:
-
Permalink:
ricardofrantz/nanobook@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/ricardofrantz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
wheels.yml@4f68c7fb101b2f97ccb6d569cf6924bf2119c17e -
Trigger Event:
push
-
Statement type: