Windows and macOS were carried on an argument that does not survive examination. They were the only place in the whole chain that installed the published wheel and ran it, which made this benchmark an install smoke test by accident. That check is worth having, and worth forty seconds next to the build in release.yml rather than thirteen minutes inside a performance measurement: nobody reads a benchmark to find out whether a package imports. release.yml already builds on all four targets, it just never executes what it built. What is lost is a per-platform timing that was never quoted; the numbers that get published are the Linux ones. Adding a platform back is one matrix entry. The jobs are also named for what they measure rather than for the runner they landed on, which the row already says: `backtests (ubuntu-latest)` and `grids (ubuntu-latest)` instead of a raw label next to a hand-written one.
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.
