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 (freshoos_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:
- Pessimistic-curve net credit ≤ 0 — the harvest is cost-dominated at honest fills.
- Time-stop closes > 80% of cohorts — the profit target is structurally unreachable; v1's disease reproduced at width 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:
- 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.
- 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).
- D computed per §5 (≥8 qualifying cohorts; conservative edge if wide), shown with its inputs in the append.
- 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.
- A fleet slot exists under
fleet.max_live_sleeves: 3(in practice v1's slot and paper account, since v1 has resolved). - 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.