# VRP Strategy Improvement Plan — Agent Reference

**Session date:** 2026-05-12 / 2026-05-13  
**Context:** Follow-up to analysis showing VRP-only underperformance in 2021–2026, driven by
a sharp rise in `stop_loss` exits (89 trades, −$41k loss in 2021–2026 vs 3 trades, −$5 in
2016–2020) and damaging PMCC (R1) trades in low-volatility complacency regimes.

---

## What Was Done

### 1. Dynamic VIX Scaling at R2 Entry (`--r2-vix-scale-contracts`)

**Files changed:** `vrp_backtester.py`, `vrp_backtest_theta.py`

Added a new `_r2_scaled_contracts()` method in `VRPBacktester`. When
`--r2-vix-scale-contracts` is passed, the per-day overlap slice for **all R2 entries**
(full-mode, r2_diagonal, r2_spread, r2_pair) is scaled proportionally to the current VIX:

```
scaled_contracts = max(1, round(base_contracts × VIX / 12.0))
```

**Rationale:** Deploy more contracts when risk premium is rich (VIX near 20) and fewer when
thin (VIX near 12). At VIX=12 → 1× base; at VIX=18-20 → ~1.5–1.7× base.

**CLI flag:** `--r2-vix-scale-contracts` (action: store_true)

---

### 2. VIX Term Structure Gate at R2 Entry (`--r2-term-structure-gate`)

**Files changed:** `vrp_backtester.py`, `vrp_backtest_theta.py`

Added `^VIX9D` download alongside `^VVIX` in `load_spy_vix_from_yfinance()`. Stored as
`vix9d_close` column after forward-fill in `normalize_spy_df()`.

Added gate inside `_r2_crossover_entry_ok()`: **if VIX9D > VIX30 (front-end inverted),
block all new R2 entries for that day.** Front-end inversion signals near-term fear spikes
that historically cause short-vol R2 trades to be stopped out quickly.

Gate fires independently of `--no-r2-crossover-filters` (structural vs signal filter).

**CLI flag:** `--r2-term-structure-gate` (action: store_true)

---

### 3. Disable PMCC / R1 Regime (`--no-pmcc`)

**Files changed:** `vrp_backtester.py`, `vrp_backtest_theta.py`

Added `disable_pmcc: bool = False` parameter to `VRPBacktester.__init__()`. When True, the
R1 weekly strangle (low-VIX complacency regime, VIX < 12) is skipped in both `"full"` and
`"r1_strangle"` portfolio modes.

**Rationale:** Post-2020 PMCC trades were the single largest driver of losses. 2021–2026 had
89 `stop_loss` exits totalling −$41k; PMCC exposure in low-VIX environments where actual
realized vol exceeded implied was the primary culprit.

**CLI flag:** `--no-pmcc` (action: store_true)

---

### 4. Re-Run Risk Reversal Engine at Fixed 1 Contract

**Script:** `RenTech/strategy_stack/backtest_iv_calendar_risk_reversal.py`  
**Output:** `RenTech/data/logs/engine_iv_rr_1lot_fixed.jsonl`

```bash
cd /Users/robzingale/trading_bot
.venv/bin/python RenTech/strategy_stack/backtest_iv_calendar_risk_reversal.py \
  --artifact RenTech/data/models/vol_mispricing_xgb.joblib \
  --mode risk_reversal --contracts 1 \
  --out-trades RenTech/data/logs/engine_iv_rr_1lot_fixed.jsonl
```

**Result:** 245 trades | Σ PnL **+$8,423** | contracts = 1 per trade  
**Why:** Prior `ivx1` RR JSONL traded a variable number of contracts based on broker-risk
budget. Fixing to exactly 1 lot caps tail risk in the overlay portfolio and makes sizing
explicit.

---

### 5. New Overlay Engine: Long SPY Put Debit Spread

