LEAPS + Protective Spreads Strategy
Own a ~2-year 0.90 Δ LEAPS. At +10% (when IV Rank is 20 or more), write a 0.30 Δ call on the LEAPS call's expiry: a spread with a locked worst case. Past the call, bank it and start again. A second LEAPS starts once the first is locked. Until each lock, sell income calls; always hold a cheap crash put.
Default settings, 2020 to Nov 4, 2026.
By stock and year
Select a row to chart it below. Shade is the gap to buying and holding that stock.Unhedged: nothing protects against a crash beyond what the strategy itself holds.
| Stock | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 YTD | CAGR | B&H CAGR | Max drawdown |
|---|---|---|---|---|---|---|---|---|---|---|
| +45.6%+30.4 | +70.6%+43.7 | −14.3%+5.2 | +33.5%+9.3 | +28.1%+4.8 | +16.6%+0.2 | +13.4%+1.0 | +25.8% | +13.4% | −17.6% | |
| +111.1%+66.0 | +53.6%+26.8 | −38.0%−4.9 | +70.9%+17.1 | +20.8%−4.1 | +20.7%+0.5 | +10.2%−2.4 | +28.3% | +18.5% | −40.7% | |
| +49.0%+30.5 | +75.6%+62.3 | −15.2%+6.4 | +26.0%+10.9 | +22.6%+12.5 | +11.9%+0.5 | +17.8%+2.4 | +24.6% | +8.2% | −32.3% | |
| +93.5%−24.3 | +67.2%−58.0 | −38.3%+12.0 | +247.6%+8.6 | +150.8%−20.3 | +56.5%+17.6 | +19.2%+19.1 | +66.1% | +65.2% | −61.1% | |
| +119.5%+42.8 | +91.9%+58.1 | −11.6%+15.3 | +37.1%−11.1 | +22.1%−7.9 | +9.6%+1.0 | +22.2%−6.4 | +36.3% | +25.2% | −21.5% | |
| +69.1%+53.9 | +77.8%+50.9 | −3.7%+15.8 | +28.2%+3.9 | +25.3%+2.0 | +14.2%−2.1 | +10.9%−1.5 | +29.5% | +13.4% | −19.4% | |
| +138.8%+93.6 | +63.3%+36.5 | −26.2%+6.9 | +53.3%−0.5 | +19.7%−5.1 | +19.1%−1.1 | +7.1%−5.5 | +32.1% | +18.5% | −28.3% | |
| +87.9%+69.5 | +83.0%+69.7 | −2.4%+19.2 | +24.7%+9.6 | +19.0%+8.9 | +9.0%−2.4 | +13.1%−2.2 | +30.3% | +8.2% | −23.4% | |
| +80.9%−36.9 | +53.3%−71.9 | −37.8%+12.5 | +251.2%+12.2 | +228.4%+57.3 | +54.0%+15.1 | +16.9%+16.9 | +68.5% | +65.2% | −63.9% | |
| +121.1%+44.4 | +91.2%+57.4 | −4.6%+22.3 | +36.4%−11.8 | +20.9%−9.2 | +8.3%−0.3 | +18.3%−10.3 | +36.7% | +25.2% | −16.7% |
Growth of $10,000
Weekly closes on a log scale; the red shade is the strategy's drawdown from its last high. Returns are on the capital the strategy needed at its peak, with interest on idle cash. Hypothetical: how the backtests are made.
Rules · the when / do flow, read-only until you make a copyShow flow
The strategy runs as 4 tracks side by side. Each day, the first rule whose conditions hold in each track acts.
1. LEAPS
One ~2-year LEAPS per lot: bought, rolled when old or deep in the money, banked past the lock
- PS1Buy the LEAPS call
When:
leg.leap{lot}.open == 0Do: buy call (as leap{lot})delta leap_delta (0.9)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120 - PS5The LEAPS call is getting old or deep in the money: swap it for a fresh one
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andleg.leap{lot}.dte <= leap_roll_dte or leg.leap{lot}.delta >= leap_roll_deltaandnot (iv_rank > roll_ivr_max and leg.leap{lot}.dte > 90)Do: close income{lot}; close leap{lot}; buy call (as leap{lot})delta leap_delta (0.9)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120 - PS5The LEAPS call is getting old or deep in the money: close the spread, buy a fresh LEAPS
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 1andleg.leap{lot}.dte <= leap_roll_dte or leg.leap{lot}.delta >= leap_roll_deltaandnot (iv_rank > roll_ivr_max and leg.leap{lot}.dte > 90)Do: close lock_call{lot}; close leap{lot}; buy call (as leap{lot})delta leap_delta (0.9)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120 - PS4Past the call: the spread is near its most, so bank it and start a fresh LEAPS
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 1andspot >= leg.lock_call{lot}.strikeDo: close leap{lot}; close lock_call{lot}; buy call (as leap{lot})delta leap_delta (0.9)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120
2. Income call
Until the lock: a call sold above the LEAPS call, rolled near expiry or at half its credit
- PS8The income call is about to expire or has earned half: roll it to a new one
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andspot < leg.leap{lot}.entry_spot * (1 + lock_step) or iv_rank < lock_ivr_minandleg.income{lot}.open == 1and(leg.income{lot}.dte <= 3 and (leg.income{lot}.mark >= 0.05 or leg.income{lot}.strike < spot * 1.02)) or (income_take > 0 and leg.income{lot}.dte > 3 and leg.income{lot}.mark <= leg.income{lot}.cost * (1 - income_take))Do: roll income{lot}delta income_delta (0.2)dte income_dte (40)dte_min 21dte_max 60strike_min max(spot, leg.leap{lot}.strike) + 0.001require new.mark >= 0.05 and new.strike > max(spot, leg.leap{lot}.strike) - PS8The income call is done and no new one is worth selling: buy it back
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andspot < leg.leap{lot}.entry_spot * (1 + lock_step) or iv_rank < lock_ivr_minandleg.income{lot}.open == 1and(leg.income{lot}.dte <= 3 and (leg.income{lot}.mark >= 0.05 or leg.income{lot}.strike < spot * 1.02)) or (income_take > 0 and leg.income{lot}.dte > 3 and leg.income{lot}.mark <= leg.income{lot}.cost * (1 - income_take))Do: close income{lot} - PS8No income call while waiting: sell one above the price and the LEAPS call
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andspot < leg.leap{lot}.entry_spot * (1 + lock_step) or iv_rank < lock_ivr_minandleg.income{lot}.open == 0andleg.leap{lot}.age >= 1Do: sell call (as income{lot})delta income_delta (0.2)dte income_dte (40)dte_min 21dte_max 60strike_min max(spot, leg.leap{lot}.strike) + 0.001require new.mark >= 0.05 and new.strike > max(spot, leg.leap{lot}.strike)
3. Lock call
At +lock_step: a call on the LEAPS call's expiry turns it into a spread with a locked floor
- PS2The stock is up enough and IV is not too low: write the lock call on the LEAPS call's expiry
When:
leg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andspot >= leg.leap{lot}.entry_spot * (1 + lock_step)andnot (iv_rank < lock_ivr_min)Do: close income{lot}; sell call (as lock_call{lot})delta lock_delta (0.3)expiry leg.leap{lot}.expirystrike_min max(spot, leg.leap{lot}.strike) + 0.001require new.strike > max(spot, leg.leap{lot}.strike)
4. Crash put
Always hold a cheap far put under each LEAPS call
- PS7No LEAPS: sell the crash puts
When:
leg.leap{lot}.open == 0andleg.hedge{lot}.open == 1 or leg.lhedge{lot}.open == 1Do: close hedge{lot}; close lhedge{lot} - PS7The lock went on: swap the crash put for the locked size
When:
leg.lock_call{lot}.open == 1andleg.hedge{lot}.open == 1andlocked_hedge_delta > 0Do: close hedge{lot}; buy put (as lhedge{lot})delta locked_hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS7The lock went on: sell the crash put
When:
leg.lock_call{lot}.open == 1andleg.hedge{lot}.open == 1Do: close hedge{lot} - PS7The lock came off: swap back to the full crash put
When:
leg.lock_call{lot}.open == 0andleg.lhedge{lot}.open == 1Do: close lhedge{lot}; buy put (as hedge{lot})delta hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS7The crash put is old, has paid off, or is too far out: swap it for a fresh one
When:
leg.hedge{lot}.open == 1andleg.hedge{lot}.dte <= hedge_replace_dte or leg.hedge{lot}.mark >= leg.hedge{lot}.cost * hedge_take_x or leg.hedge{lot}.delta >= hedge_take_delta or leg.hedge{lot}.delta < hedge_restrike * hedge_delta / hedge_deltaDo: close hedge{lot}; buy put (as hedge{lot})delta hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS7The locked crash put is old, has paid off, or is too far out: swap it
When:
leg.lhedge{lot}.open == 1andleg.lhedge{lot}.dte <= hedge_replace_dte or leg.lhedge{lot}.mark >= leg.lhedge{lot}.cost * hedge_take_x or leg.lhedge{lot}.delta >= hedge_take_delta or leg.lhedge{lot}.delta < hedge_restrike * locked_hedge_delta / hedge_deltaDo: close lhedge{lot}; buy put (as lhedge{lot})delta locked_hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS7No crash put under an unlocked LEAPS: buy one
When:
hedge_delta > 0andleg.leap{lot}.open == 1andleg.lock_call{lot}.open == 0andleg.hedge{lot}.open == 0Do: buy put (as hedge{lot})delta hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS7No crash put under a locked LEAPS: buy the smaller one
When:
leg.lock_call{lot}.open == 1andleg.lhedge{lot}.open == 0andlocked_hedge_delta > 0Do: buy put (as lhedge{lot})delta locked_hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot
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 |
|---|---|
leap_delta | 0.9 |
leap_dte | 730 |
leap_roll_dte | 270 |
leap_roll_delta | 0.95 |
roll_ivr_max | 70 |
lock_step | 0.1 |
lock_delta | 0.3 |
lock_ivr_min | 20 |
income_delta | 0.2 |
income_dte | 40 |
income_take | 0.5 |
hedge_delta | 0.05 |
locked_hedge_delta | 0.05 |
hedge_dte | 90 |
hedge_replace_dte | 30 |
hedge_take_x | 3 |
hedge_take_delta | 0.35 |
hedge_restrike | 0.03 |
Make a copy to change any of it and run your own backtest.
Trade log · every open, roll, assignment and close for SPYShow trades
Loading…
Own a ~2-year 0.90 Δ LEAPS. At +10% (when IV Rank is 20 or more), write a 0.30 Δ call on the LEAPS call's expiry: a spread with a locked worst case. Past the call, bank it and start again. A second LEAPS starts once the first is locked. Until each lock, sell income calls; always hold a cheap crash put.
What it is
Hold a two-year 0.90 delta LEAPS. When the stock is up 10% and IV Rank is at least 20, sell a 0.30 delta call on the LEAPS call's own expiry, turning it into a call spread with a locked worst case. Past the short call, take the profit and start again. A second LEAPS starts once the first is locked. Before each lock, sell income calls, and always hold a cheap crash put.
When to use it
Use it when you are bullish but want gains locked in stages rather than left open, and you are comfortable trading a capped upside per spread for a known worst case.
Maximum risk
Before a lock, the LEAPS call can lose most of its value in a fall (the crash put helps in sharp ones). Once locked as a spread, the loss is limited to the net cost of the spread, and the gain is capped at its width.
Questions
Why write the lock call on the LEAPS call's expiry?
Same-expiry calls make a true vertical spread: the worst case is fixed and does not depend on how the two legs' time values drift.
Why wait for IV Rank 20 before locking?
Selling the lock call when implied volatility is very low pays little for capping the upside. Waiting for some volatility gets a better price.
What does the second LEAPS do?
Once the first LEAPS is locked, its upside is capped. A second LEAPS restores open-ended upside while the first one runs to its target.