Skip to main content
Simmer’s sim-venue, dry-run, and paper-trade modes all run live-forward — they test a strategy against today’s prices going forward. Backtesting is the missing historical leg: replay your skill against past prediction-market data to see how it would have performed before you commit real money.
Self-serve window download available in simmer-sdk >= 0.19.0. Backtesting ships as an optional extra — it pulls a few heavier dependencies (duckdb, fastapi, uvicorn) that most SDK users don’t need.

Install

This adds the simmer command:

Try it offline

The SDK bundles a tiny demo slice, so you can run a complete backtest with no data download and no network:

Backtest your own skill

Point the CLI at a skill bundle and a window — the historical tape is fetched for you and cached, no data hunting required:
The first run for a window fetches a small slice (tens of MB) from Simmer’s tape service and caches it under ~/.simmer/tapes/; repeat runs of the same window are instant. The fetch needs your SIMMER_API_KEY (set it in the environment, the same key you use to trade) — there’s no separate signup. The engine runs your unmodified skill once per tick as a subprocess against a frozen, look-ahead-safe replay server — the same wire shapes as production, so anything that calls /api/sdk/* can be backtested. State files the skill writes (daily-spend counters, etc.) are sandboxed in a temp copy.

Programmatic API

Reading the report

The report (stdout summary + full JSON via --out) includes:
  • summary — pnl, hit rate, max drawdown, trades, decisions, settlements, ticks.
  • baselines — the same entries/notionals under buy-and-hold-YES and a seeded random side rule, so you can tell skill from luck.
  • decisions / fills / equity_curve — the full per-tick trace.
  • realism_gaps — what the model does not capture (see below).
  • reproducibility.config_hash — a deterministic hash of the run inputs. Same (bundle, tape, window, cadence, args) → same config_hash → identical results.

What backtests do and don’t model

Backtests use trade-tape prices, not an order book. They measure decision quality — did the strategy pick the right side at the right time — not execution realism. Every report lists its realism_gaps: no slippage, no market impact at size, no queue position, no latency, no maker rebates. Treat a backtest as a filter for bad ideas, not a promise of live P&L.
A run is only trustworthy if it’s cleanbundle.clean == true means the skill executed successfully on every tick. A run with failed ticks under-reports the strategy (the skill didn’t actually run on those ticks) and the CLI exits non-zero.

Getting a tape

Most users don’t need to — pass --t0/--t1 (or --window) and the slice is fetched and cached automatically (see above).
Data coverage currently ends ~2026-05-05. Pick a window inside that range; a window starting after it returns an error. (The dataset is a snapshot of public on-chain Polymarket history; a freshness updater is planned.)
Bring your own tape (--tape). If you’d rather supply your own data — a different window, your own source, or to work fully offline — point --tape at a local directory containing markets.parquet + quant.parquet. The public, MIT-licensed dataset and the toolkit to regenerate it live at SII-WANGZJ/Polymarket_data; --tape lets power users slice their own and skip the hosted fetch entirely.

Graduation path

See Trading Venues for the live-forward modes.