**Script:** `RenTech/strategy_stack/backtest_long_put_spread_overlay.py` *(new file)*  
**Output:** `RenTech/data/logs/engine_long_put_spread_1lot.jsonl`

```bash
cd /Users/robzingale/trading_bot
.venv/bin/python RenTech/strategy_stack/backtest_long_put_spread_overlay.py \
  --contracts 1 \
  --out-trades RenTech/data/logs/engine_long_put_spread_1lot.jsonl \
  2>&1 | tee RenTech/data/logs/engine_long_put_spread_1lot_run.log
```

**Result:** 59 trades | Σ PnL **+$2,319** | win rate **81%** | window 2016–2023

**Structure:** Systematic long SPY put debit spread (no XGBoost signal required):
- **Long leg:** ~−0.25Δ put (≈5% OTM)
- **Short leg:** ~−0.07Δ put (≈12% OTM)
- **Same expiry:** ~30 DTE (±10 days)
- **Roll:** every 15 trading days
- **Exit:** at expiry or when spread value ≥ 2× entry debit (profit target)

**VIX call spread proxy:** Uses existing SPY theta chain data. Profits on sharp SPY drops
(VIX spikes) at capped cost. Max loss = net debit paid per spread × contracts × 100.

**CLI options:** `--long-delta`, `--short-delta`, `--dte-target`, `--dte-band`,
`--rebalance-every`, `--profit-target-mult`, `--min-vix`, `--max-vix`,
`--contracts` or `--broker-risk-pct-of-portfolio`

---

## Benchmark Results (VRP-Only with New Flags)

**Command:**
```bash
cd /Users/robzingale/trading_bot
.venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py \
  --no-vol-scaling --dd-risk-scaling --overlap-portfolio --overlap-slice-contracts 2 \
  --no-pmcc --r2-vix-scale-contracts --r2-term-structure-gate \
  --no-progress \
  --export-trades-jsonl RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl \
  2>&1 | tee RenTech/data/logs/vrp_no_pmcc_vixscale_termgate_run.log
```

**Output:** `RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl`

| Metric | Value |
|--------|-------|
| Window | 2016-01-04 → 2026-04-02 (2577 days) |
| Capital | $100,000 |
| Ending Capital | $152,176 |
| Total Return | 52.2% |
| Max Drawdown | −5.55% |
| CAGR | 3.76% (4.20% on CAGR horizon) |
| Sharpe | 2.06 |
| Total Trades | 1,382 (677 R2a + 677 R2b + 28 R3/R4, 0 PMCC) |

---

## Portfolio Sharpe Optimization (New VRP + 1-lot RR)

**Command:**
```bash
cd /Users/robzingale/trading_bot
.venv/bin/python RenTech/strategy_stack/portfolio_vrp_plus_vxx.py \
  --vrp-trades RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl \
  --put-trades RenTech/data/logs/engine_iv_otm_put_ivx1.jsonl \
  --straddle-trades RenTech/data/logs/engine_iv_straddle_ivx1.jsonl \
  --risk-reversal-trades RenTech/data/logs/engine_iv_rr_1lot_fixed.jsonl \
  --vxx-bear-trades RenTech/data/logs/vxx_portfolio_bear_call.jsonl \
  --vxx-call-trades RenTech/data/logs/vxx_portfolio_long_call.jsonl \
  --optimize-sharpe \
  --sharpe-max-dd-pct 10 \
  --sharpe-fixed-vxx-pct 0.01 \
  --no-vxx-sweep \
  --out-csv RenTech/data/logs/portfolio_opt_v2_noPMCC_vixscale.csv \
  2>&1 | tee RenTech/data/logs/portfolio_opt_v2_noPMCC_vixscale_run.log
```

**Output:** `RenTech/data/logs/portfolio_opt_v2_noPMCC_vixscale.csv`

**Optimal allocation (10% DD cap, VXX fixed at 1%):**

