How to Backtest Prediction Market Strategies

A step-by-step walkthrough — from pulling your first snapshot to running a full backtest with realistic fill simulation.

Why backtesting prediction markets is different

Prediction markets aren't like spot crypto. Prices are bounded between 0 and 1, markets have fixed expiry times, and liquidity profiles look nothing like a BTC/USDT orderbook. A strategy that works on Binance won't necessarily work on Polymarket. You need prediction-market-specific data — and you need orderbook depth, not just price feeds.

Step 1: Get historical data

PolyTest is a Polymarket backtesting API that lets traders replay historical orderbooks and test trading strategies on crypto prediction markets. Sign up for a free account at polytest.io, grab an API key, and start making requests. You'll have access to real snapshot data in under 5 minutes.

# List BTC 5-minute markets
curl -H "X-API-Key: YOUR_API_KEY" \
  "https://api.polytest.io/api/v1/markets?coin=btc&market_type=5m&limit=20"

Step 2: Understand the data

Each snapshot gives you: best bid, best ask, mid price, spread, volume, 8 levels of orderbook depth (both sides), the underlying coin's reference price, and a millisecond timestamp. The orderbook depth is the key differentiator — without it, you're just backtesting against mid-price, which tells you nothing about what your actual fills would look like.

Step 3: Avoid look-ahead bias

The most common backtesting mistake is using future data to make past decisions. PolyTest snapshots are point-in-time — each one represents exactly what the market looked like at that moment. Process them in chronological order and only use data that would have been available at decision time. Never peek at the next snapshot to decide what to do now.

Step 4: Simulate realistic fills

This is where most backtests fall apart. If you assume you can buy at mid-price, your results will look way better than reality. Use the orderbook depth data to simulate fills: walk through the levels, consume available liquidity at each price, and calculate your average fill price including slippage. A 100-share order at mid 0.52 might actually fill at 0.527 if there's only thin liquidity on the ask side.

function simulateFill(
  orderbook: { price: number; size: number }[],
  quantity: number
) {
  let filled = 0;
  let cost = 0;

  for (const level of orderbook) {
    const fillAtLevel = Math.min(level.size, quantity - filled);
    cost += fillAtLevel * level.price;
    filled += fillAtLevel;
    if (filled >= quantity) break;
  }

  return {
    avgPrice: cost / filled,
    filled,
    slippage: cost / filled - orderbook[0].price,
  };
}

Step 5: Account for timing

Polymarket Up/Down markets resolve at specific times. A 5-minute BTC market that starts at 14:00 resolves at 14:05. Your strategy needs to know when to enter and when the market closes. PolyTest snapshots include millisecond timestamps so you can model entry timing precisely. Don't assume you can enter at market open — by the time you see the price, it may have already moved.

Step 6: Measure what matters

Win rate alone is misleading in prediction markets. Track: P&L after slippage, maximum drawdown, Sharpe ratio if you're running the strategy continuously, and how your results change across different market conditions. A strategy that prints money in trending markets might bleed in choppy ones. Use PolyTest's time-range filtering to test across different periods.

Common mistakes

Backtesting against mid-price instead of simulating orderbook fills. Ignoring the spread — Polymarket Up/Down spreads can be 2-5 cents, which eats into margins fast. Testing on a single coin or timeframe and assuming it generalizes. Overfitting to a short time window. Not accounting for the fact that your orders would move the market if you're trading meaningful size.