Reading Polymarket backtest results

Both the execution and alpha engines return the same result object. This guide covers what is in it: the metrics, the DataFrames underneath them, the dashboard, and how to compare and archive runs.

The summary metrics

result.summary() prints every metric at once; each is also a plain attribute:

python
print(result.summary()) # all metrics, formatted result.total_pnl, result.total_return result.win_rate, result.profit_factor, result.expectancy result.max_drawdown, result.sharpe_ratio, result.sortino_ratio result.total_fees, result.fee_drag_bps, result.turnover

Two deserve special attention on Polymarket. fee_drag_bps tells you how much of the edge fees consumed, which decides whether a high frequency idea survives contact with the fee schedule. max_drawdown comes with max_drawdown_duration_ms, since a small but months long drawdown is a different problem from a deep fast one.

DataFrames for anything deeper

The metrics are aggregates over data you can get at directly:

python
result.settlements_df() # one row per settled market: P&L, fees result.by_series() # the same, rolled up per series result.trades_df() # every fill result.orders_df() # full order lifecycle result.equity_df() # equity curve time series

settlements_df() is usually where the story is: a strategy that makes all its money in two markets out of fifty is telling you something. orders_df() answers execution questions, like how many limit orders never filled.

The dashboard

result.show() opens an interactive dashboard in the browser: equity curve, drawdown, per market settlements, and the trade tape. It works identically for execution and alpha runs.

Racing strategies

Pass a list of strategies and labels= to backtest them over the same window in one run:

python
result = client.backtest( [Tight(), Loose()], "btc-up-or-down-5m", labels=["tight", "loose"], initial_cash=10_000, after=..., before=..., ) result.show() # overlaid equity curves result["tight"].summary() # each run individually

Saving and reloading runs

Runs archive to disk and restore later, dashboard included, so a good run survives your terminal session:

python
result.save("runs/tight-v3") from marketlens.backtest import BacktestResult result = BacktestResult.load("runs/tight-v3")

Common questions

What metrics does a Polymarket backtest report?

The summary covers P&L and return, win rate, profit factor, expectancy, average win and loss, payoff ratio, max drawdown and its duration, Sharpe and Sortino ratios, volatility, turnover, capital utilization, average holding time, trade and market counts, total fees, and fee drag. Each is also available as a plain attribute on the result.

How do I see per market P&L in a Polymarket backtest?

The settlements DataFrame has one row per settled market with its P&L and fees, and a per series rollup is available too. Separate DataFrames cover fills, the order lifecycle, and the equity curve.

How do I compare two Polymarket strategies?

Pass a list of strategies with labels to a single backtest call. The equity curves overlay in one dashboard, and each labelled run is accessible on its own.

Can I save a backtest run and reload it later?

Yes. A result saves to a directory on disk and loads back later, dashboard included, so runs can be archived, diffed, and shared without re-running.

Try it

Run one and read it yourself

The free tier includes 5M events per day with full API and full archive access, no card required.

bash
$ pip install marketlens