| Sleeve | Fraction | USD @ $100k |
|--------|----------|-------------|
| OTM Put | 2.38% | $2,378 |
| Straddle | 24.97% | $24,974 |
| Risk Reversal | 2.20% | $2,204 |
| VXX | 1.00% | $1,000 |

**Full portfolio results:**

| Portfolio | CAGR | Sharpe | Max DD | Total Return |
|-----------|------|--------|--------|--------------|
| VRP only | 4.20% | 2.06 | −5.55% | 52.2% |
| VRP + IV overlays | 4.30% | 2.11 | −5.49% | 53.7% |
| VXX sleeve only | 0.01% | 0.65 | −0.03% | 0.1% |
| **FULL** | **4.31%** | **2.12** | **−5.49%** | **53.8%** |

---

## Prior Baseline (for Comparison)

The prior best run used the **original VRP** (with PMCC, no VIX scaling, no term gate) +
same IV/VXX sleeves:

| Portfolio | CAGR | Sharpe | Max DD | Total Return |
|-----------|------|--------|--------|--------------|
| VRP only | 6.95% | 2.49 | −5.40% | 98.5% |
| FULL | **7.13%** | **2.56** | **−5.39%** | **101.8%** |

**Key files:** `RenTech/data/logs/vrp_low_dd_ov2_vxxbundle_vrp_trades.jsonl` (VRP),
`RenTech/data/logs/portfolio_opt_10dd_sharpe_fullvrp.csv` (equity curves)

**Important note:** The new flags (no-PMCC + VIX-scale + term-gate) reduced total CAGR vs
the baseline (4.31% vs 7.13%). The PMCC/R1 regime, while damaging in 2021+, was
significantly profitable in 2016–2020. Disabling it entirely removes those early gains.
A future refinement (see TODO list below) would be to **selectively filter PMCC entries
by VIX environment** rather than disabling the regime entirely.

---

## Artifact Index

| File | Description | Key Metrics |
|------|-------------|-------------|
| `RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl` | VRP trades with all 3 new flags | 1382 trades, +$52k |
| `RenTech/data/logs/vrp_no_pmcc_vixscale_termgate_run.log` | Full run log with settings banner | — |
| `RenTech/data/logs/engine_iv_rr_1lot_fixed.jsonl` | Risk-reversal overlay, exactly 1 lot | 245 trades, +$8,423 |
| `RenTech/data/logs/engine_long_put_spread_1lot.jsonl` | Long SPY put debit spread overlay | 59 trades, +$2,319, 81% WR |
| `RenTech/data/logs/engine_long_put_spread_1lot_run.log` | Put spread run log | — |
| `RenTech/data/logs/portfolio_opt_v2_noPMCC_vixscale.csv` | Daily equity curves (4 columns) | Sharpe 2.12, DD −5.49% |
| `RenTech/data/logs/portfolio_opt_v2_noPMCC_vixscale_run.log` | Optimizer run log + allocation | — |

---

## TODO / Next Steps

### High Priority

**A. Wire put spread as 5th sleeve in `portfolio_vrp_plus_vxx.py`**

Add `--put-spread-trades` argument and corresponding sleeve to `execute_portfolio_merge()`
and `optimize_portfolio_sharpe()`. Then re-run the optimizer:

```bash
# After adding --put-spread-trades flag:
.venv/bin/python RenTech/strategy_stack/portfolio_vrp_plus_vxx.py \
  --vrp-trades RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl \
  --put-trades RenTech/data/logs/engine_iv_otm_put_ivx1.jsonl \
  --straddle-trades RenTech/data/logs/engine_iv_straddle_ivx1.jsonl \
  --risk-reversal-trades RenTech/data/logs/engine_iv_rr_1lot_fixed.jsonl \
  --put-spread-trades RenTech/data/logs/engine_long_put_spread_1lot.jsonl \
  --vxx-bear-trades RenTech/data/logs/vxx_portfolio_bear_call.jsonl \
  --vxx-call-trades RenTech/data/logs/vxx_portfolio_long_call.jsonl \
  --optimize-sharpe --sharpe-max-dd-pct 10 --sharpe-fixed-vxx-pct 0.01 \
  --no-vxx-sweep \
  --out-csv RenTech/data/logs/portfolio_opt_v3_with_putspread.csv
```

