# VRP Fund Pitch Internal Reference (Reproducible Spec)

This document is a detailed internal reconstruction of `vrp_fund_pitch.html`, cross-checked against:

- `RenTech/strategy_stack/vrp_backtester.py`
- `RenTech/strategy_stack/vrp_backtest_theta.py`
- `RenTech/strategy_stack/portfolio_vrp_plus_vxx.py`
- `RenTech/strategy_stack/tier_a_series.py`
- `RenTech/strategy_stack/sleeve_risk_fractions.json`

It is intended to be detailed enough to reproduce the strategy behavior from scratch.

## 1) What the page describes

The page presents a stacked strategy concept:

1. **VRP core engine** (Theta options backtest)
2. **Optional macro sleeve** (daily cash bump from Tier A proxy/synthetic returns)
3. **IV overlays** (OTM put, straddle, risk reversal)
4. **VXX sleeve** (bear-call + long-call components)
5. **SPY benchmark comparison**

## 2) Code-backed vs illustrative (critical)

### Code-backed

- Regimes, structures, sizing, exits: `vrp_backtester.py`
- Run flags + data loading: `vrp_backtest_theta.py`
- Overlay/VXX merge math: `portfolio_vrp_plus_vxx.py`
- Macro proxy/synthetic formulas: `tier_a_series.py`

### Illustrative in HTML

- Hero KPI numbers in `vrp_fund_pitch.html`
- In-browser generated equity curve (`/* Illustrative curve anchored ... */`)
- JS-injected ledger rows unless regenerated from current exports

Use Python scripts/logs as canonical source of truth.

## 3) Core data model

- Options data: Theta monthly parquet chunks (default `RenTech/data/theta_chunks`)
- Core snapshot convention: SPY 15:45 ET chunks (`spy_1545_YYYY_MM.parquet`)
- Underlying regime panel: SPY, VIX, VVIX via yfinance
- Trading days: intersection of Theta dates and SPY panel dates

## 4) Regime engine (exact map)

New options entries require:

- `SPY > SMA(200)`

VIX bands:

- R1: `VIX < 12`
- R2: `12 <= VIX <= 20`
- R3: `20 < VIX <= 30`
- R4: `VIX > 30`

## 5) Options structures by regime

From strategy config defaults in `sleeve_risk_fractions.json`:

- **R1 weekly long strangle**
  - buy ~7D +45 delta call
  - buy ~7D -18 delta put
- **R2a put diagonal**
  - sell ~21D -30 delta put
  - buy ~45D -15 delta put
- **R2b put credit spread**
  - sell ~30D -22 delta put
  - buy ~30D -9 delta put
- **R3 put spread**
  - sell ~45D -15 delta put
  - buy ~45D -7 delta put
- **R4 wider put spread**
  - sell ~45D -15 delta put
  - buy ~45D -5 delta put

R2 behavior is coupled at entry: R2a + R2b open together as separate managed tickets with independent exits.

## 6) Entry filters and risk multipliers

### R2 crossover filters (default ON)

In R2 band (`12 <= VIX <= 20`), extra filters require:

- `SPY_close > SMA_50`
- `vix_ma_20 / vix_max_50 < 0.95` (block when ratio is `>= 0.95`)

Exact constants in engine:

- `R2_SPY_MA_SHORT_DAYS = 50`
- `R2_VIX_MA_TO_MAX_BLOCK_ABOVE = 0.95`

Disable: `--no-r2-crossover-filters`

### Vol scaling (default ON)

From constants in `vrp_backtester.py`:

- Global cut: if VVIX > 1.15 * VVIX median(20), apply `global_mult = 0.65`
- R2 extra stress cut: `r2_mult = 0.55` when stress logic fires
- R1 is exempt from global VVIX cut in low-VIX branch

Disable: `--no-vol-scaling`

### Drawdown risk scaling (default OFF)

Enable: `--dd-risk-scaling` with defaults:

- enter reduced-risk mode at DD >= 15%
- exit reduced mode at DD <= 10%
- new-entry risk multiplier in reduced mode: 0.50

## 7) Sizing mechanics

### Legacy (flat-book wave sizing)

- `qty = floor(target_risk_usd / per_contract_risk)` (min 1)

### Overlap mode

Enable: `--overlap-portfolio`

- Daily adds use fixed per-ticket size `--overlap-slice-contracts N`
- Add only if sleeve aggregate commitment remains under same target risk cap

Important implication: with overlap on, raising risk fractions often increases concurrency allowance more than per-ticket size (unless you also raise overlap slice `N`).

## 8) Default sleeve risk fractions (from JSON)

- `pmcc`: 0.02
- `diagonal`: 0.10
- `r2_spread`: 0.05
- `naked`: 0.02
- `credit_spread`: 0.02

Caps:

- `overlay_risk_cap_frac`: 0.01
- `total_risk_cap_frac`: 0.22

If scaling sleeves up, ensure config validation still holds:

- `max(core_sleeve_frac) + sum(overlay_risk_fractions) <= total_risk_cap_frac`

## 9) Exit rules and sizing equations (deterministic)

Each managed ticket exits on first trigger:

- take profit
- stop loss
- time stop
- all legs expired

Exact engine equations:

- **R1 weekly long strangle**
  - `debit = abs(initial_net_premium)`
  - `tp_total = 0.50 * debit * qty`
  - `sl_total = -0.50 * debit * qty`
  - `time_stop_days = 7`
  - legacy sizing denominator: `max_risk = debit`

