← All backtests

Calendar Spread Strategy

NeutralThetaRules built-in

Sell a ~30-day at-the-money call, buy the same strike ~60 days out, when IV Rank is ivr_max or less and the front month's IV is at least iv_ratio × the back month's. Take 25%, stop at 50%, out before the front expires or if the price runs.

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. Calendar

Short front month, long back month, same strike

  1. INLow IV Rank and front IV / back IV at least iv_ratio: open the calendar When: book.open == 0 and iv_rank <= ivr_maxDo: sell call (as front) strike spot dte dte_f (30) dte_min dte_f_min (21) dte_max dte_f_max (40) avoid_earnings 1 strict 1; buy call (as back) strike leg.front.strike dte dte_b (60) dte_min dte_b_min (50) dte_max dte_b_max (80) strict 1 require leg.front.iv / new.iv >= iv_ratio
  2. TPtake_pct of the debit made: close When: book.pnl_pct >= take_pctDo: close front; close back
  3. SLstop_pct of the debit lost: close When: book.pnl_pct <= -stop_pctDo: close front; close back
  4. MVThe price ran move_pct from the strike: close When: abs(spot - leg.front.strike) / leg.front.strike >= move_pctDo: close front; close back
  5. EXFront month nearly done: close When: leg.front.dte <= exit_dteDo: close front; close back
  6. Closed 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
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.05
ivr_max40

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

neutral

Sell a ~30-day at-the-money call, buy the same strike ~60 days out, when IV Rank is ivr_max or less and the front month's IV is at least iv_ratio × the back month's. Take 25%, stop at 50%, out before the front expires or if the price runs.

What it is

Sell an at-the-money call about 30 days out and buy the same strike about 60 days out, only when the front month's implied volatility is at least as high as the back month's. Take 25% of the debit, stop at a 50% loss, and close before the front month expires or if the price moves 5% from the strike. It only opens when IV Rank is 40 or less, since a calendar gains when IV rises.

When to use it

Use it when you expect the price to stay near the strike for a few weeks, especially when near-term volatility is elevated relative to later months.

Maximum risk

The most you can lose is the debit paid. A large move either way, or a fall in the back month's volatility, can lose most of it.

SPY backtest

Calendar spread 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+436.5%+83.8%−28.5%+53.7% (134)+56.7%$1,000
1 year+240.2%+240.2%−38.1%+53.6% (56)+13.6%$1,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. Calendar

Short front month, long back month, same strike

  1. INLow IV Rank and front IV / back IV at least iv_ratio: open the calendar When: book.open == 0 and iv_rank <= ivr_maxDo: sell call (as front) strike spot dte dte_f (30) dte_min dte_f_min (21) dte_max dte_f_max (40) avoid_earnings 1 strict 1; buy call (as back) strike leg.front.strike dte dte_b (60) dte_min dte_b_min (50) dte_max dte_b_max (80) strict 1 require leg.front.iv / new.iv >= iv_ratio
  2. TPtake_pct of the debit made: close When: book.pnl_pct >= take_pctDo: close front; close back
  3. SLstop_pct of the debit lost: close When: book.pnl_pct <= -stop_pctDo: close front; close back
  4. MVThe price ran move_pct from the strike: close When: abs(spot - leg.front.strike) / leg.front.strike >= move_pctDo: close front; close back
  5. EXFront month nearly done: close When: leg.front.dte <= exit_dteDo: close front; close back
  6. Closed 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
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.05
ivr_max40

Questions

Why compare front and back month IV?

A calendar profits from the front month decaying faster. When front IV is high relative to the back, you sell rich premium and buy cheaper time.

Why is the backtest only from 2024?

The entry depends on the real term structure of volatility, which only exists in the data from February 2024, when real option closes start.

Why close if the price moves 5%?

A calendar's profit is concentrated near the strike. Once the price runs away, the spread loses value quickly and rarely recovers.

Related strategies