Runs

Configuration and output shared by the Execution and Alpha backtest modes. Scope a run, cache its data, then read metrics, save, and open the dashboard.

Subtypes

A series can bundle several bet types under one ticker. Pass subtype to run just one across the series under a shared portfolio. Rolling and structured series carry a single bet type and need no subtype; sports leagues mix several.

Subtypes
up_or_downrolling
Directional "up or down" windows.
survivalstructured
Multi-strike surface.
densitystructured
Outcome-band density; also weather.
barrierstructured
Hit-a-price markets.
beat_estimateearnings
Earnings beat.
moneylinesports
Match winner.
spreadsports
Spread / handicap / run line.
totalsports
Over/under totals (also total:corners, total:cards, total:sets).
segment_winnersports
Set or half winner.
bttssports
Both teams to score.

Sports subtypes may add a settlement scope, e.g. spread:f5, total:corners:h1, or segment_winner:set1.

python
result = client.backtest( strategy, "soccer-fifwc", subtype="moneyline", initial_cash=10_000, after="2026-06-22T16:00:00Z", before="2026-06-23T12:00:00Z", )

Offline

Pass data_dir to replay from a local Parquet cache. The first run downloads; later runs read from disk.

Execution runs cache order book history; alpha runs cache bars. See Exports for the download endpoints.

python
# downloads on first run, replays from cache after result = client.backtest( strategy, "btc-up-or-down-5m", initial_cash=10_000, after="2026-04-15T01:45:00Z", before="2026-04-15T01:50:00Z", data_dir="data", )

Metrics

Both modes return the same BacktestResult. Read metrics as properties or as a dict via result.summary().

Summary Metrics
total_pnlfloat
Net profit/loss in USD.
total_returnfloat
Return as a fraction (0.034 = 3.4%).
win_ratefloat
Fraction of winning trades.
sharpe_ratiofloat | None
Annualized Sharpe ratio.
sortino_ratiofloat | None
Annualized Sortino ratio.
max_drawdownfloat
Maximum peak-to-trough drawdown as fraction of capital.
profit_factorfloat
Gross profit / gross loss.
expectancyfloat
Average profit per trade.
capital_utilizationfloat
Average fraction of capital deployed.
fee_drag_bpsfloat
Total fees as bps of traded volume.
turnoverfloat
Traded notional over average equity.
volatilityfloat | None
Annualized volatility of per-bar returns. Alpha runs only.

Alpha runs compute sharpe_ratio and sortino_ratio from the per-bar equity curve and add volatility. Execution runs report them per settlement.

jsonResponse
{ "total_pnl": "342.5000", "total_return": "3.43%", "win_rate": "68.00%", "sharpe_ratio": "2.14", "sortino_ratio": "3.01", "max_drawdown": "1.80%", "profit_factor": "2.35", "expectancy": "7.2872", "avg_holding_ms": 720000, "capital_utilization": "42.00%", "total_trades": 47, "total_fees": "38.4200", "fee_drag_bps": "8.20", "turnover": "1.85" }

Saving

Save a result to disk and reload it later. Loaded results are read-only with no live portfolio.

Methods
save(path, overwrite=False)Path
Write to a new directory. Raises FileExistsError unless overwrite=True.
load(path)BacktestResult
Reconstruct a result from a saved directory.
Files
manifest.json
Run config, targets, and computed metrics.
trades.parquet
One row per fill.
orders.parquet
One row per order.
settlements.parquet
One row per settled market.
equity.parquet
Equity curve snapshots.
python
from marketlens.backtest import BacktestResult result: BacktestResult = client.backtest(...) result.save("runs/btc-fader") loaded = BacktestResult.load("runs/btc-fader") loaded.summary()

Dashboard

Open a local browser dashboard with equity curve, drawdown, PnL by market, PnL distribution, trade timeline, order analysis, settlements table, and run config. Pass additional results to overlay.

Methods
show(*others, labels, title, open_browser)None
Render the result. Pass other backtest results to overlay runs.
dashboard(*paths, labels, title, open_browser)None
Load saved runs from disk and render them.
Arguments
labelslist[str] | None= null
Display name per run.
titlestr | None= null
Header title.
open_browserbool= true
Open the default browser automatically.
python
from marketlens.backtest import BacktestResult result.show() # overlay a second run result.show(other, labels=["baseline", "tuned"]) # load saved runs from disk BacktestResult.dashboard("runs/baseline", "runs/tuned")