The VRP exec twin previously opened a NEW full-envelope spread every run, overwriting the
single-slot book-state and never closing the prior one -- armed weekly it would stack N x
notional. plan_and_record_vrp now maintains a 5-rung ladder (mirrors VrpStrategy.advance):
closes rungs at 50% profit-take or DTE<=1 first, then opens at most one new rung sized at
envelope/ladder (never the full envelope) only when a slot is free. Ladder decisions are
factored into a pure, unit-tested plan_vrp_ladder helper.
Also: IbkrBroker.place_combo used the wrong parent-order action for a net-credit combo (SELL
with a negative limit); switched to BUY with a negative limit per IBKR's combo convention.
fxhnt-opra-backfill.yaml's git-sync cloned the feature branch instead of master (this Job is
applied manually post-merge). Added tests/unit/test_vrp_exec_helpers.py for the previously
untested pure P&L helpers (compute_spread_exec_return/compute_ladder_exec_return/build_pos_state).
Removed the dead --live flag from execute-vrp (plan_and_record_vrp never consulted allow_live;
the paper-envelope refusal guard is the real safety mechanism).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Freezes puts (spread band) + near-ATM calls (for the strategy's parity forward) into
xsp_option_bars, then recomputes the vrp track off the frozen table. _xsp_forward_estimate
uses min(sorted(...)) for cross-process determinism. Wires vrp_nav into the nightly job,
Definitions.assets, and cockpit_forward deps. (Controller committed after self-verifying:
subagent completed the work + augmentations but returned the malformed monitor-wait status.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The brief's test supplied only 2 loss values but cvar_daily averages the worst
ceil(0.10*n) returns (5 slots at n=42), diluting CVaR with positives -> ratio 1.69
< 1.755, unsatisfiable. Rebuilt as a genuinely fat-left VRP-shaped series (45x +0.06,
5x -0.5 at n=50 -> cvar/std ~2.98). VrpStrategy code unchanged (was already correct).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds VrpStrategy.advance() recomputing the daily book entirely off frozen
xsp_option_bars rows (parity forward -> IV inversion -> ~20-delta short
strike, real-mark daily P&L / (n_open * margin)), plus the trading_days()
helper on XspOptionBarsRepo it depends on.
Known issue: test_fat_left_tail_triggers_cvar_floor is a pure-arithmetic
assertion independent of VrpStrategy; with the merged cvar_daily's
ceil(alpha*n) discrete tail count (n=42, alpha=0.10 -> n_tail=5), the given
2-loss-day series structurally cannot exceed the 1.755 threshold (max
achievable ratio ~1.694 by brute force). Left as-authored per no-silent-
change directive; needs a follow-up fix to the test's series shape or
threshold.
One fused venue-consolidation spec, two bounded components, execution coded-but-suspended:
- Component A (centerpiece): a `vrp` sleeve rebuilt on REAL OPRA option data (XSP
put-credit-spreads, 2013→). Databento OPRA.PILLAR verified empirically (XSP/SPX bars
back to 2013-04-01). Put-call-parity forward + IV-inversion 20Δ strike + real-mark
defined-risk P&L, frozen into an xsp_option_bars PIT table. Wired to forward engine +
reconciliation gate + merged CVaR sizing + cockpit. Supersedes the parked flat-VIX
synthetic spec (biased placeholder).
- Component B (thin): UCITS-legal execution routing for the existing multistrat — modeled
track UNCHANGED (models US underlyings, long history); adds a US→UCITS instrument map +
`--venue ucits` execute path. PRIIPs blocks US ETFs on a Dutch retail account.
Both exec legs ship SUSPENDED (C1/C2/C3 pattern) — neither XSP options nor UCITS-Euronext
can be paper-executed on the US-style DU9600528 account. Crypto stays structurally on Bybit
(perp edges; IBKR can't host). Marks 2026-07-11 synthetic-VRP spec SUPERSEDED.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Paper/live ceilings ($1M/$35k) selected by execution.allow_live, folded into the
audited allocation_policy_hash. K = min(max_lev, K_vol, K_cvar) with target_cvar at
the Gaussian ES-10x multiplier -> no-op for normal strategies, de-levers fat-left-tail
sleeves (VRP). ALLOCATION_POLICY_VERSION 2. Cockpit overview shows the resolved ceiling.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Whole-branch Important: dashboard showed the stale hardcoded ceiling while the engine sizes against
the resolved (paper $1M / live $35k) ceiling. Task-5 Minor: ruff I001 import-sort.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The decommission removed infra/k8s/jobs/fxhnt-forward-cronjob.yaml, but the deploy
WorkflowTemplate still 'kubectl apply -f'd it under set -e -> deploy step exit 1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 'combined' crypto-momentum book was retired; its legacy forward-tracking path is
now dead (the fxhnt-forward-cronjob was long since replaced by the Dagster deterministic
engine, and is already gone from the cluster). Removed: the 'forward-track' CLI command +
_FUTURES_UNIVERSE, the combined_book / combined_book_factory / combined_book_source
modules, CombinedBookStrategy + CombinedBookForwardTracker (KEEPING the load-bearing
ForwardTracker base used by the recompute engine + bybit tracks), the combined_book_*
config fields, and 5 combined-book-dedicated test files. MomentumVrpStrategy kept (a
tested strategy primitive, not a combined_book module).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The broad-Binance-universe momentum book (venue binance+glbx) was a survivorship/
microcap mirage superseded by the isolated crypto_tstrend edge + bybit_4edge. Removed
the combined_forward_nav Dagster asset (+ its cockpit_forward/paper_book_snapshot deps),
the registry entry (DB registry row auto-prunes via _seed_registry), the dashboard
headline preference, and the dead migration builder. CombinedBook modules retained
(still used by the forward-track CLI). Test fixtures repointed combined -> crypto_tstrend.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ports the Bybit execution leg off Dagster into run_bybit_testnet / execute-bybit
(both legs now CLI+CronJob; Dagster is pipelining-only). Adds a paper-validation
--paper-envelope on both legs that bypasses B2a but hard-refuses on non-paper/
non-testnet accounts and never reads strategy_allocation. Records the real exec
venue and surfaces it in the cockpit Executed-reality badge.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two execute-CLI gaps from the C3 port:
- `execute_multistrat`'s generic `except Exception` caught the ValueError `plan_and_record` raises
when a paper-envelope is refused (account not paper) and printed it as a connectivity failure
("broker error: ... reachable? ... creds/gateway set?") — misleading for a deliberate safety
refusal. `execute_bybit` had no try/except at all, so the same refusal from `run_bybit_testnet`
surfaced as a raw traceback. Both commands now catch `ValueError` distinctly, print
"paper-envelope refused: <msg>", and exit 1 — same exit code and zero orders placed, just an
honest message.
- `_resolve_paper_envelope` silently fell back to the config default whenever the flag was <= 0.0,
so `--paper-envelope -5` looked identical to "unset" and hid an operator typo. A negative flag
now raises `typer.BadParameter` instead of falling through.
Extends test_cli_execute_helpers.py: the negative-envelope rejection, and two new tests (no live
broker — YahooDataProvider/AlpacaBroker faked, run_bybit_testnet faked) proving each command's
refuse path prints the distinct message and never reaches order placement.
Task 7 deleted tests/integration/test_bybit_testnet_job_wiring.py wholesale, taking with it the
regression tests for 4 named past bugs the ported `run_bybit_testnet` code still contains but was
left untested: unlock-tier misclassification on the bare-vs-USDT-suffixed symbol (FIX 1),
mean_timing_drift dividing by the wrong denominator when a fill has no book_mark (FIX 2), the
recorded fill ts using the record-step wall clock instead of the exchange fill time (FIX 3), and
the open-orders resting-guard not aborting placement (FIX 4) — plus the per-day NAV-marker
idempotency no-op and the normal-path fills+NAV happy path. Ports all of them onto
`run_bybit_testnet` directly (not the deleted Dagster assets), patching the module's own
`fxhnt.application.bybit_testnet_run` seams instead of `adapters.orchestration.assets`. Also adds
a new run-level test for the paper-envelope refuse (non-paper account + paper_envelope>0 raises
ValueError before any order is placed) — the case the CLI-level Minor fixes in the next commit
need to stay distinct from a connectivity error.
Deliberately does NOT port `test_job_exists_with_two_assets_and_not_in_combined` or
`test_schedule_registered_on_its_own_job_stopped` — those tested the deleted Dagster job/schedule
and their absence is already asserted in test_orchestration_definitions.py.
bybit-testnet-egress.yaml widened the dagster pod's public-443 egress solely for the now-deleted
bybit_testnet_execution_job (the leg is CLI-driven via fxhnt-bybit-rebalancer now, with its own
inline NetworkPolicy) — remove the dead file rather than leave an unneeded grant on the research
pod. Also close the gap the port left on that inline NP: its external-443 rule only excepted
10.32.0.0/16 + 172.16.0.0/16, letting the rebalancer reach other cluster-internal 443 endpoints
in the wider RFC-1918 space; except the full set (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), as
the deleted NP did.
Alpaca rebalancer gains --paper-envelope 1000000; kept suspended because the
paper API keys currently 401 (regenerate + refresh secret, then arm). New
fxhnt-bybit-rebalancer runs execute-bybit --execute --paper-envelope 1000000
(bybit-testnet-credentials), suspended until testnet keys are populated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>