5. Options strategies
I want to change a trading strategy · 2/5 I want to rerun the evidence · 5/5
Options are the natural instrument for an indicator that knows how big but not which way. A straddle (one call plus one put at today's price) pays if price moves a lot in either direction. An iron condor pays if price stays inside a range. You can bet on size without betting on direction.
cargo run --release --bin sd_options # every strategy, every era
cargo run --release --bin sd_options -- --sweep # choose thresholds on 2001-2018
cargo run --release --bin sd_options -- --noise 0.5 # SD sees noisy history
cargo run --release --bin sd_options -- --trades t.csv # every trade, for a spreadsheet
#The abstraction
Everything a strategy decides is in one small trait (src/strategy/mod.rs):
pub trait Strategy: Send + Sync {
fn name(&self) -> &'static str;
fn thesis(&self) -> &'static str; // one paragraph: why
fn enter(&self, ctx: &Context) -> Option<Plan>; // flat: open what?
fn exit(&self, ctx: &Context, open: &OpenView) -> bool; // in a trade: close now?
}
Context is the SD reading, the spot price and implied volatility, all
known at today's close. Plan is a list of legs (call/put, strike as a
multiple of spot, bought or sold) and days to expiry. The simulator
(sim.rs) does everything else: pricing, costs, marking to market, expiry,
bookkeeping. A new idea is about 30 lines.
#Recipe: add a strategy
- Write a struct and
impl Strategy forit instrategy/mod.rs. Put the why inthesis(). - Add it to
catalog(). - If it has a threshold, add variants to
sweep()inbin/sd_options.rsand pick the threshold from then<2019columns only. - Run
sd_optionsand compare it with itsAlways*baseline in every era.
#Pricing without option history
We have 25 years of stock prices but no historical option quotes, so options
are repriced with Black-Scholes (pricing.rs). The input that decides
everything is implied volatility (IV): the market's own estimate of how
much the stock will move. We use, in order:
- Real Cboe indices for five underlyings: VIX (SPY), VXN (QQQ), VXD
(DIA), GVZ (GLD), OVX (USO), daily since 2001–2008. ATM IV is taken as
0.88 × index (indices measure variance-swap levels, which sit above ATM
because of skew), plus a linear put skew. Results tagged
real. - A proxy for everything else:
ln IV = −0.094 + 0.391·ln RV₂₀ + 0.438·ln RV₁₂₆, fitted on those five against their indices (ρ = 0.94). Results taggedproxy.
The proxy's blind spot, stated plainly. Single-stock options price earnings announcements and other jumps. A proxy fitted to index ETFs cannot see them, so it makes single-stock options look cheaper than they really are. That flatters bought options (straddles) and punishes sold ones (condors). Treat
proxyresults as directional evidence, not as a P&L forecast.
Costs (sim.rs::Costs), per leg, per side: a half-spread of 2% of the
option's price (4% for single stocks) with a floor proportional to the
stock price, plus commission. Legs that expire worthless are not charged to
close. Returns are on capital at risk: the debit paid, or a credit
spread's widest wing minus its credit.
#The strategies, and why each exists
| Strategy | Bets on | Enters when | Exits when |
|---|---|---|---|
CoilStraddle | a big move, either way | tier ≥ 2 and SD's expected move ≥ 1.3 × implied move | +60% on risk, ≤5 days left, or the fire has decayed below half strength |
QuietCondor | a small move | no squeeze, no fire, intensity ≤ 0.35, implied ≥ 1/0.6 × SD's move | 50% of max profit, ≤5 days left, or a squeeze starts |
FireVertical | direction after a fire | just fired, |lean| ≥ 0.3; short strike at SD's expected move | 80% of max, lean flips, decay < 0.5, ≤3 days left |
SdRouter | the regime SD reports | the straddle rule (condor optional, off) | the rule of whatever it opened |
Always* | nothing | whenever flat | same profit/time exits |
The Always* baselines are the most important rows in every table. SD
earns its keep only if a strategy beats its own baseline.
#Results
Mean return on capital at risk per trade, after costs
(reports/options_clean.txt).
Size bets: SD's filter turns a losing trade into a winning one.
| 2001–13 | 2014–18 | 2019–26 | |
|---|---|---|---|
CoilStraddle, proxy IV (trades) | +13.4% (229) | +20.7% (40) | +8.5% (162) |
AlwaysStraddle, proxy IV | −8.8% | −8.0% | −3.9% |
AlwaysStraddle, real IV | −9.6% | −6.4% | −3.9% |
Buying straddles on a timer loses steadily: options charge a premium for movement, the variance risk premium. Buying them only when SD sees a deep coil whose expected move beats the implied move by 30% wins in every era. On the five real-IV ETFs, an edge that large almost never occurs (two trades in 25 years). So the real-IV evidence for this setting is thin, and the proxy's blind spot (above) means the proxy numbers are probably optimistic. Both are true at once.
How the 1.3 threshold was chosen (reports/options_sweep.txt): on
2001–2018 only, returns rise steadily with the required edge (−4.6%
real / −3.9% proxy at 1.0, up to +4.2% / +11.8% at 1.3). Above 1.45 there
are too few trades to trust. The 2019+ columns were read once, afterwards.
Calm bets: no edge after costs. The best pre-2019 QuietCondor setting
earned +1.2% (real) / +0.7% (proxy) before 2019 and −0.5% / −3.4% after.
That is not an edge. It stays in the catalog as a documented negative
result, and SdRouter leaves it switched off.
Direction bets: SD's lean loses to "always bullish". FireVertical
lost −8.4%, −10.5% and −2.4% per trade on real IV, while AlwaysBullCall
made +1.1%, −1.7% and +6.0%. That is chapter 2's finding again, in
dollars.
Under noise (reports/options_noise_*.txt, CoilStraddle 2019+
proxy): +8.5% clean, +10.5% at 0.25σ, +5.3% at 0.5σ, +0.1% at 1.0σ. The
volatility guard (chapter 4) is what keeps it from going negative.
#The recommended strategy
SdRouter, which today means CoilStraddle:
- Wait for a coil. SD v2 tier ≥ 2 (
**or***in Group C). - Compare sizes. SD's expected 21-day move vs the implied move, IV × √(21/252) × √(2/π). Buy only if SD's is at least 1.3× larger. The ThinkScript label "Vol edge" shows this using the chart's live implied volatility, so use that, not the proxy, when trading.
- Buy the one-month at-the-money straddle.
- Take +60% when offered. Otherwise close once the fire has aged past half strength (about 2.5θ after it fired), or 5 trading days before expiry.
- Size small. Win rate is about 47–60%; the edge comes from the winners being bigger than the losers. Worst single trades lost about 60% of risk.
sd2 SYMBOL prints the vol edge and whether today is a setup.