LEAPS + Protective Put Strategy
Own a ~2-year LEAPS instead of shares. Once it is up, buy a put under it: a floor with no ceiling. Until then, sell covered calls and hold a cheap crash put. If the stock falls through the floor, bank the pair and start again.
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.Hedged by design: the protection is part of the strategy, so there is no unhedged version.
| Stock | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 YTD | CAGR | B&H CAGR | Max drawdown |
|---|---|---|---|---|---|---|---|---|---|---|
| +127.3%+112.1 | +80.0%+53.1 | −0.8%+18.7 | +43.8%+19.5 | +36.3%+13.0 | +17.8%+1.4 | +14.0%+1.5 | +41.1% | +13.4% | −39.8% | |
| +186.6%+141.5 | +24.9%−1.9 | −17.8%+15.3 | +35.2%−18.6 | +53.7%+28.8 | +22.4%+2.3 | +9.1%−3.5 | +35.7% | +18.5% | −36.5% | |
| +243.7%+225.2 | +25.4%+12.1 | −3.1%+18.5 | +18.1%+2.9 | +14.3%+4.2 | +14.5%+3.1 | +8.4%−7.0 | +32.7% | +8.2% | −35.7% | |
| +14.6%−103.1 | +31.9%−93.3 | −7.9%+42.4 | +1.2%−237.7 | +157.4%−13.8 | +27.7%−11.2 | +15.0%+15.0 | +27.7% | +65.2% | −44.2% | |
| +190.5%+113.8 | −17.4%−51.2 | −18.6%+8.2 | +37.6%−10.6 | +32.7%+2.6 | +2.6%−5.9 | +29.1%+0.6 | +25.4% | +25.2% | −56.3% |
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
Hold the stock through a ~2-year LEAPS call instead of shares
- PS1Buy the LEAPS call
When:
leg.leap.open == 0Do: buy call (as leap)delta leap_delta (0.8)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.dte <= leap_roll_dte or leg.leap.delta >= leap_roll_deltaDo: close leap; buy call (as leap)delta leap_delta (0.8)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120 - Rule
When:
leg.leap.open == 0Do: nothing (hold)
2. Floor put
Once the LEAPS call is up, buy a put under it: a floor with no ceiling
- PS2The stock is up enough since the LEAPS call buy: buy the floor put
When:
leg.leap.open == 1andspot >= leg.leap.entry_spot * (1 + lock_step)Do: buy put (as floor_put)delta floor_delta (0.3)expiry leg.leap.expirystrike_min leg.leap.strike + 0.001strike_max spot - 0.001require new.strike > leg.leap.strike and new.strike < spot - PS5The LEAPS call rolled; this put belongs to the old one: sell it
When:
close_floor_on_roll == 1andleg.floor_put.entry_day < leg.leap.entry_dayDo: close floor_put - PS4The stock fell through the floor: bank the pair and start a fresh LEAPS
When:
bank_floor == 1andspot < leg.floor_put.strikeDo: close floor_put; close leap; buy call (as leap)delta leap_delta (0.8)dte leap_dte (730)dte_min leap_dte - 120dte_max leap_dte + 120 - Rule
When:
leg.floor_put.open == 0Do: nothing (hold)
3. Covered call while waiting
Until the floor is bought, sell a short call against the LEAPS call for income
- PS5The LEAPS call rolled; this call belongs to the old one: buy it back
When:
leg.wait_call.entry_day < leg.leap.entry_dayDo: close wait_call - PS2The floor is on: buy the call back so the upside is open
When:
leg.floor_put.open == 1andleg.wait_call.open == 1Do: close wait_call - PS8The call expires in days: roll it to a new one about 40 days out
When:
leg.floor_put.open == 0andspot < leg.leap.entry_spot * (1 + lock_step)andleg.wait_call.dte <= 3andleg.wait_call.mark >= 0.05 or leg.wait_call.strike < spot * 1.02Do: roll wait_calldelta call_delta (0.2)dte call_dte (40)dte_min 21dte_max 60strike_min max(spot, leg.leap.strike) + 0.001require new.mark >= 0.05 and new.strike > max(spot, leg.leap.strike) - PS8The call expires in days and no new one is worth selling: buy it back
When:
leg.floor_put.open == 0andspot < leg.leap.entry_spot * (1 + lock_step)andleg.wait_call.dte <= 3andleg.wait_call.mark >= 0.05 or leg.wait_call.strike < spot * 1.02Do: close wait_call - PS8No call open while waiting: sell one above the price and the LEAPS call
When:
leg.leap.age >= 1andleg.floor_put.open == 0andspot < leg.leap.entry_spot * (1 + lock_step)andleg.wait_call.open == 0Do: sell call (as wait_call)delta call_delta (0.2)dte call_dte (40)dte_min 21dte_max 60strike_min max(spot, leg.leap.strike) + 0.001require new.mark >= 0.05 and new.strike > max(spot, leg.leap.strike)
4. Hedge put while waiting
Until the floor is bought, hold a cheap far put against a crash
- PS9The floor is on (or there is no LEAPS): sell the crash put
When:
leg.hedge.open == 1andleg.leap.open == 0 or leg.floor_put.open == 1Do: close hedge - PS9The crash put is old, has paid off, or is too far out: swap it for a fresh one
When:
leg.hedge.open == 1andleg.hedge.dte <= hedge_replace_dte or leg.hedge.mark >= leg.hedge.cost * hedge_take_x or leg.hedge.delta >= hedge_take_delta or leg.hedge.delta < hedge_restrikeDo: close hedge; buy put (as hedge)delta hedge_delta (0.05)dte hedge_dte (90)dte_min hedge_replace_dte + 10strike_max spot - 0.001require new.strike < spot - PS9No crash put while waiting for the floor: buy one
When:
leg.hedge.open == 0andleg.leap.open == 1andleg.floor_put.open == 0Do: buy put (as hedge)delta 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.8 |
leap_dte | 730 |
leap_roll_dte | 270 |
leap_roll_delta | 0.95 |
lock_step | 0.1 |
floor_delta | 0.3 |
call_delta | 0.2 |
call_dte | 40 |
hedge_delta | 0.05 |
hedge_dte | 90 |
hedge_replace_dte | 30 |
hedge_take_x | 3 |
hedge_take_delta | 0.35 |
hedge_restrike | 0.03 |
close_floor_on_roll | 1 |
bank_floor | 1 |
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 LEAPS instead of shares. Once it is up, buy a put under it: a floor with no ceiling. Until then, sell covered calls and hold a cheap crash put. If the stock falls through the floor, bank the pair and start again.
What it is
Hold a two-year LEAPS instead of shares. Once the stock has risen about 10% since the LEAPS call was bought, buy a put under it to lock in a floor with no ceiling. Until then, sell covered calls against the LEAPS call and keep a cheap crash put. If the stock falls through the floor, sell both and start again.
When to use it
Use it when you want leveraged upside on a long-term holding but want to protect gains once the position is working, without capping the upside with a short call.
Maximum risk
Before the floor goes on, you can lose most of the LEAPS call's cost in a fall (the crash put softens a sharp one). Once the floor is on, the loss is limited to the gap between the LEAPS call and the put strike plus what the put cost.
Questions
What is a floor put here?
A put bought under the LEAPS call once the stock is up lock_step (10%). Together they act like a long call spread with no short leg: the put sets a worst case, and the upside stays open.
Why sell calls only before the floor?
Covered calls pay for waiting. Once the floor is on, the call is bought back so a rally is not capped.
What does banking the pair mean?
If the stock falls through the floor, the LEAPS call and the put are sold together at their locked value, and a fresh LEAPS starts at the new, lower price.