Backtesting a Polymarket Bot: Data Sources and Honest Methods (2026)
Backtesting a Polymarket bot honestly means replaying your signal against the book it would actually have faced — Data API v2 price history for the series, on-chain trades for ground truth, regime-aware fees, and a fill model that assumes you get filled when you’re wrong. Most backtest failures are fill-model failures, not signal failures.
What data do you need?
| Source | What it gives | Limits |
|---|---|---|
Data API v2 /v2/prices-history |
Price series per token | Depth not included |
Data API v2 /v2/trades |
Actual fills | Rate-limited pagination |
| Gamma API | Market metadata, resolution rules, dates | Static descriptions |
| On-chain (Polygon) | Complete settlement record | Raw; needs indexing |
| Dune dashboards | Community aggregates | Not your bot’s view |
Price history answers “where was the market.” Trade records answer “who actually crossed and at what size” — the difference between a paper series and a book you could have participated in.
What does an honest backtest include?
- Fee regimes — the taker formula (shares × feeRate × p × (1−p)) for spot, volume-tiered notional rates for perps; switch models at regime boundaries
- Spread costs — your entries cross the spread or rest and risk adverse selection; model both, not just the flattering one
- Fill realism — limit fills happen when price trades through you, which correlates with being wrong; a queue-aware fill model beats an optimistic touch-fill one
- Resolution accounting — wins pay $1 at resolution, not at signal exit; capital lockup until resolution changes compounding
- Rate limits — if your live loop can’t execute the backtest’s trade cadence within its tier, the backtest describes a bot you can’t run
What is the minimal backtest skeleton?
# per token, from /v2/prices-history
series = fetch_prices(token_id, start, end)
for t in timestamps:
signal = strategy(series[:t]) # no lookahead
if signal.enter and not position_open:
fill_price = series[t] + spread_cost(t) # cross the spread
fee = taker_fee(shares, fill_price, category)
book.append(Position(fill_price + fee, entry_time=t))
if signal.exit or position.resolved:
pnl = position.close(series[t] or RESOLUTION_PRICE)
The three lines that make it honest: series[:t] (no lookahead), + spread_cost
(you never get the midpoint), and RESOLUTION_PRICE (events settle at $1/$0, not
at your exit whim).
How do you validate without fooling yourself?
- Walk-forward, not single split — optimize on window 1, test on window 2, roll; a parameter set that only works on one window is curve-fit
- Regime coverage — the sample should include at least one fee-regime change (the April 2026 cutover is a natural boundary) and one event-type you didn’t tune on
- Capacity check — rerun at 2x, 5x, 10x size; if PnL collapses, your edge was your own impact avoidance, and it dies at scale
- Baseline comparison — does the strategy beat “buy YES at 50¢ on the same markets” and “hold cash”? If not, complexity earned nothing
Which backtest metrics matter for event markets?
| Metric | Why it’s different here |
|---|---|
| PnL per resolved market | Capital returns at resolution, not on close |
| Max drawdown by capital-at-risk | Lockup windows make DD stickier |
| Fill rate on signals | Signals you couldn’t execute are zero |
| Fee share of gross edge | The formula fee punishes near-extreme trades |
| Time-to-resolution exposure | Long lockups are their own risk line |
FAQ
Q: Where do I get historical prices for Polymarket backtests?
A: Data API v2 /v2/prices-history per token for series; /v2/trades and Polygon
on-chain records for actual fills and settlement truth.
Q: How do I model fees across the 2026 migration? A: Regime-aware: category formula for spot event markets, volume-tiered notional rates for perps, switching at April 28, 2026 for backtests that span it.
Q: Why do my backtest fills look better than live trading? A: Optimistic fill models — assuming your limit order fills on a price touch instead of a trade-through, and ignoring that fills cluster against your position. Tighten the fill model before doubting the live infrastructure.
Q: What’s the biggest backtest mistake for event markets? A: Ignoring resolution mechanics — positions pay $1/$0 at resolution, and the capital sits locked until then. PnL accounting that treats event shares like continuously tradable assets overstates returns.
Q: How much history is enough? A: Enough to cover at least two distinct market regimes and one unseen event category in validation — for most strategies that means several months of active markets, not one hot event.
Sources
Disclaimer
Not financial advice. Educational purposes only. Updated October 2026.