Guide
How to backtest Polymarket 5-minute strategies
Updated 19 October 2026 · Checked against our recorded data
A backtest is only as good as the book it runs on. This walkthrough tests a simple rule on real Polymarket 5-minute order book data, buying at the actual ask with fees taken off, and grading on Polymarket's own result.
1. Get the data
Download the free BTC sample (Parquet). It holds three files: btc_book_2026-10-16.parquet (22,634 book updates), btc_trades_2026-10-16.parquet (17,904 trades) and btc_windows_2026-10-16.parquet (12 windows with results).
2. Take the book at a decision time
Pick the moment your rule decides, say 120 seconds into each window, and take the last book state at or before it. That is what you could actually have traded against.
import duckdb
book = 'btc_book_2026-10-16.parquet'
win = 'btc_windows_2026-10-16.parquet'
snap = duckdb.sql(f"""
SELECT window_start, outcome, ask1_px, ask1_sz
FROM (
SELECT *, row_number() OVER (
PARTITION BY window_start, outcome ORDER BY elapsed_ms DESC) rn
FROM '{book}' WHERE elapsed_ms <= 120000)
WHERE rn = 1""")
3. Apply a rule and price it honestly
Example rule: buy whichever side is the favourite at 120 seconds, at the best ask, if that ask is 0.80 or below. Then charge the taker fee, which on these markets is 0.07 x p x (1 - p) per share (see the fees guide).
res = duckdb.sql(f"""
WITH fav AS (
SELECT * FROM snap
QUALIFY row_number() OVER (
PARTITION BY window_start ORDER BY ask1_px DESC) = 1)
SELECT f.window_start, f.outcome, f.ask1_px AS p, w.result,
(CASE WHEN f.outcome = w.result THEN 1 ELSE 0 END)
- f.ask1_px - 0.07 * f.ask1_px * (1 - f.ask1_px) AS pnl_per_share
FROM fav f JOIN '{win}' w USING (window_start)
WHERE f.ask1_px <= 0.80""").df()
print(res, res.pnl_per_share.sum())
4. Check you could have filled
The ask1_sz column is the size on offer at the best ask. If your stake is larger, you walk to ask2_px and pay more. Size every simulated trade against the depth that was really there.
5. Avoid the classic traps
- Look-ahead. Only use rows with
elapsed_msat or before your decision time. - Mid-price fills. You buy at the ask, not the midpoint. On thin books the gap is several cents.
- Grading on spot. Use the
resultcolumn, not an exchange close (see how settlement works). - Tiny samples. One hour is 12 windows. Test a rule across weeks of windows before trusting it, and keep a slice of data you never tuned on.
Test it on real data
Every number here can be checked in our free BTC sample: one hour, 12 windows, every book update and every trade. Full history for all seven coins from £1.99 a month.