mm
A headless, exchange-agnostic market-making engine for Rust.
Exchange connectivity lives at the edges. The quoting logic is a pure, deterministic pipeline. The same engine runs live, on paper, and in backtests — only the exchange changes.
Get Started → · Why mm · GitHub
cargo add mm --features backtest,avellanedause mm::core::EngineBuilder;
use mm::models::Symbol;
let mut engine = EngineBuilder::new()
.exchange(Box::new(exchange)) // live adapter, replay, or simulator
.symbols(vec![Symbol::new("BTC-USDT")])
.strategy(Box::new(strategy)) // compose the quoting pipeline
.risk(Box::new(risk_stack))
.planner(planner)
.build()?;
engine.run().await?;Highlights
- Deterministic & testable — the pipeline has no IO and no clocks.
- Backtest = Live — identical strategy code, only the exchange is swapped.
- Composable — mix fair-price, spread, inventory, and quote models.
- Lean — optional models and adapters are cargo features; compile only what you use.
- Async engine — event-loop core over
tokio, pure synchronous pipeline. - Typed errors — libraries expose
thiserrortypes, not stringly errors.
Features
| Feature | What it does | Docs |
|---|---|---|
| Live trading | Quote real venues through exchange adapters — the same engine that runs backtests. | Order lifecycle |
| Paper trading | Run live market data through the engine with simulated fills, no capital at risk. | Paper trading |
| Backtesting | Replay historical events; the simulator fills resting quotes and reports metrics. | Backtesting |
| Multi-symbol | Quote many symbols concurrently, each with independent state and its own strategy. | Engine |
| Risk management | Stackable pre-trade filters gate every quote before it reaches the venue. | Risk layer |
| Quote ladders | Multi-level / geometric quotes placed around fair price. | Ladders |
| Reporting | Self-contained interactive HTML report — equity, drawdown, inventory, fills, markout, PnL. | Charts |
| Avellaneda–Stoikov | Inventory-aware optimal spread model out of the box. | Avellaneda–Stoikov |