Python backtesting infrastructure for systematic strategies

Python library, Rust core. Realistic execution modeling, sub-second performance, reproducible research workflows.

$pip install manifoldbt
View source →
strategy.py
import manifoldbt as bt
from manifoldbt.indicators import close, sma, rsi

fast = sma(close, 20)
slow = sma(close, 50)
signal = bt.when((fast > slow) & (rsi(close, 14) < 70), 1.0, 0.0)

strategy = (
    bt.Strategy.create("momentum")
    .signal("signal", signal)
    .size(signal * 0.25)
    .stop_loss(pct=3.0)
    .take_profit(pct=8.0)
)

result = bt.run(strategy, config, store)
print(result.summary())
Same strategy, same data, real-time race
manifoldbt░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
vectorbt░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
backtrader░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

Built-in visualizations

Publication-ready charts out of the box. Tearsheets, parameter sweeps, risk analytics, all with a single function call.

bt.plot.tearsheet(result), Overview
Tearsheet overview, metrics bar, equity curve, drawdown
bt.plot.tearsheet(result), Returns
Tearsheet returns, monthly heatmap, annual bars, returns distribution
bt.plot.tearsheet(result), Rolling
Tearsheet rolling, rolling Sharpe 126d/252d, rolling volatility 126d/252d
bt.plot.var_chart(result)
Value at Risk, VaR 5% and CVaR 5% with histogram

Execution modeling

The gap between backtest and live performance is driven by execution assumptions. Each component is modeled independently and configurable per venue.

Fee model
Typical framework
Flat percentage or fixed cost
manifoldbt
Maker/taker split, minimum fee, per-venue configuration
Slippage
Typical framework
Fixed bps or ignored entirely
manifoldbt
Fixed-bps, spread-based, or size-aware volume-impact model, opt-in
Funding rates
Typical framework
Not modeled
manifoldbt
Per-bar funding accrual from the venue's historical funding-rate series
Borrow costs
Typical framework
Not modeled
manifoldbt
Short borrow charged per bar from an annual rate, per venue
Order types
Typical framework
Market orders only
manifoldbt
Market, limit, stop, stop-limit, market-if-touched, stop-loss, take-profit, trailing stop
Reproducibility
Typical framework
Depends on random seeds and data snapshots
manifoldbt
Deterministic bit-for-bit replay via cryptographic manifests

Data connectors

Built-in providers fetch and normalize market data into Arrow IPC. Parallel ingestion with progress tracking, import from any source.

Binance logoBinance

Spot & perpetuals

crypto
Hyperliquid logoHyperliquid

Perpetuals L1

crypto
dYdX logodYdX

Perpetuals v4 (decentralized)

crypto
Bitstamp logoBitstamp

Spot, BTC, ETH, EUR & USD pairs

crypto
Massive logoMassive

Stocks, ETFs, futures, options, forex

equitiesfuturesoptionsforex
Databento logoDatabento

CME, NASDAQ, OPRA, tick to daily

futuresequitiesoptions
CSV / DataFrame import, auto-detected format
MetaTrader 4Native CSV export
MetaTrader 5Native CSV/TSV export
Custom CSVtimestamp, OHLCV
DataFramepandas or Polars, in memory

All data is stored locally as Arrow IPC (per-symbol, multi-resolution), instant replay, no re-download.

Performance

The engine is written in Rust and operates on Apache Arrow columnar arrays. Data flows through the pipeline with zero-copy semantics and SIMD-friendly memory layout.

<200ms
Single-shot backtest, 1 year of 1-min bars
552K combos
2D heatmap generated in seconds
All cores
Parallel sweeps, walk-forward & Monte Carlo via Rayon
bt.plot.heatmap_2d(sweep, metric="t-stat(alpha)")
Parameter sweep heatmap, Sharpe ratio by period × num_std

Research workflow

A stat arb strategy using Ornstein-Uhlenbeck mean-reversion, built entirely with the expression DSL.

stat_arb.py
import manifoldbt as bt
from manifoldbt.expr import col, lit, symbol_ref
from manifoldbt.indicators import close, kalman

# Spread construction
pair_close = symbol_ref("ETHUSDT", "close")
ratio = close / (pair_close + lit(1e-12))

# Kalman equilibrium
equilibrium = kalman(ratio, q=1e-4, r=1e-2)
spread = ratio - equilibrium

# OU parameter (mean-reversion speed)
neg_theta = spread.linreg_slope(28)

# Z-score signal
spread_z = spread.zscore(28).ewm_mean(8)
raw = (lit(0.0) - spread_z) * lit(0.05)
signal = bt.when(
    (neg_theta < lit(0.0))
    & ((spread_z > lit(0.5)) | (spread_z < lit(-0.5))),
    raw,
    lit(0.0),
)

strategy = (
    bt.Strategy.create("ou_stat_arb")
    .signal("spread_z", spread_z)
    .signal("neg_theta", neg_theta)
    .signal("signal", signal)
    .size(col("signal"))
)

result = bt.run(strategy, config, store)
print(result.summary())