- **R2a diagonal**
  - `diag_risk_per_contract = max(body.max_margin, SIZING_MIN_MAX_RISK_USD)`
  - `tp_total = 50.0 * qty`
  - `sl_total = -150.0 * qty`
  - `time_stop_days = 14`
  - legacy sizing denominator: `diag_risk_per_contract`

- **R2b put credit spread**
  - `credit = max(0.0, initial_net_premium)`
  - `max_risk = body.max_loss_per_contract`
  - `per_c = max(max_risk, SIZING_MIN_MAX_RISK_USD)`
  - `tp_total = 0.50 * credit * qty`
  - `sl_total = -1.0 * max_risk * qty`
  - `time_stop_days = 21`
  - legacy sizing denominator: `per_c`

- **R3 put credit spread**
  - `credit = max(0.0, initial_net_premium)`
  - `max_risk = body.max_loss_per_contract`
  - `per_c = max(max_risk, SIZING_MIN_MAX_RISK_USD)`
  - `tp_total = 0.50 * credit * qty`
  - `sl_total = -1.0 * max_risk * qty`
  - `time_stop_days = 24`

- **R4 wide put credit spread**
  - `credit = max(0.0, initial_net_premium)`
  - `max_risk = body.max_loss_per_contract`
  - `per_c = max(max_risk, SIZING_MIN_MAX_RISK_USD)`
  - `tp_total = 0.50 * credit * qty`
  - `sl_total = -1.0 * max_risk * qty`
  - `time_stop_days = 24`

## 10) Execution friction (modeled, code-backed)

The page claims institutional friction; engine details are:

- default `SLIPPAGE_FACTOR = 0.20`
- semantics: pay 20% of half-spread from mid when bid/ask are available
- applies to opens, closes, and MTM marks
- `0.0` = mid-only; `1.0` = full bid/ask cross from mid

CLI override:

- `--slippage <float>`

## 11) Macro sleeve (optional)

Enable with:

- `--macro-overlay`

Daily update:

- `capital += capital * macro_frac * mean(active_band_returns)`

Controls:

- `--macro-overlay-frac F` (default 0.01)
- `--macro-overlay-no-spy200`
- `--macro-overlay-exclude-putw`

Examples of IDs used in page text and Tier A module:

- `putw_etf`, `bxm`, `pbp`
- `syn_vrp_carry`, `syn_zero_dte_vrp`, `syn_straddle_complacency`
- `syn_iron_condor_blend`, `syn_jade_lizard_blend`

## 12) Overlay + VXX merge mechanics

Use `--full-portfolio-report` in `vrp_backtest_theta.py`.

Model in `portfolio_vrp_plus_vxx.py`:

- VRP scaled relative to VRP reference capital
- Overlay/VXX sleeves scale daily raw JSONL PnL by:
  - `your_risk_budget_usd / risk_ref_usd`

Use `--portfolio-merge-json RenTech/strategy_stack/overlay_risk_fracs_optimized.json` for fraction-based sleeve sizing vs account capital (instead of legacy fixed budgets).

## 13) Reproduction commands (copy/paste)

Run from repo root:

1. Baseline VRP core:
   `cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 .venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py --no-progress`

2. Low-DD overlap style:
   `cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 .venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py --no-vol-scaling --dd-risk-scaling --overlap-portfolio --overlap-slice-contracts 1 --no-progress`

3. Full merged book (VRP + overlays + VXX):
   `cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 .venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py --full-portfolio-report --portfolio-merge-json RenTech/strategy_stack/overlay_risk_fracs_optimized.json --no-progress`

4. VRP + macro sleeve:
   `cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 .venv/bin/python RenTech/strategy_stack/vrp_backtest_theta.py --macro-overlay --macro-overlay-frac 0.01 --no-progress`

## 14) Canonical reproduction target vs page artifacts

Canonical outputs for reproduction should come from:

- terminal summaries from `vrp_backtest_theta.py`
- `bt.metrics()` in backtester runs
- merged-book output from `portfolio_vrp_plus_vxx.py`
- JSONL logs under `RenTech/data/logs/`

The HTML page can contain mixed artifacts:

- equity curve in page JS is partly synthetic/illustrative
- hero KPI figures are presentation values unless explicitly regenerated
- ledger can contain stale or older-window rows if not refreshed from current exports

## 15) Minimal implementation pseudocode

For each trading day:

1. Load SPY/VIX/VVIX + option chain snapshot.
2. Mark active positions to market.
3. Update drawdown state (if enabled).
4. If SPY <= SMA200, skip new entries.
5. Map VIX to R1-R4.
6. Compute entry risk multipliers (vol + DD).
7. Build regime structure by target DTE/delta.
8. Size ticket(s):
   - legacy: floor(risk/per-contract)
   - overlap: fixed `N` contracts/day subject to commitment cap
9. Add new positions if all gating passes.
10. Exit open positions by TP/SL/time/expiry.
11. Apply optional macro bump.
12. Update equity series and trade logs.

## 16) Known caveats

- Overlap mode can make risk scaling non-linear (fixed slice + cap logic).
- HTML chart and KPI panel are presentation artifacts unless tied to run logs.
- Macro synthetic IDs are approximations for behavior/shape studies, not exchange-index mark replication.