**B. Selective PMCC filter (replace blanket `--no-pmcc`)**

Instead of disabling R1 entirely, only block PMCC entries when:
- VIX is very low (< 10) AND
- 20-day realized vol < 10 (complacency trap)

This would preserve the profitable 2016–2020 PMCC trades while filtering the 2021–2026
blow-ups. Implement as `--pmcc-vix-floor FLOAT` (default 0.0 = allow all) in
`VRPBacktester`.

**C. R2 stop-loss tightening in high-VVIX environments**

The post-2020 stop-loss spike is also driven by VVIX being structurally elevated. When
VVIX > 110 (its 80th percentile), tighten R2 stop-loss multiplier from 1× to 0.5×.
Implement as `--r2-high-vvix-sl-mult FLOAT` in `VRPBacktester`.

**D. Re-run put spread engine for 2016–2026 full history**

The current put spread run only covers 2016-01-04 → 2023-12-29 (theta data gap). Confirm
whether 2024–2026 chunks exist and re-run to match the VRP window.

```bash
.venv/bin/python RenTech/strategy_stack/backtest_long_put_spread_overlay.py \
  --contracts 1 \
  --start 2016-01-04 --end 2026-04-02 \
  --out-trades RenTech/data/logs/engine_long_put_spread_1lot_full.jsonl
```

### Lower Priority

**E. Rebuild `vrp_fund_pitch.html` with new numbers**

After updating the multi-sleeve portfolio with the new VRP JSONL, regenerate:
```bash
.venv/bin/python RenTech/strategy_stack/generate_vrp_fund_pitch_multi_sleeve_assets.py
```

**F. Toggle matrix with new flags**

Add `--no-pmcc`, `--r2-vix-scale-contracts`, `--r2-term-structure-gate` as rows in
`run_vrp_toggle_matrix.py` to quantify each flag's isolated contribution.

**G. Year-by-year equity breakdown for new configuration**

Run the yearly equity analysis (as done for `portfolio_opt_10dd_sharpe_fullvrp.csv`)
against the new `portfolio_opt_v2_noPMCC_vixscale.csv` to confirm 2021–2026 improvement.

---

## Engine Flag Reference (New Flags Added This Session)

All three flags apply to `vrp_backtest_theta.py` (and are passed through to
`VRPBacktester`):

| Flag | Default | Effect |
|------|---------|--------|
| `--no-pmcc` | off | Skip R1 weekly strangle entirely (VIX < 12 days produce no new entries) |
| `--r2-vix-scale-contracts` | off | Scale R2 overlap_slice_contracts by `round(base × VIX / 12)` |
| `--r2-term-structure-gate` | off | Block R2 entries when VIX9D > VIX30 (inverted front-end) |

**Combined low-DD preset with all new flags:**
```bash
.venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py \
  --no-vol-scaling --dd-risk-scaling --overlap-portfolio --overlap-slice-contracts 2 \
  --no-pmcc --r2-vix-scale-contracts --r2-term-structure-gate \
  --no-progress \
  --export-trades-jsonl RenTech/data/logs/vrp_no_pmcc_vixscale_termgate.jsonl
```

---

## Related Documents

- `AGENTS.md` — workspace-level agent rules and workflow expectations
- `RenTech/strategy_stack/VRP_PLUS_VXX_OVERLAY_MERGE.md` — how portfolio merge scaling works
- `RenTech/strategy_stack/SHARPE_OPT_FULLBOOK_TRADE_EXPORT.md` — full trade log export workflow
- `RenTech/strategy_stack/VRP_FUND_PITCH_INTERNAL_REFERENCE.md` — canonical flag configs per preset
