Skip to content
mm

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,avellaneda
use 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 thiserror types, not stringly errors.

Features

FeatureWhat it doesDocs
Live tradingQuote real venues through exchange adapters — the same engine that runs backtests.Order lifecycle
Paper tradingRun live market data through the engine with simulated fills, no capital at risk.Paper trading
BacktestingReplay historical events; the simulator fills resting quotes and reports metrics.Backtesting
Multi-symbolQuote many symbols concurrently, each with independent state and its own strategy.Engine
Risk managementStackable pre-trade filters gate every quote before it reaches the venue.Risk layer
Quote laddersMulti-level / geometric quotes placed around fair price.Ladders
ReportingSelf-contained interactive HTML report — equity, drawdown, inventory, fills, markout, PnL.Charts
Avellaneda–StoikovInventory-aware optimal spread model out of the box.Avellaneda–Stoikov