The three points were sized before this runner had ever run one. It has now, so they are sized from what it measured: 87.5 us per combination for manifoldbt at 20,000 bars, 1.16 ms for vectorbt, 1.34 ms for raptorbt, and 15.0 ms for raptorbt at 200,000 bars. 20,000 x 5,000 stays, because it is the only one of the three vectorbt can hold: it materialises 1.57 MB per combination at that length, so 5,000 already costs it 2.5 GB. The other two grow to 20,000 and 10,000 combinations and put it out of scope, which is where a sweep stops being a speed comparison and becomes a capability one. raptorbt sets the budget, not manifoldbt. With no fan-out API its sweep is a Python loop costing a full backtest per cell, so the large point goes deep in combinations on a short series rather than the reverse: 20,000 combinations on 20,000 bars costs it 27 s a call, where 5,000 combinations on a million bars would cost it 25 minutes. Also: sweeps, not grids. `run_sweep`, `run_sweep_lite` and `--sweep` are what the product calls this, and a second word for the same thing is a second thing to learn. `grid` is kept only where it means the parameter space itself.
ManifoldBT
Rust-powered backtesting engine for quantitative research
Website · Documentation · Examples
ManifoldBT is a Python backtesting library with a Rust core. Strategies are written in a fluent Python DSL, compiled to a vectorized Rust expression graph, then run through a sequential fill simulation with realistic fees, slippage, funding and look-ahead protection. Vectorized speed with event-driven execution realism.
Why ManifoldBT
- Fast — 500K bars in ~13 ms. 353x faster than vectorbt, ~3,500x faster than backtrader.
- Expressive — fluent DSL with 30+ indicators, conditional logic, cross-asset references
- Rigorous — Monte Carlo, walk-forward, parameter sweeps, lookahead detection, exposure diagnostics
- Portable —
pip install, no Rust toolchain needed. Works on Python 3.9+.
Installation
pip install manifoldbt # engine only: backtests, sweeps, metrics
pip install manifoldbt[plot] # + interactive charts and native windows (show=True)
pip install manifoldbt[all] # everything: plots, windows, PNG export, pandas/polars
The base install stays light (no browser, no GUI) for scripts, servers and CI.
[plot] adds plotly and a native window backend; [all] also pulls kaleido for
static PNG/SVG export (which bundles a headless Chromium).
Quick Start
import manifoldbt as mbt
from manifoldbt.indicators import close, ema
from manifoldbt.helpers import time_range, Interval, Slippage
fast = ema(close, 12)
slow = ema(close, 26)
strategy = (
mbt.Strategy.create("ema_crossover")
.signal("fast", fast)
.signal("slow", slow)
.signal("signal", mbt.when(fast > slow, mbt.lit(1.0), mbt.lit(-1.0)))
.size(mbt.col("signal") * mbt.lit(0.25))
)
start, end = time_range("2022-01-01", "2025-01-01")
config = mbt.BacktestConfig(
universe=[1],
time_range_start=start,
time_range_end=end,
bar_interval=Interval.hours(12),
initial_capital=10_000,
execution=mbt.ExecutionConfig(allow_short=True, max_position_pct=0.5),
fees=mbt.FeeConfig.binance_perps(),
slippage=Slippage.fixed_bps(2),
warmup_bars=30,
)
store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1,
start="2022-01-01T00:00:00Z", end="2025-01-01T00:00:00Z", interval="1h")
result = mbt.run(strategy, config, store)
print(result.summary())
Loading data
Bring your own data, or pull it from a built-in connector — both return a
DataStore ready for mbt.run(...).
CSV — free on all tiers, auto-detects standard / MetaTrader 4 / MetaTrader 5:
store = mbt.import_csv("EURUSD_1m.csv", symbol="EURUSD", symbol_id=1,
interval="1m", asset_class="forex")
Exchange connectors — Binance, Bybit, Hyperliquid, dYdX, Bitstamp (free); Databento, Massive (Pro):
store = mbt.ingest(provider="binance", symbol="BTCUSDT", symbol_id=1,
start="2024-01-01T00:00:00Z", end="2025-01-01T00:00:00Z")
Or from the CLI:
manifoldbt import-csv data.csv --symbol EURUSD --symbol-id 1 --interval 1m
manifoldbt ingest --provider binance --symbol BTCUSDT --symbol-id 1 --start ... --end ...
Examples
| # | Example | What it shows |
|---|---|---|
| 00 | Template | Minimal starting point |
| 01 | Trend Following | EMA crossover, volume filter, stop-loss |
| 02 | Mean Reversion | EMA crossover with parameter sweep |
| 03 | Multi-Asset Momentum | Cross-asset signals |
| 04 | Linear Regression | Regression-based signal |
| 05 | Statistical Arbitrage | Pairs trading, spread z-score |
| 06 | Full Visualization | Tearsheet and charts |
| 07 | Walk-Forward | Out-of-sample validation |
| 08 | 2D Sweep | Parameter grid heatmap |
| 09 | 3D Surface | Parameter surface plot |
| 10 | Monte Carlo | Permutation-based robustness |
| 11 | Portfolio | Multi-strategy portfolio |
| 12 | Diagnostics | Lookahead & exposure safety checks |
| 13 | Stochastic Simulation | SDE path simulation (GBM, Heston, …) |
| 14 | Multi-Timeframe | Combining signals across timeframes |
| 15 | Cross-Exchange | Signal on one venue, execute on another |
| 16 | Exogenous Data | External series (e.g. hashrate) as a signal |
| 17 | Per-Venue Fees | Per-venue funding & borrow costs |
| 18 | CSV Import | Load OHLCV from CSV (standard / MT4 / MT5) |
Performance
EMA(12/26) + RSI(14) on 500K synthetic 1-min bars (manifoldbt/vectorbt: median of 5 runs; backtrader: median of 3):
| Engine | Time | vs ManifoldBT |
|---|---|---|
| ManifoldBT (Rust) | 13 ms | 1x |
| vectorbt (NumPy) | 4,662 ms | 353x slower |
| backtrader (Python) | 46,944 ms | ~3,556x slower |
ManifoldBT and vectorbt produce identical results (−30.23% vs −30.24% return, same trade count); backtrader's event-driven fills give a different PnL.
Reproduce: python benchmarks/bench_vs_competitors.py --rows 500000 --runs 5
How it compares
| ManifoldBT | vectorbt | backtrader | Nautilus | |
|---|---|---|---|---|
| Engine | Rust (vectorized + sequential fills) | Numba/NumPy (vectorized) | Python (event-driven) | Rust/Python (event-driven) |
| Execution realism¹ | High | Basic | High | High |
| Focus | Backtesting + research | Backtesting at scale | Backtest + live | Backtest + live (production) |
¹ fees, slippage, funding, partial fills, look-ahead detection.
On GPU (Pro), the Monte Carlo engine runs ~36x faster than the all-core CPU path (SDE path simulation, RTX 3090, f32).
Documentation
Full API reference, indicator list, configuration guide, and best practices:
www.manifoldbt.com/docs/documentation.html
Community vs Pro
| Community | Pro | |
|---|---|---|
| Output resolution | Daily | 1m, 5m, 15m, 1h |
| Monte Carlo | 1K sims | Unlimited |
| Walk-Forward | - | Anchored + Rolling |
| Parameter Stability | - | Yes |
| Crypto connectors (Binance, Bybit, Hyperliquid) | Yes | Yes |
| Databento & Massive connectors | - | Yes |
| Safety checks (lookahead, exposure) | - | Yes |
| Tearsheets & export | - | Yes |
License
Apache 2.0 with Commons Clause. The source is available, free to use, modify and self-host. Reselling the software or offering it as a paid hosted service is not permitted. See LICENSE for the full text.
