Strategy Mechanics
Headline basket, composition
| Ticker | Class | Strike grid (pts) | Wing width (pts) | Capital (equal-weight) |
|---|---|---|---|---|
| AAPL | Single-stock equity | $1 | 5 | $50,000 |
| MSFT | Single-stock equity | $1 | 5 | $50,000 |
| WMT | Single-stock equity | $1 | 5 | $50,000 |
| GLD | Commodity ETF | $1 | 5 | $50,000 |
Basket-level total capital: $200,000. Cross-asset diversification: 3 single-stocks (idiosyncratic vol) + 1 commodity ETF (cross-asset uncorrelated vol). All positions are put-credit-spreads (defined-risk; long-put protection at short_strike − 5 pts).
Entry construction
- Structure: Defined-risk put credit spread (short put + long put protection). No call wing, the iron-condor variant tested separately and underperformed (see Variants).
- Short put delta target: −0.16 (one-sigma OTM, BS-Greek-defined via OptionMetrics IV when available; BS pricer fallback when IV missing)
- Wing widths: 5 strike points (per-instrument strike-grid specified above)
- DTE at entry: 30 to 45 calendar days; selected expiry is the chain whose DTE is closest to 35
- Entry frequency: weekly Monday open per instrument (skipped if Monday is a holiday; defer to next session)
- One structure per name per week: no overlapping spreads in the same instrument
Exit logic, five fates
| Fate | Trigger |
|---|---|
profit_target |
Exit debit ≤ 50% of entry credit |
stop_loss |
Exit debit ≥ 200% of entry credit (gap-aware fill = min(stop, opening_gap)) |
time_exit |
DTE ≤ 21 |
emergency |
|short_delta| > 0.50 |
eos_force |
End-of-OOS forced close at last bar |
Exogenous-factor inputs to the engine
The engine uses these macro/regime indicators at every trade decision. All are non-look-ahead, point-in-time at the trade-decision timestamp.
| Series | Source | Role in engine |
|---|---|---|
| VIX (CBOE) | TWS feed | Slippage scaling (per-VIX-bucket bid-ask half-spread fraction); vol-multiplier in sizing |
| VIX3M (CBOE) | TWS feed | Vol-term-structure context for regime classification |
| VVIX (CBOE) | TWS feed | Vol-of-vol, tail-event halt threshold input |
| SKEW (CBOE) | TWS feed | Tail-risk indicator |
| IRX (3M T-bill yield) | FRED via TWS feed | Risk-free baseline for daily cash accrual + Sharpe denominator |
| TNX (10Y Treasury yield) | FRED via TWS feed | Term-structure curvature context |
| HYG − LQD spread | TWS feeds | Credit-stress proxy, tail-event halt input |
| SPY × Treasury rolling 20-day correlation | computed from SPY + TNX | Stress-multiplier in sizing when correlation regime shifts (risk-off pattern: equity-down, rates-down both moving) |
| SPX bars (open / close) | TWS feed | Market-wide gap-skip signal (Monday gap ≥ 3% → skip all entries that day); tail-event halt move thresholds |
| Per-ticker bars (4 underlyings) | OptionMetrics IvyDB Securities | Strike selection; entry/exit price recording; wing computation |
The headline result is conditioned on the entire macro context above, not just the option chains for AAPL/MSFT/WMT/GLD. The engine reads each series asof the trade-decision timestamp via pd.Series.asof(today).
Halt framework, 3 active layers
| Layer | What it does |
|---|---|
| Tail-event halt | Halt on extreme single-day market shocks: VIX up 50% or more in a day, VVIX above 150, HYG-LQD spread breaching 3 standard deviations, or SPX moving beyond a single-day threshold. |
| Drawdown halt | Halt when the basket has been underwater for more than 90 days OR drawdown exceeds 15% within a trailing 90-day window. |
| Auto-resume | Lift halt when three market-regime conditions clear simultaneously OR a 60-trading-day time fallback fires. |
Two earlier halt layers were tested in development and dropped after audit; details available in the source repository.
Per-trade sizing
| Component | Formula |
|---|---|
| Base risk per trade | min(1% × current equity, max-loss-per-spread) |
| Position size | floor(base_risk / max_loss_per_spread) |
| Vol multiplier | scale by VIX bucket (lower VIX → larger size) |
| Stress multiplier | scale by SPY-Treasury rolling correlation (risk-off → smaller size) |
| Hard cap | 1% of equity per spread, defined-risk bounded by wing × multiplier |
The 1% per-trade cap is enforced in dollars; it dominates other sizing inputs at the modest per-instrument capital ($50K each in the headline basket).
Friction model
| Item | Spec |
|---|---|
| Slippage | 30 / 50 / 75 / 100% of bid-ask half-spread for VIX buckets <20 / 20–30 / 30–40 / >40 |
| Commissions | $0.65 per option contract per side |
| Gap-aware fill | Stop-loss fill = min(stop_level, opening_gap_price) |
| Monday gap rule | Gap ≥ 1.5% adds 50% slippage; gap ≥ 3% skips entry |
| Quote source | Real OptionMetrics IvyDB chain bid/ask (not BS pricer) when available; BS pricer fallback if chain row missing |
ML overlay
The strategy includes one calibrated XGBoost overlay that contributes to the headline:
| Component | Architecture | Result | Status |
|---|---|---|---|
| Regime-stress overlay | XGBoost on 15 macro features (VIX, VIX3M, VVIX, yield-curve, SPY-Treasury correlation, HYG-LQD spread, etc.) with 5 hand-curated stress event peaks as labels. Calibration auto-select: Platt for small folds, isotonic for larger. | OOS Brier 0.1079 vs naive baseline 0.1256 = +14.1% reduction, above the 5% acceptance gate. | Activated as (1 − p_stress) book scaler. |
Book exposure on day t is scaled by (1 − p_stress_t), where p_stress_t is the calibrated probability of a stress-event peak in the next 63 trading days. Mean p_stress over the OOS window is 18%; days with p_stress > 30% are 14.6% of the sample. The overlay contributes 0.012 of excess Sharpe and tightens maximum drawdown from -0.13% to -0.12%, with Brier-score reduction +14.1% versus a naive baseline (acceptance gate at ≥5%).
We also evaluated a per-instrument trade-quality classifier. Across the four headline tickers, the classifier did not beat the majority-class log-loss baseline at the 64-71% per-instrument win rates. We use base sizing rather than ML-modulated sizing per trade, and report this as an evidence-based architecture choice in Variants.