# VRP v2 — pre-registered spec (FROZEN AT COMMIT, 2026-08-01)

**Status: HASH-FROZEN AT THIS COMMIT** (panel item D1, red-team-revised form:
freeze NOW with exactly one deferred slot — an open draft would absorb v1's
outcome; `research/2026-08-01_quant_panel_suggestions.md` §3 D1, §5
struck-in-part). Everything above the sentinel line at the bottom is pinned by
SHA-256 in `tests/test_docs_consistency.py::test_vrp_v2_spec_frozen` — the
same mechanism as the December memo and the micro-cap battery
pre-registration. **Append discipline:** dated appends below the sentinel
only, and **NONE once v1's forward-gate verdict is computable** (first day
with ≥ 126 clean-clock trading days from 2026-07-27, ~2027-01-27) — with a
single sanctioned exception: the **mechanical activation append** of §9,
which enters the one deferred constant by the formula pinned in §5 and
records the owner's decision, changing nothing else. Any other post-verdict
append would be v1-outcome absorption, the exact failure mode the red team
struck from the original "draft now, freeze after v1" sequencing.

**This document changes NO live rule.** `config/vrp.yaml` (v1) is untouched;
v1 trades its registered rule until its gate resolves. Every v2 value below
is a registration that takes effect only through the §9 activation protocol.
**Activation is a separate future decision reserved to the owner** (report
§6.5: "Whether VRP v2 runs at all… the dollars are yours"); this spec's job
is to make that decision impossible to gate-shop.

Plain-language key, used throughout: *vega* = sensitivity of the position's
value to a 1-point change in implied volatility (the "vol content");
*theta* = value gained per day from time decay; *DTE* = calendar days to
expiry; *drag* = the round-trip cost of crossing the bid-ask spread, per
share, as measured by the pessimistic twin (the ledger that re-prices every
paper fill at the worst side of the same-moment quote); *cohort* = one
open→close round trip of the single registered structure.

---

## 0. Why v2 exists (motivation only — no v2 parameter derives from v1 outcomes)

v1's own measurements, as recorded in the panel report (§4.4): the $1-wide
spread has ~no vega, burns ~40% of collected credit per 8–9-day cycle in
spread friction (~$0.07–0.08/share round trip vs ~$0.18 credit), and its
21-DTE exit guards a blow-up zone a capped-loss spread does not have. The
counterparty collecting the spread is the market maker. v2's thesis: the
variance risk premium is harvested only with actual vega, held long enough
to amortize the friction.

These v1 numbers appear here as *motivation, with attribution to the frozen
report* — they set no v2 parameter. The only v2 parameter that will ever be
derived from v1 data is the deferred drag constant **D** of §5, entered
mechanically at activation by a formula pinned today. That is the "exactly
one deferred slot" the red team required.

## 1. The registered structure (entry)

Inherited unchanged from the v1 scaffold: underlying **SPY**; structure kind
**put_credit_spread** only (safety whitelist); **one cohort at a time**
(single-structure wrapper); mleg **market** orders with the same fill
confirmation, reconcile-at-start, and fail-closed state machine; the profit
trigger's 2-read × 15-second quote confirmation (decision-fidelity amendment
2026-07-25).

