Sharpe ~0.8-1.0 (2019-2025) avec VIX filter optimisé.
Hypothèses à tester
OTM threshold: 3%, 5%, 7%
DTE: 14, 21, 30 jours
VIX filter: (12/18), (15/20), (18/25)
Prérequis
Environnement Lean Research
Données SPY + VIX
Durée estimée: ~10 minutes
Note : Les options complètes ne sont pas disponibles dans QuantBook. Ce notebook utilise une approximation du premium basée sur Black-Scholes.
# Setup QuantBookfrom AlgorithmImports import*import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport warningsfrom scipy.stats import normwarnings.filterwarnings('ignore')plt.style.use('seaborn-v0_8-darkgrid')plt.rcParams['figure.figsize'] = (14, 5)qb = QuantBook()print("QuantBook initialisé.")
QuantBook initialisé.
1. Chargement des données
On charge les données SPY et le VIX pour la période 2019-2026.
# SPY underlyingspy = qb.add_equity("SPY", Resolution.DAILY)# Charger l'historique (2019-2026)start = datetime(2019, 1, 1)end = datetime(2026, 1, 1)spy_history = qb.history(spy.symbol, start, end, Resolution.DAILY)print(f"Donnees SPY: {len(spy_history)} lignes")# Synthetiser VIX a partir de la volatilite realisee de SPYspy_close_raw = spy_history['close'].droplevel(0)spy_returns = spy_close_raw.pct_change()realized_vol = spy_returns.rolling(21).std() * np.sqrt(252) *100vix_series = realized_vol *1.15+3.0vix_series = vix_series.clip(lower=10, upper=80)vix_series.name ='VIX'# Note: CBOE data non disponible dans Dockerprint(f"VIX synthetise: range [{vix_series.min():.1f}, {vix_series.max():.1f}]")
Donnees SPY: 1760 lignes
VIX synthetise: range [10.0, 80.0]
Chargement des données historiques du VIX via qb.add_index pour filtrer les régimes de forte volatilité.
# Preparer les donneesspy_close = spy_history['close'].droplevel(0)vix_close = vix_series# Aligner les datesdata = pd.DataFrame({'SPY': spy_close,'VIX': vix_close}).dropna()print(f"Periode: {data.index[0].date()} a {data.index[-1].date()}")print(f"Donnees: {len(data)} jours de trading")print(f"\nStatistiques SPY:")print(f" Prix initial: ${data['SPY'].iloc[0]:.2f}")print(f" Prix final: ${data['SPY'].iloc[-1]:.2f}")print(f" Return total: {(data['SPY'].iloc[-1]/data['SPY'].iloc[0] -1):.1%}")print(f"\nVIX synthetise: {data['VIX'].mean():.1f} (moyenne)")
Periode: 2019-02-01 a 2025-12-31
Donnees: 1739 jours de trading
Statistiques SPY:
Prix initial: $259.33
Prix final: $396.33
Return total: 52.8%
VIX synthetise: 14.3 (moyenne)
2. Approximation du premium d’options
Black-Scholes simplifié pour estimer le premium des puts et calls.
def estimate_option_premium(spy_price, vix, days_to_expiry, otm_pct=0.05, option_type='put'):""" Estime le premium d'une option via Black-Scholes. Parameters: - spy_price: Prix actuel SPY - vix: Volatilité implicite (en points) - days_to_expiry: Jours jusqu'à expiration - otm_pct: % OTM pour le strike - option_type: 'put' ou 'call' """# Volatilité annualisée vol = vix /100.0# Temps en années t = days_to_expiry /365.0# Strike OTMif option_type =='put': strike = spy_price * (1- otm_pct)else: strike = spy_price * (1+ otm_pct)# Taux sans risque r =0.05# Black-Scholes d1 = (np.log(spy_price / strike) + (r +0.5* vol**2) * t) / (vol * np.sqrt(t)) d2 = d1 - vol * np.sqrt(t)if option_type =='put': premium = strike * np.exp(-r * t) * norm.cdf(-d2) - spy_price * norm.cdf(-d1)else: premium = spy_price * norm.cdf(d1) - strike * np.exp(-r * t) * norm.cdf(d2)returnmax(0, premium)# Test de la fonctiontest_price =450.0test_vix =18.0test_dte =21put_premium = estimate_option_premium(test_price, test_vix, test_dte, 0.05, 'put')call_premium = estimate_option_premium(test_price, test_vix, test_dte, 0.05, 'call')print(f"Premium estimé pour SPY=${test_price}, VIX={test_vix}, DTE={test_dte}:")print(f" Put (5% OTM): ${put_premium:.2f}")print(f" Call (5% OTM): ${call_premium:.2f}")print(f"\nPut en % du sous-jacent: {(put_premium/test_price)*100:.1f}%")
Premium estimé pour SPY=$450.0, VIX=18.0, DTE=21:
Put (5% OTM): $0.95
Call (5% OTM): $1.47
Put en % du sous-jacent: 0.2%
Interprétation: Premium Wheel
VIX élevé → Premium plus élevé (avantageux pour le vendeur)
OTM 5% → Strike standard pour la stratégie wheel
DTE 21 → ~30 jours (mensuel)
La stratégie wheel génère du revenu régulier en vendant des options OTM.
3. Backtest Wheel Strategy
Simulation de la stratégie wheel avec: - Phase 1: Vendre puts quand cash - Phase 2: Vendre calls quand détient SPY - VIX filter: 15-20 (éviter extrêmes) - Exposition max: 80%