Expression DSL

Signals are declared as composable expressions, evaluated vectorized across the full time series, no Python loops or row-by-row callbacks. Execution is then simulated event by event for realistic fills.

Symbol references

Cross-asset data access via symbol_ref(). Build spreads, ratios, and relative-value signals that reference any symbol in the universe.

Walk-forward validation

Out-of-sample testing with rolling train/test splits. Parameter stability analysis prevents overfitting to a single period.

Manifest replay

Every backtest produces a cryptographic manifest. Replay any result bit-for-bit, months later, on a different machine.

Research tools

Pro

Built-in tools to validate strategies before deploying capital. Every analysis runs in Rust, no Python bottlenecks.

Walk-forward optimization

Split your data into train/test folds. Optimize parameters in-sample, validate out-of-sample. Compare stitched OOS equity against the full backtest to detect overfitting.

bt.plot.walk_forward(wf, mode="bars")
Walk-forward, IS vs OOS Sharpe per fold
bt.plot.walk_forward(wf, mode="stitched", full_result=result)
Stitched OOS equity vs full backtest

Monte Carlo analysis

Bootstrap returns to estimate tail risk and P(ruin), or permute return order to measure path dependency and drawdown distribution.

bt.plot.monte_carlo(result, method="bootstrap")
Monte Carlo bootstrap, fan chart with P(ruin)

Safety checks

Pro

Automated diagnostics that catch common backtesting pitfalls. Run them before trusting any result.

Lookahead bias detection

Tests every signal for future data leakage and names the one that leaks. Catches the bugs that silently inflate a backtest.

$ bt.diagnostics.detect_lookahead(strategy, config, store)
 
Lookahead Bias Detection Report
================================
 
Tolerance: 1.0%
 
Signal 'fast' no future data ok
Signal 'slow' no future data ok
Signal 'rsi' no future data ok
Signal 'entry' no future data ok
Position sizing no future data ok
 
Result: CLEAN - no lookahead bias detected

Exposure stability

Verifies that strategy exposure is consistent when you extend or truncate the backtest period. Detects regime-dependent behavior.

$ bt.diagnostics.check_exposure_stability(strategy, config, store)
 
Exposure Stability Report
=========================
 
Exposure drift, window 1: 0.3% ok
Exposure drift, window 2: 0.8% ok
Regime sensitivity: stable across 3 windows
 
Result: STABLE - exposure consistent across time ranges

Pricing

Community
Free
Full engine, no time limit
pip install manifoldbt
  • Rust-powered engine
  • All 35+ indicators
  • Multi-asset
  • CSV / DataFrame import
  • Engine resolution: 1m
  • Timeseries output: Daily
  • Monte Carlo resampling: 1,000 sims
  • Parameter sweeps (all-core, 2-D, batch): 256 combos
  • Crypto connectors (Binance, Bybit, Hyperliquid, dYdX, Bitstamp)
  • MCP server (AI agent integration)
  • Tearsheets & export
  • Seats: 1
Pro
$19/mo
Unlock Rust-optimized research tools
  • Rust-powered engine
  • All 35+ indicators
  • Multi-asset
  • CSV / DataFrame import
  • Engine resolution: 1m
  • Timeseries output: Up to 1m
  • Monte Carlo resampling: Unlimited
  • Parameter sweeps (all-core, 2-D, batch): Unlimited
  • Crypto connectors (Binance, Bybit, Hyperliquid, dYdX, Bitstamp)
  • MCP server (AI agent integration)
  • Tearsheets & export
  • Safety checks (lookahead, exposure)
  • Cross-exchange backtesting
  • Databento & Massive connectors
  • Built-in WFO
  • GPU acceleration
  • Seats: 1
TeamEarly access
$299/mo
Managed compute and hosted data
  • Rust-powered engine
  • All 35+ indicators
  • Multi-asset
  • CSV / DataFrame import
  • Engine resolution: 1m
  • Timeseries output: Up to 1m
  • Monte Carlo resampling: Unlimited
  • Parameter sweeps (all-core, 2-D, batch): Unlimited
  • Crypto connectors (Binance, Bybit, Hyperliquid, dYdX, Bitstamp)
  • MCP server (AI agent integration)
  • Tearsheets & export
  • Safety checks (lookahead, exposure)
  • Cross-exchange backtesting
  • Databento & Massive connectors
  • Built-in WFO
  • GPU acceleration
  • Seats: 5
  • Managed compute (cloud sweeps, Monte Carlo, WFO)
  • Included compute credits: 5,000/mo
  • Hosted data credits (Databento, Massive): 5,000/mo
  • Usage dashboard, spend caps & alerts
  • Pay-as-you-go overage
  • Priority support: Direct channel

In detail: what Pro unlocks, what Team includes, what Firm adds

FAQ

Learn backtesting in Python

Step-by-step guides, runnable strategy walkthroughs, and honest comparisons, all built on realistic, reproducible backtests.

Or browse 15 Python trading strategies, each with runnable code and a backtest, see all strategies →