Registered v2 entry values (each with its one-line justification, chosen
inside the report's ranges):

- **Entry DTE: target 45 calendar days** — nearest listed SPY expiry to 45,
  accepted within **[38, 52]**. *Why 45: theta is on the steepening part of
  its curve while vega (∝ √T) is still ~22% higher than at v1's 30-DTE
  target — the vol content v1 stripped; the ±7-day band only covers
  holiday/listing gaps (SPY lists M/W/F expiries, so the nearest is normally
  within 2 days).*
- **Short strike: the listed strike whose put delta is nearest −0.275,
  required to lie in [−0.30, −0.25]; no entry that day otherwise.** *Why the
  midpoint: pinning the center of the report's −25Δ…−30Δ band forecloses
  edge-selection inside the registered range; $1 SPY strikes are ~1–2 delta
  points apart at 45 DTE, so a qualifying strike essentially always exists.*
- **Width: $3.00** (long put 3 dollars below the short). *Why 3 of 2–3: the
  widest registered width carries the most net vega (net vega scales ~
  linearly with width — roughly 3× v1's, ~3.7× after the DTE change) and the
  best friction amortization (two legs' spread cost is ~width-independent
  while credit grows with width); the sizing arithmetic of §2 is designed
  jointly around it.*
- **Static credit floor: min_credit $0.15** — 5% of width, the exact
  convention the width 5→1 re-registration established (0.05 on width 1).
  This is the D-independent dust backstop; the operative entry filter is §5.

## 2. Sizing — the JOINT width × risk-budget registration (arithmetic at $10k)

Sizing rule (formula unchanged from v1, values re-registered jointly):

```
contracts = floor(equity × risk_budget_pct / (width × 100))
```

strike-based (credit-blind) worst case — the same measure the safety gate
recomputes. **Registered v2 value: `risk_budget_pct: 0.045`** (v1: 0.02).

The red team's finding this must fix: v1 sits **exactly at 2.00 budget
multiples** — a knife edge. The requirement is that the contract count sit
**mid-interval**, so ordinary equity noise cannot change the book. The
arithmetic at $10,000 equity:

| Config | Per-contract worst case | Budget multiple at $10k | Count | Count changes at |
|---|---|---|---|---|
| v1 (width 1, budget 2%) | $100 | 10000×0.02/100 = **2.00 exactly** | 2 | **$9,992** → 1 (an $8 dip halves the book) |
| v2 naive (width 2, budget 2%) | $200 | 200/200 = **1.00 exactly** | 1 | $9,999 → 0 (any dip flattens the sleeve) |
| v2 naive (width 3, budget 2%) | $300 | 200/300 = 0.67 | **0** | never opens below $15,000 equity — structurally flat |
| **v2 registered (width 3, budget 4.5%)** | $300 | 450/300 = **1.50 — mid-interval** | 1 | $6,667 → 0; $13,333 → 2 (**±33%** equity moves) |

At the registered pair the count is 1 across the entire $6,667–$13,333
equity band: the $8-dip knife edge is gone by construction, not by hope.
*Why 4.5%: it is the smallest round half-percent that places the $10k
account exactly mid-interval on the chosen width; risk per cohort (3.0% of
equity worst case at $10k) stays inside the fleet's smallness posture.*

## 3. The JOINT safety-gate re-registration — **OWNER COUNTERSIGN REQUIRED**

The safety gate's per-structure cap (`safety.max_option_loss_pct`, enforced
in `execution/safety.py` from strike-recomputed worst case) is **0.02** and
was registered jointly with v1's width-1 sizing. Left untouched, it makes
every v2 registration above unopenable — the red team's structural-flatness
finding: width 2 × qty 1 = $200 = **exactly 2.0%** at $10k (any dip rejects
every open); width 3 × qty 1 = $300 = 3.0% > 2.0% (flat below $15k outright).
A cap that cannot pass the registered structure is not a safety line, it is
a silent OFF switch.

**Proposed amendment, frozen here, effective only at activation with the
owner's countersign: `safety.max_option_loss_pct: 0.02 → 0.045` — equal to
the re-registered `risk_budget_pct`.** Rationale: v1's activation
deliberately unified sizing and gate onto ONE risk number (strike-based
worst case; `option_intents.py`: "one made qty-N opens flap REJECT at budget
knife-edges; one risk number now"). Keeping cap = budget preserves that
invariant exactly: `floor()` guarantees every sized structure fits the cap
at every equity, the gate rejects a qty-1 structure precisely where sizing
itself reaches zero ($6,667), and any oversized-structure bug still REJECTs
(width-5: $500 = 5% > 4.5% at $10k; a double-qty bug: $600 = 6% > 4.5%).
A cap below the budget re-opens the flap-REJECT class; a cap above it is a
second, weaker number guarding nothing the budget does not.

This is a **proposal inside a frozen spec, not a live change**: the live
keystone-pinned 0.02 stands until the activation append records the
countersign, and the `config_guard.SLEEVE_KEYSTONES["vrp"]` re-pin ships in
the same commit as the config change (house rule), at activation.

## 4. Exit rules (both pinned; whichever fires first)

- **Profit target: 50% of max profit** — the report's exact number,
  unchanged; denominator = realized fill credit, with the 2-read × 15s
  confirmation, both inherited from the 2026-07-25 fidelity amendment.
  *Why 50%: realizes the high-probability portion of the decay curve and
  recycles the budget before the slow tail.*
- **Time stop: 10 trading days after the confirmed open fill.** *Why 10 of
  7–10: the top of the registered range maximizes theta capture per round
  trip — the amortization thesis; v1 burned ~40% of credit per cycle
  precisely because its cycles were short.*

At a 45-DTE entry a 10-td (~14 calendar day) maximum hold exits by ~31 DTE
in the worst case: v1's `manage_dte: 21` zone is unreachable **by
construction** and the rule is deliberately absent from v2 (the report:
that exit guards a blow-up zone a capped-loss spread does not have). No
other discretionary exit exists; the safety gate's halts and the §6
drawdown line are the only overrides.

## 5. Entry filter and THE ONE DEFERRED SLOT

**Filter: decision-snapshot MID net credit per share ≥ k × D, with k = 3.0
pinned today.** ("Decision-snapshot mid net credit" is exactly the quantity
the twin ledger's `mid_credit` column records.) *Why k = 3: at the filter
boundary, measured friction consumes at most one-third of gross credit —
a 1.5× margin to the ≥50%-of-credit family-kill line A1 pre-registered, so
no entry that passes the filter can be cost-dominated on the twin's own
ruler.* The static $0.15 floor of §1 applies in addition (binding filter =
max of the two).

**D — the deferred drag constant — is the ONLY deferred parameter in this
spec.** It is entered at activation, mechanically, by this formula (pinned
today, red-team condition):

> **D = the median per-cohort round-trip spread drag per share on the
> POST-A1-fix pessimistic twin, over v1's full remaining window.**
>
> - A cohort qualifies only if its open AND close were both priced on the
>   post-A1-fix same-snapshot basis and both drag components are present
>   and finite; round-trip drag = open-row + close-row
>   `spread_drag_per_share`. The 4 pre-fix ledger rows (2026-07-13 …
>   2026-07-31, incl. the impossible negative close drag of 07-31) are
>   **basis-contaminated** (A1 red team) and excluded by construction.
> - **Minimum-observation rule: ≥ 8 qualifying cohorts** (mirrors
>   `kelly.min_observations: 8`). Fewer at v1 resolution → activation
>   waits until 8 exist; the twin keeps accruing. The count is the clock.
> - **Conservative band edge if wide:** if IQR(drags) > 0.5 × median, or
>   any qualifying cohort drag is negative (a measurement-integrity flag
>   under A1), use the **75th percentile** instead of the median.
> - If even the 75th percentile is ≤ 0, the feed is unstable per A1's own
>   kill language: activation is **BLOCKED** pending A1's uncertainty-band
>   resolution — a zero or negative D would silently vacate the filter.
> - k × D is rounded UP to the next cent (stricter filter, never looser).

Runtime inputs (live equity, quotes) flowing through pinned formulas — the
contract count of §2, the drawdown line of §6 — are not deferred
*parameters*; D is the only value this spec leaves open, and the only place
v1's outcome may ever touch v2's rules.

## 6. Forward gate scaffold (same 126-day design; twin from day one)

Identical scaffold to v1's `forward_gate:`, re-pinned for v2 at activation:

- `min_live_trading_days: 126` — no verdict earlier; clean clock starts at
  v2's first equity mark (fresh `oos_monitor.since`, keystoned).
- `min_forward_sharpe_lower: 0.0` — live Sharpe bootstrap 95% lower bound.
- `retire_after_consecutive_degraded: 2`.
- **Pessimistic twin active from cohort 1** — the gate evaluation reports
  both curves; a pass that exists only on the optimistic curve is not a
  pass (December memo §6, inherited).
- Regime labeling inherited from the December memo §6: record the window's
  mean VIX percentile and whether a ≥5% SPY drawdown occurred; a
  calm-regime pass is labeled "unstressed" and does not by itself justify
  scaling.

**The drawdown line that can actually bind (computed):** the line is pinned
as **5 × worst single-cohort loss**, where worst single-cohort loss is the
strike-based (credit-blind, conservative) worst case of the registered
structure, `width × $100 × qty_at_activation`. At $10k activation equity:
qty = 1 (§2), worst cohort = **$300**, line = 5 × $300 = **$1,500 = 15.0%
of activation equity** → `max_drawdown_limit: 0.15`, numerically the same
line as v1's but now *derived*, not inherited. It can genuinely bind inside
the gate window: 5 consecutive full-width wipeouts at a ≤10-td time stop is
~50 trading days < 126 (v1's same 15% line needed 7.5 wipeouts of its $200
cohorts). If activation equity puts qty elsewhere, the activation append
recomputes the line by this formula — a pinned formula over a runtime
input, not a second deferred slot. A drawdown *inside* the envelope is the
premium working, not failing (v1 config header, unchanged); the line exists
for outside.

## 7. Kill criteria (verbatim, regardless of Sharpe)

Any one of these, evaluated on the gate window, kills v2:

1. **Pessimistic-curve net credit ≤ 0** — the harvest is cost-dominated at
   honest fills.
2. **Time-stop closes > 80% of cohorts** — the profit target is
   structurally unreachable; v1's disease reproduced at width 3.
3. **Drawdown breach (§6 line) regardless of Sharpe.**

## 8. Pre-committed ceiling (in this spec's own words)

**126 trading days cannot prove the variance risk premium exists — only
that the harvest is not cost-dominated and operations are clean.** The
Sharpe leg at T=126 is a ~5–12%-power coin flip (December memo §1
arithmetic); the structural falsifiers of §7 are the real gate. A v2 PASS
is authorization to keep running a small, twin-audited experiment — never
to be retold as "the premium proved itself." A NOT-PASS on Sharpe alone is
the modal outcome and weak evidence, exactly as pre-committed for December.

## 9. Activation protocol (the only door)

Activation is the owner's decision (report §6.5), permitted only when ALL
of the following hold, and executed as ONE dated mechanical append below
the sentinel:

1. v1's forward gate has resolved (≥126 clean-clock td from 2026-07-27,
   ~2027-01-27+) and its verdict is recorded — v2 never runs beside v1.
2. **A1's family-level kill has NOT fired**: if the post-fix twin says drag
   ≥ 50% of credit even at width 2–3 structures, the family is untradable
   at retail friction and **D1 dies without activating** (report §6.5).
3. D computed per §5 (≥8 qualifying cohorts; conservative edge if wide),
   shown with its inputs in the append.
4. Owner countersigns the §3 cap amendment (0.02 → 0.045) and the §2
   budget (0.02 → 0.045). **Any value other than the frozen proposals is a
   new registration, not an append.**
5. A fleet slot exists under `fleet.max_live_sleeves: 3` (in practice v1's
   slot and paper account, since v1 has resolved).
6. The config commit re-pins `config_guard.SLEEVE_KEYSTONES["vrp"]` for
   every changed value in the same commit, and starts v2's fresh clean
   clock (`oos_monitor.since`, keystoned).

The append records: GO / NO-GO, the countersigned values, D and its
computation, the resulting entry-filter constant (k × D), the recomputed
§6 drawdown line, and nothing else.

---

dated appends land below this line; after v1's verdict is computable, only the §9 mechanical activation append may land.
