On this page5 sections
What you need before you can test anything
| Data | Where it comes from | The catch |
|---|---|---|
| Markets, outcomes, resolution dates and results | Gamma API | Resolved markets drop out of default listings; ask for them explicitly and store them |
| Price history per outcome token | CLOB prices-history endpoint | Sampled prices, not the book — you cannot see depth or the spread you would have crossed |
| Trades and positions for any wallet | Data API | Great for copy-trading research; rate-limited, paginated by cursor |
| Order-book depth over time | Nobody | You record it yourself from the WebSocket market channel, for weeks, before you can test a maker or a taker honestly |
| Your own fills | The user channel and your logs | The only data that calibrates a fill model to *your* latency and size |
| External signals with timestamps | Exchange feeds, news APIs, transcripts, forecast models | Timestamp at *receipt*, not publication — that is when your bot would have known |
Third-party platforms in the catalog — PolyData, Dome, HashDive, Polymarket Analytics — package the public parts of this into cleaner, bulk form. None of them can give you the one thing that matters most for execution: depth you were not there to record.
The seven ways backtests lie
- Last-price fills. The backtest buys at the last traded price. You would have paid the ask, and on a thin book the ask for your size was worse than the touch. The spread is the first cost and the most often omitted.
- No fees. Only takers pay, and the fee is C × rate × p × (1 − p): at a 50-cent price 1.75% of notional on crypto markets, 1.25% on sports, 1% on politics, zero on geopolitics. A taker strategy that looks like +1% per trade on a minute market is a −2.5% strategy after two crossings.
- Assumed fills. A maker backtest that assumes every resting order at the touch was filled has ignored queue position and size cutoffs; a taker backtest that assumes full fills has ignored depth.
- Look-ahead. The resolution was known when the market closed, not when you traded; the headline was published at 14:02:07 but your feed delivered it at 14:02:31; the spot print you "reacted to" was the one after the move. Every external series must be shifted to the moment your bot would actually have had it.
- Survivorship. Markets that were voided, delisted or resolved oddly disappear from default queries, and they are precisely the ones that would have hurt.
- Overfitting, especially on minute markets. Thousands of samples make it trivially easy to find a rule that worked — which is what makes the category so seductive. A strategy with eight tuned parameters fitted on last month has described last month. Hold out data; walk forward; distrust anything that only works with specific numbers.
- Regime change. The edge from spot leading the book was larger a year ago than today; liquidity rewards moved which books the makers sit on; fees changed the maths. A backtest across regimes averages an edge that is already gone into one that is not.
A process that survives the book
- Record first. Stream the books you intend to trade from the WebSocket market channel into storage — snapshots plus deltas — for weeks. Record external signals with receipt timestamps. This is the step everyone skips and the one that makes everything after it honest.
- Build a fill model and calibrate it. For takers: fill against recorded depth at your size, charge the spread and the fee by category. For makers: fill only when the recorded trade tape crosses your price, with a conservative assumption about your place in the queue. Then run real orders at tiny size and measure actual slippage — Uruguabot calibrates its dry-run simulator from slippage distributions measured on real fills, and that is the standard.
- Replay, out of sample. Fit on one period, test on the next, walk forward. Count what you would have done net of everything.
- Paper trade live with the same fill model, for weeks, including the boring weeks.
- Go live small — a size whose total loss would annoy you — and keep the paper run going beside it as a control.
- Scale on sample size, not on results. Hundreds of trades on minute markets before you believe an expectancy; on slow markets, accept you will be reasoning more than measuring.
The numbers that matter
Expectancy per trade after spread and fee; maximum drawdown and its duration; hit rate against average win and loss together (a 90% hit rate with one ruinous loss is how minute-market bots die); the sample size behind all of the above; and for makers, fill rate and adverse selection — how often the price moved against you right after you were filled. A Sharpe ratio on thirty trades is decoration.
What honest results look like
The most useful published record in the catalog is a net loss: Uruguabot publishes every fill from two generations of testing as raw CSVs, a 1,934-window study in which its automated signals scored at coin-flip against a human's 59%, and one default configuration at +7.3% over 25 live trades — and says in its own listing that nothing there promises future profits. Read it as a template for what you should be able to show yourself before a strategy gets real size. POLBOTS does not verify anyone's performance, including yours; that is what the process above is for.

PolyData
Analytics workspace and trading terminal for Polymarket. Track positions, liquidity and market flow in real time, analyze any wallet's PnL, exposure and win rate from live on-chain data, rank top traders on a leaderboard, and execute in a focused terminal — from market signal to order entry in one place.

Dome
Prediction-market APIs and SDK for developers. One integration for Polymarket and Kalshi data — historical order books, real-time trade webhooks and WebSockets, and backtesting — via REST plus TypeScript and Python SDKs.

HashDive
Advanced analytics for Polymarket and Kalshi. HashDive's proprietary Smart Scores rank how consistent and profitable a trader is, alongside a market screener, wallet tracking and candlestick charts with RSI, MACD and whale-volume breakdowns.

Polymarket Analytics
On-chain analytics and dashboards for Polymarket. Pulls every trade, wallet and position on-chain into searchable tables, trader leaderboards ranked by win rate and PnL, live volume discovery and consolidated position tracking.
Frequently asked questions
- Where do I get historical Polymarket data?
- Market metadata and resolutions from the Gamma API; price history per outcome token from the CLOB's prices-history endpoint; trades and positions for any wallet from the Data API; and third-party data platforms in the catalog for cleaned, bulk versions of the same. What nobody hands you is historical order-book depth — you record that yourself from the WebSocket feed, which is why serious testing starts weeks before it starts.
- Why does my backtest make money and my bot doesn't?
- Almost always one of four things: the backtest filled you at the last price when you would have crossed the spread; it forgot the taker fee (1.75% of notional at 50 cents on crypto markets); it assumed fills you would not have got at your size and queue position; or it used data — a resolution, a price, a headline — from a moment later than your bot would have had it.
- How many trades before I trust a result?
- More than feels necessary. On the minute markets, hundreds at a minimum; a vendor's 1,934-window study is the kind of sample at which a signal's coin-flip nature becomes visible, and a 25-trade live run — however profitable — is noise. On slower markets you will never have hundreds, which is a reason to weight reasoning over statistics there.
- Is paper trading a substitute for backtesting?
- It is the second half of it. A backtest tells you whether the idea ever worked; a paper run with an honest fill model tells you whether it works now, with your latency and your sizes. Do both, in that order, and treat a paper run's first profitable week as exactly that.
