Public beta: Banger supports paper trading only. Live execution is disabled, and hosted historical backtesting remains in private acceptance testing.
N°05 / Build

Hosted Kalshi backtesting

Signed-in beta users can run an immutable strategy version against normalized Kalshi one-minute market data, inspect the result, and promote that exact version and market universe to a bounded paper session.

Open your backtest history, or choose a market in the market explorer to start a prefilled run.

Run a hosted backtest

  1. Select an immutable strategy version.
  2. Choose one Kalshi market or a bounded market universe and a date range of up to seven days.
  3. Review typed parameter overrides. Overrides apply to this run only; they never rewrite the saved strategy version.
  4. Run the backtest, then inspect return, equity, drawdown, fees, fills, warnings, per-market attribution, and reproducibility metadata.
  5. Promote the exact tested version and pinned universe to paper mode when you want to observe it against current data.

Why this design

We don’t want a separate “backtest framework” with its own interface — that creates two codebases for one strategy. Instead we keep the Strategy / Venue / Context contracts and swap the implementations beneath them:

  • Hosted paper: Kalshi() → current market data → PaperContext
  • Backtest: HistoricalVenue → normalized one-minute candles → BacktestContext

Same Strategy code, same risk envelope, same handlers. Only the plumbing differs.

Use the local developer harness

from banger.backtest import Backtester, InMemoryCandleSource

from my_strategy import MyStrategy

# Build a HistoricalDataset containing one binary market and normalized candles.
source = InMemoryCandleSource(dataset)

result = Backtester(
    MyStrategy,
    source,
    starting_capital=10_000,
).run()

print(result.summary)
print(result.fills)

Historical input

A HistoricalDataset describes one binary market, the requested period, optional settlement, and chronological one-minute candles. Each candle carries opening and closing bid/ask observations.

  • Signals emitted at a candle close are eligible only at the next candle open, preventing same-candle look-ahead.
  • Limit orders fill only when they cross the available opening book; missing book observations never invent a fill.
  • Kalshi sizes floor to whole contracts, standard taker fees round to cents, and settlement applies only when it falls inside the period.

BacktestResult

Returned by Backtester.run():

result.summary       # return, ending equity, fees, drawdown, orders/fills, settlement
result.equity_curve  # chronological (timestamp, equity_usd) points
result.fills         # deterministic simulated fills
result.data_hash     # fingerprint of the normalized historical input
result.save_csv("equity.csv")

Demo

See packages/sdk-python/examples/backtest_demo.py in the repo for a working end-to-end backtest against a synthetic random-walk source.

Caveats

  • One-minute candle books cannot reproduce historical queue position, latency, intra-minute paths, or full depth. Results are estimates, not a promise of live execution quality.
  • Hosted runs support Kalshi binary markets and at most seven days per run. The engine accepts bounded shared-capital universes; your plan may impose a lower market or market-day limit.
  • Historical Polymarket data, parameter sweeps, and customer-money execution are not included in this beta.
  • A backtest is a deterministic simulation, not a profitability claim. Always validate a strategy in paper mode before relying on its behavior.

See also