docs(vrp): final VRP code-removal plan (discovery-workflow derived)
10-task subagent-driven removal: delete leaves first (7 vrp modules + black_scholes + DVOL pipeline + 12 tests), then callers (vrp_nav asset, XspOptionBarsRepo class, registry keys, CLI cmds, migration builder), then comment scrubs. KEEP xsp_option_bars table/model/data + OPRA .dbn (Constraint 1). Verified against tree: test_xsp_option_bars_repo.py does not exist; test_vrp_rebalancer_yaml already red (dangling manifest ref). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
474
docs/superpowers/plans/2026-07-20-vrp-code-removal.md
Normal file
474
docs/superpowers/plans/2026-07-20-vrp-code-removal.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# VRP Strategy Full Removal — Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox tracking; delete leaves before callers so imports never break mid-removal.
|
||||
|
||||
**Derived from:** a discovery workflow (24 file classifications + 3 deep-traces) — `wf_ffbdc8b5-c02`. The
|
||||
tricky shared-vs-VRP calls were resolved by trace: **DVOL pipeline = delete** (only VRP reads it),
|
||||
**black_scholes.py = delete** (VRP-only), **surfer vendor = untouched** (docstring mention only),
|
||||
**xsp_option_bars TABLE/MODEL/data = KEEP** (only the VRP-only `XspOptionBarsRepo` *class* is deleted).
|
||||
|
||||
## Goal
|
||||
|
||||
Fully delete the VRP (variance-risk-premium) strategy — the shelved/FALSIFIED equity-VRP
|
||||
sleeve and its executed twin `vrp_exec` — from the fxhnt repo, leaving **zero orphaned code,
|
||||
zero dead registry keys, and zero dangling imports**. The nightly Dagster pipeline, the cockpit
|
||||
web app, live IBKR/UCITS execution, the Bybit paper book, and all four kept crypto edges must
|
||||
remain fully functional and the pytest suite must be green at the end.
|
||||
|
||||
The removal spans four coupled clusters, all of which are VRP-exclusive per the deep-traces:
|
||||
|
||||
1. **VRP application modules**: `vrp_book`, `vrp_eval`, `vrp_defined_risk_eval`,
|
||||
`vrp_exec_record`, `vrp_marking`, `vrp_pricing`, `vrp_research`.
|
||||
2. **VRP option-math + IV plumbing**: `black_scholes.py` (VRP-only), the entire DVOL pipeline
|
||||
(`deribit_dvol.py`, `dvol_ingest.py`, the `dvol` feature panel, the unused
|
||||
`VolIndexClient.dvol()` port).
|
||||
3. **VRP persistence/orchestration**: `xsp_option_bars.py` repo class, the `vrp_nav` Dagster
|
||||
asset + its ~14 private OPRA-freeze/backfill helpers, the `backfill-xsp-opra` ingest path,
|
||||
the `VrpStrategy` builder, and the `vrp`/`vrp_exec` registry entries.
|
||||
4. **Comment/registry-string scrubs** across shared cockpit infrastructure that merely *names*
|
||||
VRP as an illustrative example.
|
||||
|
||||
## Architecture
|
||||
|
||||
VRP was ARCHIVED 2026-07-15 (fails the LOO marginal-Sharpe gate; see
|
||||
`pearl_fxhnt_diversifier_hunt_2026_07_15`). The two registry entries already carry
|
||||
`archived: True`, and `vrp_nav` is already **de-wired** from `definitions.py`'s nightly asset
|
||||
graph — so no live nightly asset materializes VRP today. What remains is dead weight plus two
|
||||
active-but-purposeless CLI/CronJob ingest paths (`ingest-dvol`, `backfill-xsp-opra`) and a set
|
||||
of stale registry keys/comment references.
|
||||
|
||||
Dependency direction (leaf → root), which dictates task order so imports never break mid-removal:
|
||||
|
||||
```
|
||||
black_scholes.py ────────────► vrp_defined_risk_eval.py ──┐
|
||||
deribit_dvol.py ─► dvol_ingest.py ─► (dvol panel) ────────┤
|
||||
xsp_option_bars.py (repo class) ──► vrp_book.py ──────────┤──► cli.py commands
|
||||
vrp_pricing.py / vrp_marking.py ──► vrp_book/eval/exec ───┤ migration_builders (_build_vrp)
|
||||
└──► assets.py vrp_nav + helpers
|
||||
registry.py vrp / vrp_exec
|
||||
forward_ingest _REF_ALIAS
|
||||
sim_curves / dashboard_service /
|
||||
app.py / definitions.py (scrub)
|
||||
```
|
||||
|
||||
Rule: delete leaf modules **and their tests together** first, then the callers that referenced
|
||||
them (asset graph, registry, CLI, migration builder), then the pure comment-scrub edits last.
|
||||
|
||||
## DVOL and black_scholes — resolved decisions (per deep-traces)
|
||||
|
||||
- **DVOL pipeline → DELETE (do not keep).** Exhaustive grep confirms the only readers of the
|
||||
`dvol` feature panel (`store.read_panel(..., "dvol")`) are `vrp_eval.py` and
|
||||
`vrp_defined_risk_eval.py`. `VolIndexClient.dvol()` (`ports/market_data.py:22`) has **zero**
|
||||
callers. DVOL is not a Dagster asset. DVOL is the Deribit IV index — a data source entirely
|
||||
distinct from the OPRA `xsp_option_bars` data being kept; there is no keep-carve-out for it.
|
||||
Delete `deribit_dvol.py`, `dvol_ingest.py`, the `ingest-dvol` CLI command, the
|
||||
`VolIndexClient.dvol()` port method, and their tests. The `dvol` warehouse rows in
|
||||
`bybit_features` are inert once nothing reads them — no migration needed; they can age out.
|
||||
|
||||
- **black_scholes.py → DELETE (VRP-only, not shared math).** The only importers are
|
||||
`vrp_defined_risk_eval.py` and its own unit test `tests/unit/test_black_scholes.py`.
|
||||
`vrp_pricing.py` defines a *separate* `bs_put` (different signature) and does **not** import
|
||||
from `black_scholes.py`, so there is no hidden cross-file sharing. Delete both files.
|
||||
|
||||
- **`xsp_option_bars` TABLE + `XspOptionBarRow` model + OPRA `.dbn` → KEEP.** Only the
|
||||
`XspOptionBarsRepo` *repo class* (`adapters/persistence/xsp_option_bars.py`) is VRP-only and
|
||||
gets deleted. The ORM row model `XspOptionBarRow` in `cockpit_models.py`, the physical table,
|
||||
the 13-year OPRA data, and `ForwardNavRepo.xsp_freeze_max_date()` (raw `SELECT max(date)`)
|
||||
all stay untouched.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
1. **KEEP the OPRA data.** Do **not** drop or migrate the `xsp_option_bars` table, do **not**
|
||||
remove `XspOptionBarRow` from `cockpit_models.py`, do **not** delete OPRA `.dbn` files, and
|
||||
do **not** touch `ForwardNavRepo.xsp_freeze_max_date()`. Only the VRP *ingest/consumer*
|
||||
machinery (`XspOptionBarsRepo` class, `_backfill_month`/`_freeze_*` helpers, `backfill-xsp-opra`)
|
||||
is removed. The freeze-staleness health axis (`_FREEZE_SOURCES = {"opra-pit"}`) stays generic.
|
||||
2. **Real-money paths must err false-WAIT, never false-EXECUTE.** VRP execution
|
||||
(`execute-vrp`/`vrp_exec_record`) is being deleted, not disabled — but during the removal no
|
||||
edit may cause any *surviving* real-money path (multistrat/UCITS IBKR, Bybit paper) to
|
||||
silently promote/execute on missing state. After removing the `vrp`/`vrp_exec` registry keys,
|
||||
confirm the cockpit gate and `forward_ingest` promotion loop still default to WAIT for every
|
||||
surviving strategy and never KeyError into a false-PASS.
|
||||
3. **Full pytest suite green before finishing.** Run `uv run pytest -n auto` (or
|
||||
`python -m pytest -n auto` per `pyproject.toml addopts = "-n auto"`) from the repo root and
|
||||
confirm 0 failures / 0 errors before the final commit. Per-task commands below are the fast
|
||||
local gate; the full-suite run in the final task is the release gate.
|
||||
4. **The false VRP STALE health alarm must be gone.** After removal, verify **no `vrp` key
|
||||
remains in `STRATEGY_REGISTRY`** (`vrp` and `vrp_exec` both removed) so the forward-health
|
||||
freeze/staleness axis and `dashboard_service._active_ibkr_account_sids()` can no longer
|
||||
surface a ghost VRP STALE row. Verification command in the final task.
|
||||
|
||||
### Pre-flight note (already-broken test)
|
||||
|
||||
`tests/unit/test_vrp_rebalancer_yaml.py` asserts the existence of
|
||||
`infra/k8s/jobs/fxhnt-vrp-rebalancer.yaml`, which **no longer exists** in the tree. This test is
|
||||
already failing/erroring at HEAD; it is deleted in Task 1 alongside the other VRP tests, which
|
||||
also removes that pre-existing red.
|
||||
|
||||
---
|
||||
|
||||
## Task 1 — Delete VRP application modules + their tests (leaves first)
|
||||
|
||||
**Files to delete (whole file):**
|
||||
- `src/fxhnt/application/vrp_book.py`
|
||||
- `src/fxhnt/application/vrp_eval.py`
|
||||
- `src/fxhnt/application/vrp_defined_risk_eval.py`
|
||||
- `src/fxhnt/application/vrp_exec_record.py`
|
||||
- `src/fxhnt/application/vrp_marking.py`
|
||||
- `src/fxhnt/application/vrp_pricing.py`
|
||||
- `src/fxhnt/application/vrp_research.py`
|
||||
- `src/fxhnt/application/black_scholes.py`
|
||||
- `tests/unit/test_vrp_book.py`
|
||||
- `tests/unit/test_vrp_pricing.py`
|
||||
- `tests/unit/test_vrp_exec_helpers.py`
|
||||
- `tests/unit/test_vrp_exec_ladder_cap.py`
|
||||
- `tests/unit/test_vrp_exec_record.py`
|
||||
- `tests/unit/test_vrp_rebalancer_yaml.py` (also clears the pre-existing red — see pre-flight note)
|
||||
- `tests/unit/test_registry_vrp.py`
|
||||
- `tests/unit/test_black_scholes.py`
|
||||
- `tests/integration/test_vrp_eval.py`
|
||||
- `tests/integration/test_vrp_defined_risk_eval.py`
|
||||
- `tests/integration/test_vrp_nav_asset.py`
|
||||
- `tests/integration/test_cockpit_vrp_render.py`
|
||||
|
||||
**Rationale:** every one of these modules is imported only by other `vrp_*` modules or by the
|
||||
`cli.py`/`assets.py`/`migration_builders.py` callers handled in later tasks. Deleting the tests
|
||||
in the *same* task prevents collection-time `ImportError` on the deleted modules. Do NOT yet
|
||||
touch `assets.py`, `cli.py`, `registry.py`, or `migration_builders.py` — those still reference
|
||||
these modules only via **lazy (in-function) imports**, so the module tree still imports cleanly
|
||||
after this task (the broken imports are inside function bodies not executed at import time). They
|
||||
are removed in Tasks 3–5.
|
||||
|
||||
**Covering test command** (must import-clean and not collect the deleted files):
|
||||
```
|
||||
uv run pytest tests/unit tests/integration -q --co 2>&1 | tail -20
|
||||
```
|
||||
Expect: collection succeeds with the deleted VRP tests absent and no `ImportError`.
|
||||
|
||||
**Commit:** `refactor(vrp): delete VRP application modules + black_scholes + their tests`
|
||||
|
||||
---
|
||||
|
||||
## Task 2 — Delete the DVOL pipeline + its tests
|
||||
|
||||
**Files to delete (whole file):**
|
||||
- `src/fxhnt/adapters/data/deribit_dvol.py`
|
||||
- `src/fxhnt/application/dvol_ingest.py`
|
||||
- `tests/integration/test_deribit_dvol.py`
|
||||
- `tests/integration/test_dvol_ingest.py`
|
||||
|
||||
**Edit `src/fxhnt/ports/market_data.py`:**
|
||||
- Remove the `VolIndexClient` Protocol (the `dvol()` method block, ~lines 21–24). Confirmed
|
||||
zero implementers and zero callers repo-wide; it is dead scaffolding.
|
||||
|
||||
**Do NOT touch:** `deribit_funding.py` and the `ingest-deribit-funding` CronJob/command —
|
||||
that is the *funding* (cross-venue carry) edge, a separate kept data source that reads the
|
||||
`funding`/`deribit_funding` features, never `dvol`.
|
||||
|
||||
**Rationale:** `ingest_dvol` and `DeribitDVOL` are consumed only by the `ingest-dvol` CLI
|
||||
command (removed in Task 3) which fed only the two VRP evaluators (deleted in Task 1). The
|
||||
`dvol` feature panel now has no readers.
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run pytest tests/integration -q --co 2>&1 | tail -20
|
||||
grep -rn "VolIndexClient\|import.*deribit_dvol\|import.*dvol_ingest" src/ | grep -v "/cli.py"
|
||||
```
|
||||
Expect: no collection errors; the grep returns only the (still-present, removed next task)
|
||||
`cli.py` lazy imports.
|
||||
|
||||
**Commit:** `refactor(vrp): delete DVOL pipeline (deribit_dvol, dvol_ingest, VolIndexClient port) + tests`
|
||||
|
||||
---
|
||||
|
||||
## Task 3 — Delete VRP + DVOL commands from `cli.py`
|
||||
|
||||
**File to edit:** `src/fxhnt/cli.py`
|
||||
|
||||
**Exact edits (delete each command block in full, including its in-function lazy imports):**
|
||||
- Delete `@app.command("execute-vrp")` `execute_vrp` (lines ~439–499), including the lazy
|
||||
`from fxhnt.application.vrp_exec_record import plan_and_record_vrp`. **Keep** the module-level
|
||||
and other commands' use of `ForwardNavRepo` — only remove this command's local import line if
|
||||
it has one; the `ForwardNavRepo` module itself is reused by `execute-multistrat` and others.
|
||||
- Delete `@app.command("ingest-dvol")` `ingest_dvol_cmd` (lines ~1217–1266), including the lazy
|
||||
`from fxhnt.adapters.data.deribit_dvol import DeribitDVOL` and
|
||||
`from fxhnt.application.dvol_ingest import ingest_dvol`.
|
||||
- Delete `@app.command("vrp-eval")` `vrp_eval` (lines ~2193–2288), including the lazy
|
||||
`from fxhnt.application.vrp_eval import (verify_vrp_edge, vrp_metrics_from_store, walk_forward_vrp)`.
|
||||
- Delete `@app.command("vrp-defined-risk-eval")` `vrp_defined_risk_eval` (lines ~2291–2403),
|
||||
including the lazy `from fxhnt.application.vrp_defined_risk_eval import (...)`.
|
||||
- Delete the private helpers `_print_vrp_verify` (~2406–2446) and `_print_vrp_walk_forward`
|
||||
(~2449–2469) — called only by the two eval commands above.
|
||||
|
||||
**Decision — `backfill-xsp-opra` (lines ~578–623): DELETE this command too.** It calls
|
||||
`_backfill_month` and `XspOptionBarsRepo`, both of which are deleted in Tasks 4/5, and its sole
|
||||
purpose is freezing OPRA marks into `xsp_option_bars` **for VRP recompute**. Keeping the OPRA
|
||||
*data* (Constraint 1) does not require keeping the *ingest path* — the data already exists and
|
||||
the only consumer of freshly-frozen marks was VRP. Delete the `@app.command("backfill-xsp-opra")`
|
||||
`backfill_xsp_opra` function and its `from fxhnt.adapters.orchestration.assets import _backfill_month`
|
||||
+ `from fxhnt.adapters.persistence.xsp_option_bars import XspOptionBarsRepo` local imports. (If
|
||||
the executor finds a documented non-VRP consumer of freshly-frozen OPRA marks, stop and flag —
|
||||
none was found in the trace.)
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run python -c "import fxhnt.cli" # module must import clean
|
||||
uv run fxhnt --help >/dev/null # Typer app builds with commands gone
|
||||
grep -n "vrp\|dvol\|backfill-xsp\|VrpStrategy\|black_scholes\|XspOptionBarsRepo" src/fxhnt/cli.py
|
||||
```
|
||||
Expect: import + `--help` succeed; grep returns no hits.
|
||||
|
||||
**Commit:** `refactor(vrp): remove execute-vrp/ingest-dvol/vrp-eval/vrp-defined-risk-eval/backfill-xsp-opra CLI commands`
|
||||
|
||||
---
|
||||
|
||||
## Task 4 — Remove the `vrp_nav` asset + OPRA-freeze helpers from `assets.py`
|
||||
|
||||
**File to edit:** `src/fxhnt/adapters/orchestration/assets.py`
|
||||
|
||||
**Exact edits (delete code):**
|
||||
- Delete the `@asset`-decorated `vrp_nav` function (lines ~686–718), including its inline
|
||||
imports of `DatabentoDataProvider`, `XspOptionBarsRepo`, `VrpStrategy` (~line 694).
|
||||
- Delete the exclusive private helper chain (lines ~492–683), all VRP-only and now callerless
|
||||
after Tasks 1/3: `_iso_date`, `_forward_from_marks` (+ its inline
|
||||
`fxhnt.application.vrp_pricing.parity_forward` import ~502), `_band_contracts`,
|
||||
`_band_rows_from_marks`, `_day_marks`, `_xsp_forward_estimate`, `_freeze_xsp_slice`,
|
||||
`_freeze_day`, `_prev_trading_day`, `_DEGENERATE_FORWARD_MARKERS`,
|
||||
`_is_degenerate_forward_error`, `_freeze_latest_session` (+ its inline
|
||||
`DatabentoRangeUnavailable` import ~614), `_rough_forward`, `_backfill_month`.
|
||||
- Delete the trailing `# vrp_nav ARCHIVED 2026-07-15 — de-wired (fn kept below)` comment
|
||||
(~line 1131) — the function no longer exists below.
|
||||
- Reword the module docstring (~line 4): drop the trailing `/vrp` from the forward-track asset
|
||||
enumeration.
|
||||
|
||||
**Do NOT touch:** `deribit_funding_bars` (~825–856, unrelated Deribit perp *funding*, kept for
|
||||
cross-venue-carry), and all other assets (`futures_bars`, `bybit_*`, `multistrat_*`,
|
||||
`sixtyforty_nav`, `positioning_nav`, `xsfunding_nav`, `unlock_nav`, `cockpit_forward`, …). The
|
||||
RETIRED-track comments at ~721 and ~748 do not mention vrp — leave as-is.
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run python -c "import fxhnt.adapters.orchestration.assets"
|
||||
uv run python -c "import fxhnt.adapters.orchestration.definitions" # Dagster code-location loads
|
||||
grep -n "vrp\|Vrp\|_backfill_month\|_freeze_\|XspOptionBarsRepo\|vrp_pricing" src/fxhnt/adapters/orchestration/assets.py
|
||||
uv run pytest tests/integration/test_orchestration_definitions.py -q
|
||||
```
|
||||
Expect: both modules import clean, grep returns no hits, definitions test passes.
|
||||
|
||||
**Commit:** `refactor(vrp): delete vrp_nav Dagster asset + OPRA-freeze/backfill helper chain`
|
||||
|
||||
---
|
||||
|
||||
## Task 5 — Remove `XspOptionBarsRepo` class + the `_build_vrp` migration builder
|
||||
|
||||
**File to delete (whole file):**
|
||||
- `src/fxhnt/adapters/persistence/xsp_option_bars.py` (the `XspOptionBarsRepo` repo class).
|
||||
All callers (`vrp_book.py`, `vrp_exec_record.py`, `vrp_marking.py`, the `vrp_nav` asset, the
|
||||
`backfill-xsp-opra` command) are gone after Tasks 1/3/4.
|
||||
- **VERIFIED 2026-07-20: `tests/integration/test_xsp_option_bars_repo.py` does NOT exist in the tree** —
|
||||
do not attempt to delete it. If a repo-class test surfaces under another name during removal, delete it;
|
||||
otherwise there is no test file for this class.
|
||||
|
||||
**KEEP (Constraint 1):** `cockpit_models.XspOptionBarRow`, the `xsp_option_bars` table, and
|
||||
`ForwardNavRepo.xsp_freeze_max_date()` — none of these import or depend on the repo class.
|
||||
|
||||
**File to edit:** `src/fxhnt/adapters/orchestration/migration_builders.py`
|
||||
- Delete the `_build_vrp` closure (lines ~71–76) and its `builders["vrp"] = ("vrp_state",
|
||||
_build_vrp)` registration (~78), plus the preceding `# ---- vrp_nav: ...` comment banner (~71).
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run python -c "import fxhnt.adapters.orchestration.migration_builders"
|
||||
grep -rn "XspOptionBarsRepo\|_build_vrp\|builders\[.vrp" src/
|
||||
uv run pytest tests/ -q -k "migration or migrate" 2>&1 | tail -20
|
||||
```
|
||||
Expect: import clean, grep returns no hits (the `XspOptionBarRow` model in `cockpit_models.py`
|
||||
is a different symbol and must still be present — verify separately:
|
||||
`grep -n "class XspOptionBarRow" src/fxhnt/adapters/persistence/cockpit_models.py` returns 1 hit).
|
||||
|
||||
**Commit:** `refactor(vrp): delete XspOptionBarsRepo class + _build_vrp migration builder (keep table + XspOptionBarRow)`
|
||||
|
||||
---
|
||||
|
||||
## Task 6 — Remove `vrp`/`vrp_exec` registry keys + `forward_ingest` alias
|
||||
|
||||
**File to edit:** `src/fxhnt/registry.py`
|
||||
- Delete the `"vrp"` `STRATEGY_REGISTRY` entry (lines ~161–172) and its preceding comment
|
||||
block (~157).
|
||||
- Delete the `"vrp_exec"` `STRATEGY_REGISTRY` entry (lines ~177–186) and its preceding comment
|
||||
block (~173–176).
|
||||
- Keep the dict itself and all 9 non-VRP entries and the `FUND_INSTRUMENTS` import/re-export.
|
||||
|
||||
**File to edit:** `src/fxhnt/application/forward_ingest.py`
|
||||
- Remove the `"vrp_exec": "vrp"` pair from `_REF_ALIAS` (line ~45), leaving
|
||||
`{"multistrat_exec": "multistrat", "bybit_4edge_exec": "bybit_4edge"}`.
|
||||
|
||||
**Rationale + Constraint 4:** removing the `vrp` key is what actually kills the false VRP STALE
|
||||
health alarm — with no `vrp` in `STRATEGY_REGISTRY`, the forward-health freeze/staleness loop
|
||||
and `dashboard_service._active_ibkr_account_sids()` can no longer iterate a ghost VRP row.
|
||||
(Note: `dashboard_service._IBKR_ACCOUNT_SIDS` hard-codes `"vrp"`; that literal is fixed in
|
||||
Task 7 in the *same PR* so the window where the key is gone but the literal remains never ships.)
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run python -c "from fxhnt.registry import STRATEGY_REGISTRY; assert 'vrp' not in STRATEGY_REGISTRY and 'vrp_exec' not in STRATEGY_REGISTRY, STRATEGY_REGISTRY.keys(); print('registry clean')"
|
||||
uv run pytest tests/unit/test_forward_definition.py tests/integration/test_forward_health.py tests/integration/test_dashboard_service.py -q 2>&1 | tail -20
|
||||
```
|
||||
Expect: assertion passes; forward/dashboard tests green (these confirm surviving strategies
|
||||
still WAIT-by-default — Constraint 2).
|
||||
|
||||
**Commit:** `refactor(vrp): remove vrp/vrp_exec registry entries + forward_ingest _REF_ALIAS`
|
||||
|
||||
---
|
||||
|
||||
## Task 7 — Fix the one behavioral literal + `sim_curves` book pill (data edits)
|
||||
|
||||
These are the two non-comment edits that gate on `vrp` being a *present* registry key and would
|
||||
misbehave once it is gone (Task 6). They ship together with — or immediately after — Task 6.
|
||||
|
||||
**File to edit:** `src/fxhnt/application/dashboard_service.py`
|
||||
- Line ~30: change `_IBKR_ACCOUNT_SIDS = frozenset({"multistrat", "vrp"})` to
|
||||
`frozenset({"multistrat"})`. **Why this is behavioral, not cosmetic:** `_active_ibkr_account_sids()`
|
||||
computes `not STRATEGY_REGISTRY.get("vrp", {}).get("archived")`; once the `vrp` key is gone
|
||||
this becomes `not None` = `True`, wrongly treating `vrp` as an ACTIVE ibkr-account sid and
|
||||
rendering a ghost/broken VRP row on the IBKR account page. Removing the literal eliminates it.
|
||||
|
||||
**File to edit:** `src/fxhnt/application/sim_curves.py`
|
||||
- Line ~15: remove the `"vrp"` string from the `SIM_BOOKS` tuple, leaving
|
||||
`("bybit_4edge", "bybit_4edge_levered", "multistrat", "multistrat_levered")`. **Why:** once
|
||||
the `vrp` registry entry is gone, a `vrp` Backtest-page pill would `KeyError`/500 at request
|
||||
time in `app.py` (`registry_backtest_kind("vrp")`). The dispatch logic in `sim_returns_for`
|
||||
is generic and unchanged.
|
||||
|
||||
**Covering test command:**
|
||||
```
|
||||
uv run pytest tests/unit/test_sim_curves.py tests/integration/test_dashboard_service.py tests/integration/test_ibkr_account_detail_web.py tests/integration/test_dashboard_ibkr_holdings.py tests/integration/test_paper_books_web.py tests/integration/test_ibkr_sim_web.py -q 2>&1 | tail -20
|
||||
```
|
||||
Expect: green; no VRP row/pill; surviving books render.
|
||||
|
||||
**Commit:** `fix(vrp): drop vrp from _IBKR_ACCOUNT_SIDS and SIM_BOOKS so ghost VRP row/pill can't render`
|
||||
|
||||
---
|
||||
|
||||
## Task 8 — Delete the now-purposeless VRP/OPRA CronJob manifest
|
||||
|
||||
**File to delete:**
|
||||
- `infra/k8s/jobs/fxhnt-opra-backfill.yaml` — invokes `fxhnt backfill-xsp-opra` (deleted in
|
||||
Task 3). With the command gone this CronJob would crash-loop; its only job was freezing OPRA
|
||||
marks for VRP recompute. (The `fxhnt-vrp-rebalancer.yaml` manifest is already absent from the
|
||||
tree — nothing to delete there; its dangling test is removed in Task 1.)
|
||||
|
||||
**Do NOT touch:** `fxhnt-deribit-carry-job.yaml` (funding/carry, not DVOL),
|
||||
`fxhnt-bybit-*`, `fxhnt-ucits-rebalancer.yaml`, `fxhnt-ibkr-rebalancer.yaml`, and all other
|
||||
manifests.
|
||||
|
||||
**Covering check:**
|
||||
```
|
||||
grep -rln "vrp\|ingest-dvol\|execute-vrp\|backfill-xsp-opra" infra/ # expect: no hits
|
||||
```
|
||||
|
||||
**Commit:** `chore(vrp): remove fxhnt-opra-backfill CronJob (backfill-xsp-opra command deleted)`
|
||||
|
||||
---
|
||||
|
||||
## Task 9 — Comment/docstring scrubs (no logic change) — LAST
|
||||
|
||||
Pure prose edits that dangling-reference the deleted `vrp` strategy id. No imports, logic,
|
||||
registry entries, or types change. Batched last because none affect importability.
|
||||
|
||||
**Files + edits (reword to drop the `vrp` example, keep meaning):**
|
||||
- `src/fxhnt/adapters/orchestration/definitions.py` — lines ~10–12: drop the
|
||||
"vrp_nav ARCHIVED … KEPT in assets.py but DE-WIRED" paragraph (the "KEPT" claim is now false);
|
||||
replace with a one-line "VRP removed entirely 2026-07-20" note or delete outright.
|
||||
- `src/fxhnt/adapters/persistence/cockpit_models.py` — line ~46 (drop the `(… that would have
|
||||
caught vrp)` parenthetical or generalize to "a dead strategy"); line ~228 (drop `/vrp` from
|
||||
`(multistrat/vrp …)`).
|
||||
- `src/fxhnt/adapters/persistence/forward_nav.py` — lines ~146–147 (generalize "the vrp freeze
|
||||
table" / "a vrp recompute is bounded by this max date" to opra-pit-anchored/strategy-generic
|
||||
wording; the `xsp_freeze_max_date` query stays); line ~199 (drop the "shelved/FALSIFIED
|
||||
vrp/vrp_exec" example from the `archived: True` registry note).
|
||||
- `src/fxhnt/adapters/persistence/paper_repo.py` — line ~519 (drop `vrp` from the
|
||||
`(multistrat/vrp …)` recompute-replay parenthetical).
|
||||
- `src/fxhnt/adapters/web/app.py` — lines ~449, 453, 473, 482, 551, 567, 728, 752, 810: drop the
|
||||
`/vrp` example from each `multistrat/vrp` phrase. No code change (the archived-filter
|
||||
comprehension already yields one fewer element once `vrp` left `SIM_BOOKS`/registry).
|
||||
- `src/fxhnt/adapters/web/templates/_macros.html` — line ~61 ("2-week vrp rot"): generalize.
|
||||
- `src/fxhnt/adapters/web/templates/cockpit.html` — line ~78: drop `/vrp` from
|
||||
"two IBKR real-account books (multistrat/vrp)".
|
||||
- `src/fxhnt/application/dashboard_service.py` — comment-only lines ~27, 55, 89, 390, 416, 417:
|
||||
drop/generalize the `vrp` examples (the code literal was already fixed in Task 7).
|
||||
- `src/fxhnt/application/sim_curves.py` — lines ~2, 12, 22: drop `vrp` from the
|
||||
`multistrat/vrp` recompute-replay examples (the tuple was already fixed in Task 7).
|
||||
- `src/fxhnt/application/forward_health.py` — docstring lines ~3, 11, 13, 14, 15, 24, 31 and the
|
||||
inline comment at ~147 ("for the vrp freeze axis"): generalize away from naming `vrp` as the
|
||||
mechanism's reason for existing; the `_FREEZE_SOURCES = {"opra-pit"}` logic and
|
||||
`xsp_freeze_max_date()` call are unchanged.
|
||||
- `src/fxhnt/application/display_names.py` — lines ~2 and ~51: drop the `vrp` example id /
|
||||
option-contract example from the illustrative prose.
|
||||
- `src/fxhnt/application/em_asia_marginal_eval.py` — lines ~6, 19, 71: replace "VRP" in the
|
||||
Stage-1 kill-gate precedent comments with a VRP-agnostic phrase ("prior failed diversifier
|
||||
candidates"). No logic change.
|
||||
- `src/fxhnt/config.py` — line ~215: drop `(… that would have caught vrp)` from the
|
||||
`stale_after_business_days` comment; keep the setting + default.
|
||||
- `src/fxhnt/ports/dashboard.py` — lines ~72 and ~190: drop the `vrp` example from the
|
||||
`multistrat/vrp` IBKR-real-account docstrings. (Line ~34 is unrelated carry — leave.)
|
||||
- `src/fxhnt/vendor/surfer/__init__.py` — lines ~11–13: compress the `surfer_poc`/
|
||||
`MomentumVrpStrategy` retirement note to a plain historical line without the VRP signpost.
|
||||
|
||||
**Do NOT edit** as part of scrubbing (already covered / must not change): the `xsp_option_bars`
|
||||
query, `_FREEZE_SOURCES`, `XspOptionBarRow`, any settings field, or any Protocol field.
|
||||
|
||||
**Covering test command** (broad — scrubs must not have touched logic):
|
||||
```
|
||||
uv run python -c "import fxhnt.adapters.web.app, fxhnt.application.dashboard_service, fxhnt.application.forward_health, fxhnt.config, fxhnt.ports.dashboard, fxhnt.application.display_names, fxhnt.application.em_asia_marginal_eval, fxhnt.application.sim_curves"
|
||||
uv run pytest tests/unit/test_display_names.py tests/integration/test_dashboard_service.py -q 2>&1 | tail -20
|
||||
```
|
||||
Expect: all import clean; tests green.
|
||||
|
||||
**Commit:** `docs(vrp): scrub stale VRP comment/docstring references across cockpit + shared infra`
|
||||
|
||||
---
|
||||
|
||||
## Task 10 — Full-suite green gate + removal verification (release gate)
|
||||
|
||||
**No file edits.** Final verification against all Global Constraints.
|
||||
|
||||
**Commands (all must pass):**
|
||||
```
|
||||
# (3) full suite green
|
||||
uv run pytest -n auto 2>&1 | tail -30 # 0 failed, 0 errors
|
||||
|
||||
# (4) no vrp in registry — false STALE alarm gone
|
||||
uv run python -c "from fxhnt.registry import STRATEGY_REGISTRY; assert not any(k.startswith('vrp') for k in STRATEGY_REGISTRY), list(STRATEGY_REGISTRY); print('no vrp in registry')"
|
||||
|
||||
# no orphaned VRP code / imports anywhere in src
|
||||
grep -rn "import.*vrp_\|VrpStrategy\|deribit_dvol\|dvol_ingest\|black_scholes\|XspOptionBarsRepo\|VolIndexClient\|_backfill_month\|plan_and_record_vrp" src/ # expect: no hits
|
||||
ls src/fxhnt/application/vrp_*.py 2>&1 # expect: No such file
|
||||
ls src/fxhnt/application/black_scholes.py src/fxhnt/application/dvol_ingest.py src/fxhnt/adapters/data/deribit_dvol.py src/fxhnt/adapters/persistence/xsp_option_bars.py 2>&1 # expect: No such file (all four)
|
||||
|
||||
# (1) OPRA data kept — table model + freeze query still present
|
||||
grep -n "class XspOptionBarRow" src/fxhnt/adapters/persistence/cockpit_models.py # expect: 1 hit
|
||||
grep -n "def xsp_freeze_max_date" src/fxhnt/adapters/persistence/forward_nav.py # expect: 1 hit
|
||||
|
||||
# (2) Dagster code-location + cockpit app both import clean (no false-execute / no outage)
|
||||
uv run python -c "import fxhnt.adapters.orchestration.definitions; import fxhnt.adapters.web.app; print('definitions + app import clean')"
|
||||
|
||||
# no residual vrp mentions in infra
|
||||
grep -rln "vrp\|ingest-dvol\|execute-vrp\|backfill-xsp-opra" infra/ # expect: no hits
|
||||
```
|
||||
|
||||
**Constraint 2 spot-check:** confirm `forward_ingest`'s promotion loop and the cockpit gate
|
||||
default to WAIT for every surviving strategy (the recon-gate never false-PASSes) — covered by
|
||||
`test_forward_health.py` / `test_dashboard_service.py` in the full run; if either regresses, the
|
||||
removal touched a shared gate path and must be reverted to the last green task.
|
||||
|
||||
**Commit (only after everything above is green):** `chore(vrp): verify full VRP removal — suite green, registry clean, OPRA data intact`
|
||||
|
||||
---
|
||||
|
||||
## Post-removal note
|
||||
|
||||
After merge, update `docs/superpowers/VRP-REMOVAL-TODO.md` and project memory
|
||||
(`pearl_fxhnt_diversifier_hunt_2026_07_15.md` already says "VRP now fully DELETED (shelved)") to
|
||||
reflect that the code deletion — not just shelving — is complete, and that the OPRA
|
||||
`xsp_option_bars` data was retained per Constraint 1.
|
||||
Reference in New Issue
Block a user