Backtesting infrastructure for systematic strategies
Python library, Rust core. Realistic execution modeling, sub-second performance, reproducible research workflows.
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())Built-in visualizations
ProPublication-ready charts out of the box. Tearsheets, parameter sweeps, risk analytics, all with a single function call.




Execution modeling
The gap between backtest and live performance is driven by execution assumptions. Each component is modeled independently and configurable per venue.
| Dimension | Typical framework | manifoldbt |
|---|---|---|
| Fee model | Flat percentage or fixed cost | Maker/taker split, tiered schedules, per-venue configuration |
| Slippage | Fixed bps or ignored entirely | Volume-impact model calibrated to orderbook depth |
| Funding rates | Not modeled | Perpetual funding rate accrual at 8h intervals, historical rates |
| Borrow costs | Not modeled | Short borrow costs with variable rate schedules |
| Order types | Market orders only | Market, limit, stop-loss, take-profit, trailing stop, partial fills |
| Reproducibility | Depends on random seeds and data snapshots | Deterministic bit-for-bit replay via cryptographic manifests |
Features
Performance
Core written in Rust with Apache Arrow columnar format. Backtest 1 year of 1-second bars in under 200ms.
GPU acceleration
Offload parameter sweeps and Monte Carlo studies to your local GPU. 10-100x speedup on heavy research workloads, no cluster required.
Execution realism
Volume-impact slippage, partial fills, perpetual funding rates, borrow costs, maker/taker fees. Each model independent and configurable.
Research workflow
Walk-forward optimization, parameter stability analysis, 2D heatmaps, Monte Carlo resampling. Deterministic replay via manifests.
Expression DSL
Composable signal declarations, auto-vectorized execution. 45+ built-in indicators including Kalman filter, linear regression, and z-score.
Multi-asset
Native cross-sectional operations: ranking, mean across symbols. Stat arb, pairs trading, and basket strategies out of the box.
Data connectors
Built-in providers fetch and normalize market data into Arrow IPC. Parallel ingestion with progress tracking, import from any source.
Spot & perpetuals
Perpetuals L1
Perpetuals v4 (decentralized)
Spot, BTC, ETH, EUR & USD pairs
Stocks, ETFs, futures, options, forex
CME, NASDAQ, OPRA, tick to daily
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.

Research workflow
A stat arb strategy using Ornstein-Uhlenbeck mean-reversion, built entirely with the expression DSL.
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. The engine auto-vectorizes execution across the full time series, no Python loops, no row-by-row callbacks.
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
ProBuilt-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.


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

Safety checks
ProAutomated diagnostics that catch common backtesting pitfalls. Run them before trusting any result.
Lookahead bias detection
Tests every signal for future data leakage using split-sample comparison. Catches bugs that silently inflate backtests.
$ bt.diagnostics.detect_lookahead(strategy, config, store)Lookahead Bias Detection Report================================Method: split-sample comparison (5 split points)Tolerance: 1.0%Signal 'fast' no future data okSignal 'slow' no future data okSignal 'rsi' no future data okSignal 'entry' no future data okPosition sizing no future data okResult: 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=========================Extension test (2/3 -> full): drift = 0.3% okTruncation test (full -> 1/3): drift = 0.8% okRegime sensitivity: stable across 3 windowsResult: STABLE - exposure consistent across time ranges
Pricing
- Rust-powered engine
- All 45+ indicators
- Multi-asset
- Parameter sweeps
- CSV import
- Engine resolution: 1m
- Timeseries output: Daily
- Monte Carlo resampling: 1,000 sims
- Crypto connectors (Binance, Bybit)
- Rust-powered engine
- All 45+ indicators
- Multi-asset
- Parameter sweeps
- CSV import
- Engine resolution: 1m
- Timeseries output: Up to 1m
- Monte Carlo resampling: Unlimited
- Crypto connectors (Binance, Bybit)
- Databento & Massive connectors
- Built-in WFO
- Safety checks (lookahead, exposure)
- Tearsheets & export
- GPU acceleration
- Rust-powered engine
- All 45+ indicators
- Multi-asset
- Parameter sweeps
- CSV import
- Engine resolution: 1m
- Timeseries output: Up to 1m
- Monte Carlo resampling: Unlimited
- Crypto connectors (Binance, Bybit)
- Databento & Massive connectors
- Built-in WFO
- Safety checks (lookahead, exposure)
- Tearsheets & export
- GPU acceleration
- Managed compute
- Hosted data (Databento, Massive)
- Team licenses (5+ seats)
- Priority support
- Custom integrations (data sources, indicators)