Realistic backtest fills¶
Configure a backtest with realistic execution: slippage on market orders, queue simulation for limit orders, and an exported equity curve. Same model in every binding.
1. Configure the simulator¶
#include "flox/backtest/backtest_config.h"
#include "flox/backtest/backtest_runner.h"
flox::BacktestConfig cfg;
cfg.initialCapital = 100'000.0;
cfg.feeRate = 0.0002; // 2 bps per fill
cfg.defaultSlippage = { flox::SlippageModel::FIXED_BPS, 0, flox::Price{}, 1.0, 0.0 }; // 1 bps default
cfg.queueModel = flox::QueueModel::TOB;
cfg.riskFreeRate = 0.0;
cfg.metricsAnnualizationFactor = 252.0;
flox::BacktestRunner runner(cfg);
cfg.perSymbolSlippage.emplace_back(
kEthUsd, flox::SlippageProfile{flox::SlippageModel::VOLUME_IMPACT, 0, 0.0, 0.01});
2. Run it¶
3. Inspect stats¶
These are the fields on the dict returned by run_csv / run_ohlcv / run_bars / run_tape / run_tapes (snake_case in Python/Codon, camelCase in Node, BacktestStats struct in C++).
| Python / Codon | Node.js | Description |
|---|---|---|
total_trades |
totalTrades |
Number of closed trades |
net_pnl |
netPnl |
Total P&L net of fees |
return_pct |
returnPct |
Total return % |
sharpe_ratio |
sharpeRatio |
Annualised Sharpe |
sortino_ratio |
sortinoRatio |
Annualised Sortino |
calmar_ratio |
calmarRatio |
Calmar ratio |
max_drawdown_pct |
maxDrawdownPct |
Worst drawdown |
win_rate |
winRate |
Win rate |
profit_factor |
profitFactor |
Gross profit / gross loss |
BacktestResult.stats() is a different dict with a wider field set, but the same key names. See Running a backtest.
4. Export the equity curve¶
curve = bt.equity_curve() # dict of numpy arrays
ts, eq, dd = curve["timestamp_ns"], curve["equity"], curve["drawdown_pct"]
# BacktestRunner has no CSV writer. write_equity_curve_csv lives on
# BacktestResult, which you drive from a SimulatedExecutor:
res = flox.BacktestResult(initial_capital=100_000.0, fee_rate=0.0002)
res.ingest_executor(ex)
res.write_equity_curve_csv("equity.csv") # or res.equity_curve() -> structured array
CSV header: timestamp_ns,equity,drawdown_pct. One row per closed trade.