Backtesting
The sim engine replays historical L2 book snapshots and trade ticks through your WASM algo, producing fills, PnL, and performance metrics. All replay is deterministic - same seed + same data = identical output.
Quick Start
# Build + backtest in one command
sequence backtest BTC-USD --start 2026-03-01 --end 2026-03-08
# Multi-symbol portfolio backtest
sequence backtest --symbols BTC-USD,ETH-USD --start 2026-03-01 --end 2026-03-08
# Direct sim-engine invocation
sim-engine run --wasm algo.wasm --symbol BTC-USD --start 2026-03-01 --end 2026-03-08 --capital 100000 --seed 42Multi-Symbol Mode
When using --symbols, events from all symbols are merged into a single timeline sorted by exchange timestamp. Your algo receives L2Book updates with symbol_id set:
fn on_book(&mut self, book: &L2Book, state: &AlgoState, _features: &OnlineFeatures, actions: &mut Actions) {
match book.symbol_id {
1 => { /* First symbol in --symbols list */ }
2 => { /* Second symbol */ }
_ => {}
}
}Each (symbol, venue) pair gets its own matching engine with independent queue state, latency sampling, and microstructure EMAs.
Realism Features
The sim engine includes configurable market microstructure models. All are off by default so existing backtests are unaffected.
Maker Adverse Selection
When enabled, passive fills are scored for toxicity based on trade size, order-flow imbalance, volatility regime, and spread regime. High-toxicity fills may be probabilistically skipped or receive a price penalty.
MAKER_ADVERSE_ENABLED=true sim-engine run --wasm algo.wasm --symbol BTC-USD ...Key parameters (all configurable via env vars):
MAKER_ADVERSE_SKIP_RATE- max probability of fill skip (default: 0.3)MAKER_ADVERSE_PENALTY_K- price penalty scale (default: 0.5)MAKER_ADVERSE_BIAS- sigmoid center; higher = less toxic by default (default: 2.0)
Self-Impact (Shadow Book)
When enabled, your aggressive orders consume visible depth and your passive orders add to it. The algo sees an adjusted book reflecting its own footprint:
effective_depth = historical_depth - consumed_shadow + own_displayed_depth
SELF_IMPACT_ENABLED=true sim-engine run --wasm algo.wasm --symbol BTC-USD ...Consumed depth decays exponentially (SELF_IMPACT_DECAY_RATE, default 0.5/sec) and partially clears when new raw depth replenishes at consumed price levels.
Volatility-Conditioned Latency
Submit and report latency parameters scale with recent volatility and trade intensity:
LATENCY_VOL_MU_SCALE=0.3 LATENCY_VOL_SIGMA_SCALE=0.2 sim-engine run ...When scale factors are 0.0 (default), latency sampling is identical to the constant-parameter model.
Queue Cancel Attrition
Exponential decay on queue_ahead models background cancellations thinning the queue over time:
QUEUE_CANCEL_DECAY_RATE=0.5 sim-engine run ...The decay is capped at QUEUE_CANCEL_MAX_DT_S (default 5s) to prevent unrealistic jumps during sparse event gaps.
Calibration
Tune queue, impact, and adverse selection parameters against historical data:
# Queue + latency model
sim-engine calibrate --symbol BTC-USD --venue kraken --target queue
# Impact model (k_temp, k_perm, adverse_k)
sim-engine calibrate --symbol BTC-USD --venue kraken --target impact
# All parameters jointly
sim-engine calibrate --symbol BTC-USD --venue kraken --target full
# Maker adverse selection - Step 1: fill rate
sim-engine calibrate --symbol BTC-USD --venue kraken --target maker-adverse-fill-rate
# Maker adverse selection - Step 2: penalty (freezes step 1 params)
sim-engine calibrate --symbol BTC-USD --venue kraken --target maker-adverse-penaltyCalibrated parameters are saved to ./data/calibration/{venue}_{symbol}_latest.json.
Stress Testing
Test your algo under synthetic adversity:
sim-engine stress --wasm algo.wasm --symbol BTC-USD --start 2026-03-01 --end 2026-03-08 \
--scenario liquidity-shock --factor 0.2Available scenarios: liquidity-shock, spread-widen, depth-truncation, feed-outage, gap-up, gap-down.
Output
The sim engine produces:
- Tearsheet with Sharpe, Sortino, Calmar, max drawdown, win rate, profit factor
- MM metrics with 1s/5s/30s markouts, maker/taker ratio, inventory time-at-risk, fill rate
- Equity curve sampled every 1000 events
- Trade list with per-fill P&L attribution