← All backtests

Double Calendar Spread Strategy

NeutralThetaRules built-in

At IV Rank ivr_max or less: a put calendar offset_pct below the price and a call calendar offset_pct above (front ~30 days, back ~60), when the front month's IV is at least iv_ratio × the back's. Take 25%, stop at half the debit, out before the front expires or if the price leaves the range.

Rules · the when / do flow, read-only until you make a copy
Show flow

The strategy runs as 1 track side by side. Each day, the first rule whose conditions hold in each track acts.

1. Double calendar

  1. INLow IV and the front month not cheap: open both calendars When: book.open == 0 and iv_rank <= ivr_maxDo: sell put (as pf) strike spot * (1 - offset_pct) dte dte_f (30) dte_min dte_f_min (21) dte_max dte_f_max (40) avoid_earnings 1 strict 1; buy put (as pb) strike leg.pf.strike dte dte_b (60) dte_min dte_b_min (50) dte_max dte_b_max (80) strict 1 require leg.pf.iv / new.iv >= iv_ratio; sell call (as cf) strike spot * (1 + offset_pct) expiry leg.pf.expiry strict 1; buy call (as cb) strike leg.cf.strike expiry leg.pb.expiry strict 1
  2. TPtake_pct of the debit made: close When: book.pnl_pct >= take_pctDo: close pf; close pb; close cf; close cb
  3. SLHalf the debit lost: close When: book.pnl_pct <= -stop_pctDo: close pf; close pb; close cf; close cb
  4. MVPrice left the range: close When: spot <= leg.pf.strike * (1 - move_pct) or spot >= leg.cf.strike * (1 + move_pct)Do: close pf; close pb; close cf; close cb
  5. EXFront month nearly done: close When: leg.pf.dte <= exit_dteDo: close pf; close pb; close cf; close cb
  6. Closed or expired When: book.open == 0Do: nothing (hold)

Parameters and defaults

Every named number in the rules can be changed in the Rule Builder. These are the defaults the backtest used.

ParameterDefault
ivr_max40
offset_pct0.03
dte_f30
dte_f_min21
dte_f_max40
dte_b60
dte_b_min50
dte_b_max80
iv_ratio1
take_pct25
stop_pct50
exit_dte5
move_pct0.02

Make a copy to change any of it and run your own backtest.

neutral

At IV Rank ivr_max or less: a put calendar offset_pct below the price and a call calendar offset_pct above (front ~30 days, back ~60), when the front month's IV is at least iv_ratio × the back's. Take 25%, stop at half the debit, out before the front expires or if the price leaves the range.

What it is

When IV Rank is 40 or less, open a put calendar 3% below the price and a call calendar 3% above (front about 30 days, back about 60), when the front month's IV is at least the back month's. Take 25% of the debit, stop at half the debit, and close if the price leaves the range or the front month is nearly done.

When to use it

Use it when you expect a quiet stock and low, rising implied volatility: a wider profit range than a single calendar.

Maximum risk

The most you can lose is the debit paid for both calendars.

SPY backtest

Double calendar at its default settings on SPY, each period ending Nov 4, 2026. Returns are on the capital the strategy needed at its peak (collateral and cash), including interest on idle cash.

PeriodTotal returnCAGRMax drawdownWin rateSPY buy & holdCapital
Since Feb 2024+580.4%+100.4%−20.4%+55.4% (224)+56.7%$1,000
1 year+106.1%+106.1%−31.8%+54.8% (84)+13.6%$2,000

Win rate: share of option positions closed or expired at a profit (count in brackets). SPY buy & hold: the same capital in SPY shares, price only, no dividends. Hypothetical results, not a forecast. Change the settings, ticker or dates in the Rule Builder and run your own.

The rules

The strategy runs as 1 track side by side. Each day, the first rule whose conditions hold in each track acts.

1. Double calendar

  1. INLow IV and the front month not cheap: open both calendars When: book.open == 0 and iv_rank <= ivr_maxDo: sell put (as pf) strike spot * (1 - offset_pct) dte dte_f (30) dte_min dte_f_min (21) dte_max dte_f_max (40) avoid_earnings 1 strict 1; buy put (as pb) strike leg.pf.strike dte dte_b (60) dte_min dte_b_min (50) dte_max dte_b_max (80) strict 1 require leg.pf.iv / new.iv >= iv_ratio; sell call (as cf) strike spot * (1 + offset_pct) expiry leg.pf.expiry strict 1; buy call (as cb) strike leg.cf.strike expiry leg.pb.expiry strict 1
  2. TPtake_pct of the debit made: close When: book.pnl_pct >= take_pctDo: close pf; close pb; close cf; close cb
  3. SLHalf the debit lost: close When: book.pnl_pct <= -stop_pctDo: close pf; close pb; close cf; close cb
  4. MVPrice left the range: close When: spot <= leg.pf.strike * (1 - move_pct) or spot >= leg.cf.strike * (1 + move_pct)Do: close pf; close pb; close cf; close cb
  5. EXFront month nearly done: close When: leg.pf.dte <= exit_dteDo: close pf; close pb; close cf; close cb
  6. Closed or expired When: book.open == 0Do: nothing (hold)

Parameters and defaults

Every named number in the rules can be changed in the Rule Builder. These are the defaults the backtest used.

ParameterDefault
ivr_max40
offset_pct0.03
dte_f30
dte_f_min21
dte_f_max40
dte_b60
dte_b_min50
dte_b_max80
iv_ratio1
take_pct25
stop_pct50
exit_dte5
move_pct0.02

Questions

Why only from February 2024?

Calendars depend on the gap between front- and back-month IV, which needs real option prices; those start in February 2024.

Why low IV Rank?

Calendars are long volatility: they gain if IV rises, so they are best opened when it is low.

How is it different from one calendar?

Two strikes spread the profit range wider, at about twice the cost.

Related strategies