DocsBacktestsDesigning the position
BacktestsHow-to

Designing the position

A strategy on Backtest.ai is a set of named legs plus exactly one entry signal and one exit signal. Each leg names a contract to hold; the entry signal says when to open the position and the exit signal says when to close it. This page shows how to shape a strategy from its legs, where direction and size live, and how a running position carries lots. The running example is a put credit spread, which later pages extend into an iron condor.

Updated Jul 20265 min read

Legs, slugs, and the strategy shape

A strategy is a non-empty set of legs plus one entry signal and one exit signal. Each leg is two things:

  • A slug you choose, a unique string that names the leg's role (short_put, long_put).
  • A contract-selection expression that picks the real contract the leg holds.

The slug is the leg's address for the rest of the backtest. Adjustment triggers reference a leg by slug to roll or remove it. Slugs must be unique within a strategy.

There is no fixed strategy taxonomy in the engine. Nothing labels a position as a "put credit spread" or an "iron condor"; the shape emerges from the legs you declare. A put credit spread is a short_put and a long_put. Add a short_call and a long_call to the same strategy and it is an iron condor. Use the canonical slugs short_put, long_put, short_call, long_call so the same strategy reads the same way everywhere.

Direction and size live on the contract selection

There is no separate buy/sell field and no separate quantity field. Direction and per-lot quantity are one signed integer, the size argument on the leg's option.contract(...) selection.

  • +1 is long one contract per lot. This is the default when you omit size.
  • A negative size is short. size=-1 sells one contract per lot.
  • 0 is rejected. A leg holds at least one contract in one direction.

So a short leg is not "sell" plus "quantity 1"; it is size=-1 on the selection. A long leg is size=1. One signed number carries both facts.

The short leg of a put credit spread sells one 16-delta put at 45 DTE. The selection picks the put and carries the size: size=-1, where the sign is the direction:

// short_put leg: the ~16-delta put at 45 DTE, size -1 (sell one per lot)
option.contract(dte=45, type="put", delta=-0.16, size=-1)

option.contract(...) selects the single contract closest to your targets within default thresholds: dte within 5 days, delta within 0.05. When no contract clears every threshold at a minute, the selection is null there. See selecting contracts for the full selection rules and how to tighten the thresholds.

Lots vs size

Keep two terms apart. Size is the per-lot signed count set in the leg's contract selection. Lots is a whole-number multiplier on the whole position, at least 1. They multiply:

contracts held on a leg = size × lots

A short_put leg with size -1 in a position of 3 lots is short 3 contracts. Change the leg to size -2 and the same 3 lots hold 6 short contracts. Size shapes the structure of one lot; lots scale that structure up or down without touching the legs.

A position scaled to zero lots is closed. It can persist as a lots == 0 row for audit, recording that the structure once existed and is now flat. That is the one case where lots is not at least 1: a closed position, not a live one.

Multiplier

Every contract carries a multiplier, the number of shares it delivers. It defaults to 100 for US equity options. The multiplier is metadata on the contract, not part of the contract's identity: strike, expiration, and right identify a contract, and the multiplier rides alongside them.

Adjustments operate only on standard-multiplier legs, meaning a multiplier of 100. A leg whose multiplier has drifted from 100 (an adjusted deliverable after a non-round split) is outside the set an adjustment will act on. This also feeds margin and auto-decomposition, which reason over standard-multiplier legs.

Building a position: the visual designer

The main path for shaping a strategy is the Position designer, a structured form. To build the put credit spread in it:

  1. In the Position designer, set Number of legs to 2.
  2. Set Option type to put on both legs.
  3. Set Buy/Sell per leg: Sell on the short leg, Buy on the long leg. This maps to the engine's signed size, where Buy is a positive size and Sell is a negative size.
  4. Set Contract selection per leg by target expiry and target delta: 45 days and 0.16 delta on the short leg, 45 days and 0.05 delta on the long leg. These map to the dte and delta arguments of the leg's contract-selection expression.

You have the spread when the designer shows two put legs, one Sell and one Buy, each with its own target expiry and delta. Every field resolves to the same leg the engine runs: a slug plus a contract-selection expression that carries the signed size.

Prefer code? Write each leg's selection directly in the Signal language. The selection expression is option.contract(...), which takes the contract targets dte, type, one of delta / moneyness / strike, and the signed size. The slug is the leg's only other property, set beside the selection expression.

Worked example: a put credit spread

A put credit spread is two put legs. The short_put leg sells the 16-delta put; the long_put leg buys a cheaper, further-out-of-the-money put as the protective wing, picked by its own delta target.

short_put leg, size -1:

// short_put leg: the ~16-delta put at 45 DTE, size -1 (sell one per lot)
option.contract(dte=45, type="put", delta=-0.16, size=-1)

long_put leg, size +1:

// long_put leg: the ~5-delta put at 45 DTE, size +1 (buy one per lot)
option.contract(dte=45, type="put", delta=-0.05, size=1)

Two legs, two slugs, two signed sizes. Pair them with an entry signal and an exit signal and you have a runnable strategy. Adding a short_call and long_call on the same pattern turns this spread into an iron condor without changing anything about how legs, slugs, and sizes work. Next, see selecting contracts for the full selection mechanics, then entry, exit, and timing to fire the position.

Was this page helpful?