Calendar Spread Strategy
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 copyShow 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
- INLow IV Rank and front IV / back IV at least iv_ratio: open the calendar
When:
book.open == 0andiv_rank <= ivr_maxDo: sell call (as front)strike spotdte dte_f (30)dte_min dte_f_min (21)dte_max dte_f_max (40)avoid_earnings 1strict 1; buy call (as back)strike leg.front.strikedte dte_b (60)dte_min dte_b_min (50)dte_max dte_b_max (80)strict 1require leg.front.iv / new.iv >= iv_ratio - TPtake_pct of the debit made: close
When:
book.pnl_pct >= take_pctDo: close front; close back - SLstop_pct of the debit lost: close
When:
book.pnl_pct <= -stop_pctDo: close front; close back - MVThe price ran move_pct from the strike: close
When:
abs(spot - leg.front.strike) / leg.front.strike >= move_pctDo: close front; close back - EXFront month nearly done: close
When:
leg.front.dte <= exit_dteDo: close front; close back - 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.
| Parameter | Default |
|---|---|
dte_f | 30 |
dte_f_min | 21 |
dte_f_max | 40 |
dte_b | 60 |
dte_b_min | 50 |
dte_b_max | 80 |
iv_ratio | 1 |
take_pct | 25 |
stop_pct | 50 |
exit_dte | 5 |
move_pct | 0.05 |
ivr_max | 40 |
Make a copy to change any of it and run your own backtest.
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.
| Period | Total return | CAGR | Max drawdown | Win rate | SPY buy & hold | Capital |
|---|---|---|---|---|---|---|
| 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
- INLow IV Rank and front IV / back IV at least iv_ratio: open the calendar
When:
book.open == 0andiv_rank <= ivr_maxDo: sell call (as front)strike spotdte dte_f (30)dte_min dte_f_min (21)dte_max dte_f_max (40)avoid_earnings 1strict 1; buy call (as back)strike leg.front.strikedte dte_b (60)dte_min dte_b_min (50)dte_max dte_b_max (80)strict 1require leg.front.iv / new.iv >= iv_ratio - TPtake_pct of the debit made: close
When:
book.pnl_pct >= take_pctDo: close front; close back - SLstop_pct of the debit lost: close
When:
book.pnl_pct <= -stop_pctDo: close front; close back - MVThe price ran move_pct from the strike: close
When:
abs(spot - leg.front.strike) / leg.front.strike >= move_pctDo: close front; close back - EXFront month nearly done: close
When:
leg.front.dte <= exit_dteDo: close front; close back - 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.
| Parameter | Default |
|---|---|
dte_f | 30 |
dte_f_min | 21 |
dte_f_max | 40 |
dte_b | 60 |
dte_b_min | 50 |
dte_b_max | 80 |
iv_ratio | 1 |
take_pct | 25 |
stop_pct | 50 |
exit_dte | 5 |
move_pct | 0.05 |
ivr_max | 40 |
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.