Commit Graph

940 Commits

Author SHA1 Message Date
jgrusewski
c4fb3f73eb fix(vrp): exec-twin ladder cap + per-rung sizing + combo BUY-credit sign + backfill master branch + P&L helper tests
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>
2026-07-13 00:36:11 +02:00
jgrusewski
8d0c6c67f9 feat(vrp): IBKR XSP mleg combo + execute-vrp + backfill-xsp-opra + vrp_exec twin (SUSPENDED)
place_combo (BAG combo, net credit); vrp_exec_record.plan_and_record_vrp (paper-envelope
refuse on non-paper, reuses Task-6 freeze machinery for selection); execute-vrp CLI;
backfill-xsp-opra CLI (2013-> monthly-chunked, cost-guard active for the wide band);
vrp_exec observed registry twin; fxhnt-vrp-rebalancer (suspend:true weekly) +
fxhnt-opra-backfill (manual one-time Job). Both exec paths SUSPENDED/untestable (no options
account, no live OPRA in CI) -> pure/testable contracts unit-tested (combo legs, refusal,
registry, yaml suspend). (Controller committed after self-verify + E402/ruff cleanup.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 00:15:36 +02:00
jgrusewski
4c49d94b45 refactor(vrp): batch forward-estimate mark fetch + fix stale band comment (review Minors) 2026-07-12 23:54:05 +02:00
jgrusewski
fe8d8c1ff2 fix(vrp): widen freeze band for held legs + close-on-missing-mark + guard forward-estimate KeyError
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 23:49:17 +02:00
jgrusewski
e0db586bbf feat(vrp): vrp_nav asset (freeze OPRA PIT slice -> recompute + real backtest ref) + wiring
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>
2026-07-12 23:41:10 +02:00
jgrusewski
03e12004aa feat(vrp): registry vrp entry + migration anchor builder 2026-07-12 23:29:54 +02:00
jgrusewski
3c13ec8f5b fix(vrp): deterministic ATM pair selection (min|C-P| over sorted common strikes) + chain_asof ORDER BY
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:24:55 +02:00
jgrusewski
9cdcb7b80b fix(vrp): deterministic expiry tie-break + wire real parity forward + return-basis denominator
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 23:16:51 +02:00
jgrusewski
4cc401f83b test(vrp): fix fat-left-tail CVaR test — fill the 10% tail with genuine losses
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>
2026-07-12 23:06:45 +02:00
jgrusewski
5d7aa3a3f8 feat(vrp): VrpStrategy defined-risk XSP put-spread ladder (recompute off frozen bars)
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.
2026-07-12 23:03:23 +02:00
jgrusewski
2cea5be70c feat(vrp): xsp_option_bars PIT table + repo (upsert/bars_for/chain_asof) 2026-07-12 22:56:42 +02:00
jgrusewski
e5e9f7e8de style(vrp): drop unused imports in OPRA adapter test (ruff F401) 2026-07-12 22:55:14 +02:00
jgrusewski
1c30e69a50 feat(vrp): OPRA options path on the Databento adapter (chain + bars, cost-guarded) 2026-07-12 22:52:01 +02:00
jgrusewski
1ac3627c80 feat(vrp): pure BS/IV/delta + put-call-parity forward helpers 2026-07-12 22:48:11 +02:00
jgrusewski
8da219dfa3 docs: plan — IBKR consolidation (OPRA-backed XSP-VRP + UCITS routing), 9 tasks
Component A (Tasks 1-7): VRP on real OPRA data — pure BS/IV/parity helpers, OPRA
options adapter path, xsp_option_bars PIT table+repo, VrpStrategy defined-risk ladder
recomputed off frozen bars, registry+anchor, vrp_nav asset (freeze slice + real ref),
IBKR XSP mleg exec twin (SUSPENDED). Component B (Task 8): US->UCITS execute routing
(--venue ucits) + suspended monthly CronJob. Task 9: local cockpit verify.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 22:46:16 +02:00
jgrusewski
938ea3f0cd docs: spec — IBKR consolidation (OPRA-backed XSP-VRP + UCITS multistrat routing)
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>
2026-07-12 22:38:41 +02:00
jgrusewski
4114f647d2 chore(infra): fxhnt-ibkr-rebalancer CronJob — multistrat on IBKR paper $1M (forward track while Alpaca 401)
Runs execute-multistrat --broker ibkr --execute --paper-envelope 1000000 weekdays; accrues the
observed multistrat_exec track. Whole-share rounding <0.1% at $1M. ARMED (Alpaca deploy venue waits for keys).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 23:55:35 +02:00
jgrusewski
a68a3ff929 docs: spec — defined-risk equity-VRP modeled sleeve (SPY put-credit-spreads, recompute)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 21:21:45 +02:00
jgrusewski
edeb40b541 Merge: configurable paper/live capital ceiling + CVaR-aware ex-ante sizing (B2a)
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>
2026-07-11 21:07:32 +02:00
jgrusewski
4a1d91885d test(cockpit): render assertion -> resolved paper ceiling $1M (not hardcoded $35k)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:59:22 +02:00
jgrusewski
31bc726053 fix(cockpit): overview ceiling reads resolved policy (paper/live), not hardcoded $35k; ruff import-sort
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>
2026-07-11 20:51:15 +02:00
jgrusewski
689fd3672e feat(alloc): record_allocation uses resolve_allocation_policy (paper/live ceiling, v2 hash)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:38:25 +02:00
jgrusewski
4630491454 test+guard(alloc): assert real CVaR no-op + validate cvar_alpha in _GAUSSIAN_ES (Task 4 Minors)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:33:12 +02:00
jgrusewski
51369199dc feat(alloc): CVaR-aware leverage floor K=min(max_lev,K_vol,K_cvar) (no-op for Gaussian) 2026-07-11 20:26:51 +02:00
jgrusewski
441b4b381a test(alloc): split E702 semicolon line (Task 3 Minor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:22:54 +02:00
jgrusewski
8ec63cecb5 feat(alloc): cvar_daily full-history expected-shortfall helper 2026-07-11 20:19:56 +02:00
jgrusewski
c0401f10e3 test(alloc): drop unused monkeypatch param (Task 2 Minor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 20:18:56 +02:00
jgrusewski
3bdb9c5d32 feat(alloc): cvar_alpha + resolve_allocation_policy (paper/live ceiling in hash); version 2 2026-07-11 20:15:15 +02:00
jgrusewski
08477ac5f1 feat(config): AllocationSettings paper/live capital ceilings 2026-07-11 20:10:12 +02:00
jgrusewski
884183a959 docs: plan — resolve Task 5 test-file reference
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:54:03 +02:00
jgrusewski
58d16db332 docs: plan — configurable ceiling + CVaR-aware sizing (B2a)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:53:35 +02:00
jgrusewski
55cd3af22b docs: spec fix — preserve vol-degenerate k_vol=0 fallback (CVaR is a pure floor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:51:05 +02:00
jgrusewski
b73c3a5228 docs: spec — configurable paper/live capital ceiling + CVaR-aware ex-ante sizing (B2a)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 19:48:51 +02:00
jgrusewski
bcbeb44552 fix(ci): drop deleted fxhnt-forward-cronjob.yaml from cockpit deploy apply-list
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>
2026-07-11 11:30:16 +02:00
jgrusewski
18d8d1e9cc Merge: decommission legacy combined-book forward-track (CLI + modules + cron)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:19:47 +02:00
jgrusewski
d43ecce814 chore(infra): drop dead FXHNT_COMBINED_BOOK_DATA_SOURCE env (config field removed)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:19:47 +02:00
jgrusewski
e8f0dd6c4e chore(cleanup): decommission legacy combined-book forward-track (CLI + modules + cron)
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>
2026-07-11 11:11:40 +02:00
jgrusewski
e5e17462e7 Merge: retire vestigial 'combined' crypto-momentum book (nightly + registry)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 11:01:00 +02:00
jgrusewski
391400f233 chore(strategy): retire vestigial 'combined' crypto-momentum book from nightly + registry
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>
2026-07-11 10:54:07 +02:00
jgrusewski
bfc7bbdc4b Merge: C3 — bybit exec CLI port + paper-validation envelope + exec-venue recording
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>
2026-07-11 09:26:09 +02:00
jgrusewski
9f39cc3633 docs(infra): bybit rebalancer header comment weekday->daily (matches cadence)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 02:16:48 +02:00
jgrusewski
da91c412ab fix(cli): distinct paper-envelope refuse message + reject negative --paper-envelope (Task 9 review)
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.
2026-07-11 02:15:12 +02:00
jgrusewski
7c05189aa2 test(exec): restore behavioral coverage lost porting the bybit testnet leg off Dagster (Task 9 review)
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.
2026-07-11 02:15:02 +02:00
jgrusewski
732d6e9792 fix(infra): drop orphaned dagster egress NP, tighten rebalancer RFC-1918 exclusion (Task 9 review)
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.
2026-07-11 02:14:53 +02:00
jgrusewski
609fa1b7a5 fix(infra): bybit rebalancer daily cadence (crypto 24/7, not weekday equity) (Task 9 Minor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 01:53:09 +02:00
jgrusewski
b21cab0984 chore(infra): alpaca --paper-envelope + new fxhnt-bybit-rebalancer CronJob (both suspended pending creds)
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>
2026-07-11 01:50:56 +02:00
jgrusewski
58e39955ba feat(cockpit): surface recorded exec venue in Executed-reality badge (fallback to configured) 2026-07-11 01:36:54 +02:00
jgrusewski
26e80df075 test(config): drop schedule_cron assertions (field removed, Task 7 Minor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 01:27:15 +02:00
jgrusewski
c832e94197 refactor(config): drop orphaned BybitExecutionConfig.schedule_cron (Task 7 Minor)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 01:26:46 +02:00
jgrusewski
185e504028 refactor(dagster): remove bybit exec assets/job/schedule (leg now CLI-driven)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 01:23:34 +02:00