VIX Regime Filter
Cut gross exposure when the VIX spikes — carry and momentum hate risk-off regimes
Risk
Low
Holding Period
Matches the wrapped child strategy
Best For
Risk-on/off cycles where VIX leads currency moves
How it works
Most return-harvesting strategies (carry, trend-momentum, ML direction models) have their worst drawdowns during risk-off episodes — 2008, March 2020, October 2022. These crises all show up in VIX first, spiking past 25-30 before propagating through FX and rates. The VIX filter is a meta-strategy that gates any child signals: full size when VIX < 20, trim to 70% between 20-30, cut to 30% when VIX > 30. Wrapped around carry by default (the most vol-sensitive strategy).
Mathematical Foundation
final_size = original_size · M(VIX_t) where M(v) = 1 if v<20, 0.7 if 20≤v≤30, 0.3 if v>30Signal Generation Logic
- 1Collect signals from all wrapped child strategies (default: Carry Trade)
- 2For every signal, look up the latest VIX close on-or-before the signal timestamp (no look-ahead)
- 3Map VIX level to a size multiplier: <20 (calm) = 1.0 full size, 20-30 (elevated) = 0.7 trim, >30 (panic) = 0.3 flight-to-safety
- 4Rewrite signal.final_size = original · multiplier
- 5Relabel signal.strategy = 'vix_filter'
- 6If VIX data is missing from `data`, fail OPEN (multiplier = 1.0) and log a warning — safer than silently flat-lining
Parameters Explained
wrapped_strategiesChild strategies whose signals get gated. Default wraps Carry (most vol-sensitive); works well on Momentum too.
Default
[Carry]low_thresholdVIX level below which we run full size. Calibrated to the long-run VIX average (~19 since 1990).
Default
20high_thresholdVIX level above which we cut to flight-to-safety size. 30 is the historical threshold for 'significant stress'.
Default
30size_multiplier_lowScalar for low-VIX regime. Usually 1.0 = no change.
Default
1size_multiplier_midScalar for elevated VIX. 0.7 is a moderate trim.
Default
0.7size_multiplier_highScalar for panic VIX. 0.3 leaves meaningful exposure but caps damage.
Default
0.3When It Works
Strategies whose drawdowns cluster with VIX spikes — carry unwinds, trend reversals, credit-linked trades. Historically VIX leads currency and credit moves by 1-3 days during crises.
When It Fails
Slow-burn drawdowns (think 2018 Q4 grind lower) where VIX only modestly elevates. Also penalizes legitimate high-vol opportunities (breakouts often fire right when VIX is elevated).
Risks & Limitations
- VIX lag: by the time VIX is at 30, most carry damage is already done; the filter reduces further damage but doesn't undo the first hit
- False positives: one-off VIX spikes (Feb 2018 VIX-maggeddon) trigger the filter but don't persist — get cut right before bounce-back
- Data dependency: missing VIX feed → pass-through (see fail-open policy). In prod, wire VIX from Yahoo ^VIX or FRED VIXCLS
- Not a substitute for proper risk limits; VIX filter reduces size, it doesn't enforce stop-outs
Implementation
Same meta-pattern as risk_parity. Expects VIX OHLCV under data['VIX'] — deployment hooks into Yahoo '^VIX' which we already fetch in live_signals. Dataclasses.replace rewrites the immutable Signal; multiplier is bucketed (not interpolated) to keep the behavior interpretable.
Model parameters
Child Strategy
Default wrapped strategy — most vol-sensitive
Low Threshold
VIX below this = full size (×1.0)
High Threshold
VIX above this = flight-to-safety size (×0.3)
Mid Multiplier
Size scale when VIX is between low and high
Academic background
Academic Basis
Based on Moreira & Muir (2017), 'Volatility-Managed Portfolios', Journal of Finance
Backtest this strategy
Run the exact model on your selected assets and date range. See trade-by-trade performance.
Backtest This →