DocsBacktestsBacktests on Backtest.ai
BacktestsGuide

Backtests on Backtest.ai

A backtest is a multi-leg options strategy stepped minute-by-minute over real quote data for one symbol, producing an equity curve, a margin curve, and a per-trade ledger. One run covers one symbol, holds equity-option legs only, and steps the market at 1-minute resolution, so everything you read below is anchored to a single instrument on a per-minute clock.

Updated Jul 20264 min read

A backtest in one sentence

A backtest is N legs, each addressed by a strategy slug you choose (short_put, long_call, and so on), driven by one entry signal and one exit signal, run over one symbol's per-minute spine.

It produces three result frames:

  • an equity curve (net liquidating value at every step),
  • a margin curve (margin required at every step),
  • a per-trade ledger (one row per closed trade),

plus a run summary computed at the end. The backtest results page reads each of these in detail.

Legs, signals, and one symbol in; three curves and a ledger out. Everything else on this page is how the run gets from one to the other.

Where a backtest sits in the pipeline

A backtest is the terminal stage of the research pipeline. The stages upstream of it are optional: you can validate a signal in the Signal and EDA stage, or train a model on it, but you do not have to. Every workflow ends in a backtest, because the backtest is where a strategy meets real quotes and produces an equity curve.

The Model stage sits between Signal and EDA and the backtest, and it is optional. You can run Signal and EDA straight into a backtest with no model layer in between.

What you can run it on

One run covers one symbol. The run holds equity_option legs only, steps the market at 1-minute resolution, and follows the NYSE calendar in America/New_York.

You set the run's date range as a start and an end. A bare-date end covers the full final trading session through that day's close, so an end of 2024-12-31 runs the strategy all the way to the close on the last session of the year, not to midnight the night before.

For the symbol universe and how far each symbol's history reaches, see data coverage. That page is the single source for coverage, so it is not repeated here.

The lifecycle of a run

A run request carries the legs, the entry signal, the exit signal, the sizing rule, the margin configuration, and the starting capital. From there the engine does three things in order:

  1. Resolve contracts up front. Every leg's contract selection is evaluated before the loop starts, in cross-leg dependency order, so a leg defined relative to another (a long put five strikes below the short put) resolves after the leg it depends on.
  2. Step the minute spine once. A single pass walks the per-minute spine from the start date to the end, applying splits, exits, entries, and adjustments at each minute.
  3. Return results as they complete. Results stream in batches as the run progresses, one batch at each calendar-month boundary of session days, each batch carrying that span's equity and margin points, the trades closed in that span, and that span's action ledger. A final, authoritative end summary follows, carrying the final net liquidating value and the positions still open at the end of the run.

A run that reaches its end date cleanly can be saved. A saved run can later be extended to a later end date without recomputing from the start: the engine restores the run's state at the old boundary and resumes only the new sessions when the strategy and its inputs are unchanged, and falls back to a full re-run when they are not. The backtest lifecycle page walks the minute loop and the resume path step by step.

A run fixes one fill mode and you choose it. The three are the Backtest.ai fill model (calibrated, and the mode that matches paper and live trading), mid (the optimistic bound, at the exact quoted midpoint), and bid_ask (the pessimistic bound, the full spread at the touch). Read backtest assumptions and realism before you trust a number off an equity curve.

Building one: UI vs DSL

You build a backtest in the interface. The visual Backtest tab carries a position designer for the legs, condition builders for the entry, exit, and adjustment logic, and a form for sizing and capital.

The same strategy is fully expressible in the Signal language. Legs, entry and exit signals, adjustment triggers, and contract selection all have a code form. Treat the interface as the main way to build a backtest and the Signal language as the power path underneath it: anything the designer produces, you can write directly.

What this section covers

The rest of the Backtests section takes one piece of the run apart at a time:

Was this page helpful?