Commit Graph

289 Commits

Author SHA1 Message Date
jgrusewski
33b36f8eb8 chore(surfer): relabel combined as crypto-momentum book + retire equity-factor sleeves
- combined relabeled 'Crypto momentum book (vestigial trend overlay)': the engine is validated
  crypto momentum; the futures-trend leg riding the crypto spine has no edge and never gates.
- Retired eqfactor_long/eqfactor_tilt (US-equity price-factors — weakly-held, edge never
  established) + their orphaned shared eqfactor_scores asset. Strategy classes stay in
  equity_factor_strategy.py. _seed_registry prunes stale rows automatically.

Cockpit fleet now = 4 tracks: 2 validated crypto edges (xsfunding, unlock) + the crypto-momentum
book + the 60/40 benchmark. 7 Dagster assets. Tests updated (labels + retarget to surviving
tracks); full suite 511 passed, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 22:53:03 +02:00
jgrusewski
d0d84497c7 chore(surfer): cockpit cleanup — retire dead legacy tracks + fix seed-registry prune bug
Prune the dead/superseded paper tracks: multistrat + gd (futures/TradFi premia — falsified
this session, scale-gated, no deployable edge) + poc (old crypto residual-mom+VRP PoC,
superseded by the two validated edges). Strategy classes stay in paper_strategies.py (shelf).
Removed their assets, registry entries, job/Definitions membership, cockpit_forward deps.

ROOT-CAUSE FIX: _seed_registry() now PRUNES strategy_registry rows absent from the Python
registry — previously it merge-upserted but never deleted, so retired tracks lingered on the
dashboard forever (the stale-funding bug). Retirements now stick automatically.

Fleet now 10 assets / 6 tracks: 3 crypto edges (combined, xsfunding, unlock) + 2 equity-factor
sleeves + 60/40 benchmark. Ingest is registry-driven so leftover state files are safely ignored
(no nightly-run crash risk). Tests updated; full suite 511 passed, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 22:27:19 +02:00
jgrusewski
11b8f06d8f chore(types): fix all 80 pre-existing mypy errors across the package (annotations only)
Codebase-wide type-annotation cleanup (5 parallel agents, disjoint file sets): add missing
dict/list type parameters, function param/return annotations, fix no-any-return (float/cast/
typed returns), no-untyped-call cascades (annotate the called fn), untyped-decorator (langchain
@tool ignores), dict-item (widen JSON-column value types to match inserted values). NO runtime
logic, control flow, or values changed — pure typing. Two cosmetic guard tweaks (web/app.py
funnel, always-true added clause for mypy narrowing) behavior-identical.

mypy src/fxhnt: 80 errors -> Success: no issues found in 167 source files.
Full suite 511 passed (zero regressions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:28:52 +02:00
jgrusewski
9479cf7950 feat(surfer): deploy unlock-shorts as a paper-forward cockpit track (2nd edge live)
Mirrors the xsfunding paper-track pattern for the validated token-unlock dilution-short edge:
- adapters/data/unlock_calendar_live.UnlockCalendarLive: cached unlock calendar (DefiLlama
  emissions + CoinGecko id->ticker, weekly refresh — NOT on the nightly hot path) + live
  Binance perp prices/funding/qvol. snapshot(prev_names, asof) -> window names + prices for
  prior-book names + BTC. HTTP injectable (tests use fakes, no live network).
- application/unlock_short_strategy.UnlockShortForward: ForwardStrategy advance() — books the
  prior book's realized market-neutral return (short in-window cliff names + long BTC,
  squeeze-stopped, shock+liquidity filtered, equal-weight capped gross 1), carries new book.
- Wired: unlock_nav asset + job + Definitions + cockpit_forward dep; registry 'unlock' entry
  (gate min_days=60, Sharpe>=0.5). 13 assets now.

Tests: first-run freeze then forward booking + market-neutral P&L + shock filter (fakes).
Full suite 511 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:21:20 +02:00
jgrusewski
89a6342702 feat(surfer): risk-managed token-unlock dilution-short edge (the 2nd uncorrelated edge)
The second uncorrelated edge, found via synthesis + validated. Short insider/investor
vesting-cliff names in the 10 days before the cliff (anticipatory), market-neutral
(short alt perp + long BTC). Driver = supply dilution (NOT leverage) -> corr to funding
+0.010. Data: DefiLlama emissions + CoinGecko (free).

- domain.unlock_shorts: supply_shock (unlock notional / ADV), inverse_vol_capped_weights,
  short_leg_pnl with SQUEEZE STOP (floors per-name loss — the short-book killer). 5 tests.
- application.unlock_runner.UnlockShortRunner: full risk stack — per-name inverse-vol
  sizing + weight cap + squeeze stop + portfolio vol-target.

Risk management TAMED the naive book: unsized Sharpe 1.26 / -74% DD / DSR 0.852 (FAIL)
-> risk-managed Sharpe 1.4-2.3 / -10 to -13% DD / DSR 0.97-0.999 (PASS), positive every
year incl 2022 bear, corr to funding ~0. The squeeze stop is the high-leverage lever
(tighter stop raises Sharpe AND cuts DD by removing the moon-squeeze fat tail). Even the
un-tuned conservative config passes -> not a parameter-mining artifact.

Per-event proof: +3.38% mkt-neutral, t=6.01 (non-overlapping), monotonic dose-response,
OOS-stable. Caveat: live thin-alt gap-risk through stops; not yet forward-proven.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 20:11:07 +02:00
jgrusewski
50e7983b3c feat(surfer): xsfunding micro-live order bridge (paper -> manual delta-neutral orders)
The paper->micro-live gap for the canonical cross-sectional funding deploy: the only
order tool was crypto_funding_paper.py's cmd_orders for the RETIRED absolute harness.

- domain.cross_sectional_funding.delta_neutral_orders: pure, tested. Signed book ->
  delta-neutral legs. w>0 (long top-funding) = BUY spot + SHORT perp (short collects +funding);
  w<0 (short bottom) = SELL/borrow spot + LONG perp (long collects -funding). |weight|
  iteratively capped at max_weight + renormed to gross 1; notional/leg = w*capital/(1+1/lev)
  so spot+perp margin fits capital. Flags coins unhedgeable on Binance (no spot leg).
- CLI xsfunding-orders --capital: reads the LIVE book from tracker state, fetches Binance
  spot+perp prices, prints orders for MANUAL execution. Places NOTHING; keys never read;
  deploy only after the gate = GO. Verified: gate logic (gate.py) correctly flips WAIT->GO
  on min_days+return+Sharpe.

5 new unit tests (leg mapping, capital budget, weight cap, unhedgeable flag, empty book);
suite green, mypy clean on changed lines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 17:45:00 +02:00
jgrusewski
17fa0d0394 refactor(surfer): reconcile live funding deploy onto cross-sectional construction
The cockpit ran TWO funding tracks: 'funding' (absolute 5bp-hurdle, long-only, faithful
port of crypto_funding_paper.py) and 'xsfunding' (cross-sectional long-top/short-bottom,
delta-neutral). Investigation (regime-switch backtest) showed the absolute-hurdle variant
sits idle ~60% of days and was flat through 2022, while the cross-sectional construction
harvests funding DISPERSION, trades continuously, and made +71% in the 2022 backtest
(LUNA/FTX deleveraging dispersion). The two were a confusing parallel where the conservative
one masqueraded as the dormant crown jewel.

Retire the absolute 'funding' track (asset funding_nav, registry entry, job membership) and
promote 'xsfunding' as the canonical funding deploy (relabelled 'Crypto funding harvest
(cross-sectional, delta-neutral)'). FundingCarryStrategy stays in paper_strategies.py
(tested, on the shelf) — only the live deploy changes. Tests updated (12 assets now);
full suite 499 passed, mypy clean on changed lines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 10:37:27 +02:00
jgrusewski
92f1d0b40e fix(surfer): combined book advances on crypto spine — fixes forward-track staleness
The live combined-book forward track was frozen at 2026-06-12. Root cause: build() set
the date axis to crypto INTERSECT futures. Crypto updates daily; futures fetch is
Sunday-only + Databento-lagged, so the track could only reach the last available futures
weekday and stalled between Sunday fetches — gated by the futures trend sleeve we already
proved has no edge.

Fix: book on the CRYPTO date spine (fresh daily); the trend sleeve contributes on days it
has data (0.0 otherwise) and never gates the track. Sharpe-weights and the reported
correlation still use the real crypto-futures overlap, so weighting stays honest. The
forward tracker (append-only, forward-of-last_date) picks up the un-booked crypto days on
the next run and resumes daily advance. Tests 25 passed, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 00:06:35 +02:00
jgrusewski
bb4ec3e2ae feat(surfer): wire regime kill-switch into the live combined-book forward track
The ForwardTracker now optionally throttles booked exposure off the live track's own
running drawdown: flatten to 0 once drawdown exceeds kill_dd, re-enter once it recovers
inside reenter_dd. The drawdown SIGNAL tracks shadow (un-throttled) equity so recovery is
observable while flat; the booked NAV reflects the throttled book. No-lookahead (each
day's decision uses prior-day kill-state); state is persisted (shadow_nav/shadow_peak/
killed) and lazy-inits for tracks that predate the switch.

Wired ON in both live entry points via new settings combined_book_kill_dd (0.15) /
combined_book_reenter_dd (0.07): the Dagster combined_forward_nav asset and the
forward-track CLI. Default OFF at the tracker/factory level so existing trackers and
tests are unchanged. Tests 54 passed (incl. new live-killswitch test); mypy clean on
changed lines (pre-existing debt untouched).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 23:22:15 +02:00
jgrusewski
d04c28a148 feat(surfer): regime drawdown kill-switch for the book
apply_drawdown_killswitch: flatten the book once running drawdown exceeds kill_dd
(default 15%), re-enter only after recovery inside reenter_dd (7%) hysteresis. The
drawdown signal tracks un-throttled equity so recovery is observable while flat; output
is the throttled series; no lookahead (each day uses prior-day kill-state). The small-
capital tail control - survive a crypto-deleveraging by standing down, not by paying for
a hedge sleeve. Pure + composable overlay on combine_book output. Test + mypy green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 23:16:17 +02:00
jgrusewski
e02900fad9 feat(surfer): leave-one-out marginal-Sharpe gate for the book allocator
The correct quality/decay layer the naive Sharpe floor couldn't be. A raw Sharpe
floor benches legitimate anticorrelated hedges (low standalone Sharpe but vol-reducing)
as readily as dead sleeves. marginal_gate (default False) instead benches a sleeve only
when REMOVING it raises the inverse-vol book's trailing per-period Sharpe — so it keeps
hedges (removing them lowers book Sharpe) and benches only dead, non-diversifying
sleeves (removing them raises it). Greedy leave-one-out, shrinks to >=1, pure on the
trailing window (no lookahead).

Verified: anticorrelated hedge pair stays fully invested (book vol ->0 via cancellation,
the case the Sharpe floor broke); a dragging dead sleeve is benched in its clearly-
negative windows. Acts on trailing-window evidence, so a marginally-negative sleeve
within estimation noise is kept (correct). Suite green, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 23:14:31 +02:00
jgrusewski
c39d78fd7b feat(surfer): cross-asset futures curve loader + CTA harness + opt-in allocator quality gate
Reusable infra from the diversifier research (the strategies themselves found no
deployable edge on our 22-market panel, but the construction is validated):

- dbn_local.load_curve: front + 2nd-nearby CONTINUOUS series + annualized carry
  (log(F1/F2)/gap_years) from parent-symbology outright expiries. Unlocks carry +
  basis-momentum without re-reading raw .dbn.
- cta_trend.py / cta_runner.py: literature-grounded managed-futures trend
  (vol-normalized risk-adj momentum -> tanh(x/0.89) response -> 1/3/12mo blend ->
  inverse-vol -> equal-risk-per-sector budget -> portfolio vol-target -> long/short).
  Construction validated (reproduces SG Trend +29% in 2022); premium absent for us
  (Sharpe ~0 over 2010-26 on 22 markets, ends mid-historic-drawdown).
- book_allocator: OPTIONAL edge-quality gate (min_sleeve_sharpe, default None=OFF) to
  bench dead/decaying sleeves so they can't be levered up by the vol-target. Off by
  default because a naive Sharpe floor also benches legitimate anticorrelated hedges;
  a correct quality/decay layer is future work. Suite green, mypy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 23:07:30 +02:00
jgrusewski
4f2f6024a7 feat(alloc): book-of-books allocator (date-aligned edges, inverse-vol+cap, fractional-Kelly, vol-target) + gauntlet
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:11:02 +02:00
jgrusewski
5917a11c79 feat(hunt): TSMOM trend harness (directional, vol-scaled, long/short) + gauntlet
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:49:46 +02:00
jgrusewski
63848e043e feat(hunt): crypto XS price-factor harness (reversal/lowvol/illiquidity) + gauntlet matrix
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:38:19 +02:00
jgrusewski
bad0c6accd docs: edge-discovery sprint plan (crypto XS factors + TS-trend + cross-asset trend, gauntlet-gated)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:33:10 +02:00
jgrusewski
e12819acdc feat(cockpit): mobile-friendly dashboard — fleet table reflows to cards, scroll-wrap dense tables, responsive SVG/header
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:54:20 +02:00
jgrusewski
31aba36b13 fix(xsfunding): guard live snapshot against decoupled-basis tickers (LIT-type artifacts)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 08:12:51 +02:00
jgrusewski
dc5b9b5111 fix(xsfunding): route xsfunding_nav through transient-error wrapper + retry price fetches (don't break nightly run)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 07:58:00 +02:00
jgrusewski
94da2c6a6b feat(xsfunding): register xsfunding paper track + Dagster asset in daily book
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 07:50:19 +02:00
jgrusewski
9e9fe2a13c feat(xsfunding): live-booking forward strategy (delta-neutral funding+basis, executable)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 07:45:45 +02:00
jgrusewski
0cf0e77ab4 feat(xsfunding): live per-coin snapshot (funding + perp + spot + qvol)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 07:41:59 +02:00
jgrusewski
e7c9946aac docs(xsfunding): paper-forward track implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 07:38:51 +02:00
jgrusewski
a54a59c57e fix(xsfunding): guard sp[nxt]>0 in basis runner + test basis_modeled report metadata
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:34:39 +02:00
jgrusewski
5fe24df253 feat(xsfunding): model spot-perp basis P&L in runner (true delta-neutral return; funding-only fallback)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:27:53 +02:00
jgrusewski
fce563a65d feat(xsfunding): basis-panel builder + build-basis-panel CLI + spot-panel npz persistence
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:22:46 +02:00
jgrusewski
7f0e91a45b feat(xsfunding): spot-history adapter + ticker-reuse guard clean_spot_leg (basis prep)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:18:14 +02:00
jgrusewski
178ac665c4 docs(xsfunding): spot-perp basis-modeling implementation plan
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 00:12:47 +02:00
jgrusewski
2347714cae docs(xsfunding): self-document funding-only + annualization caveats in report/CLI; book_return_xs note
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:54:17 +02:00
jgrusewski
75006af0ef fix(xsfunding): runner robust to panel gaps — use last-known qvol for cost (KeyError on real data)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:41:38 +02:00
jgrusewski
b5f065b887 feat(xsfunding): backtest-funding CLI — verdict matrix over crypto_pit panel
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:37:31 +02:00
jgrusewski
d231971cb8 feat(xsfunding): gauntlet verdict matrix (modes x floors, crypto 365d, cross-cell DSR n_trials)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:33:13 +02:00
jgrusewski
17da65c6bd fix(xsfunding): charge exit cost for dropped-out holdings; expose n_rebalances vs panel_days
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:29:11 +02:00
jgrusewski
0f115abbf1 feat(xsfunding): walk-forward runner — PIT universe + per-mode daily carry series + liquidity-scaled cost
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:19:56 +02:00
jgrusewski
a0c35eae71 fix(xsfunding): clamp quantile-cut to disjoint top/bottom; cache panel; gross-scale doc; isolating PIT test
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:16:14 +02:00
jgrusewski
250f425374 feat(xsfunding): construction weights (long_tilt/market_neutral/executable) + signed carry book-return
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:08:52 +02:00
jgrusewski
b0862836aa feat(xsfunding): PIT eligibility + cross-sectional funding score (robust_z of trailing funding)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:05:20 +02:00
jgrusewski
050f45d667 feat(xsfunding): crypto_pit npz panel adapter (survivorship-free, read-only)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 23:02:00 +02:00
jgrusewski
549a21f660 docs(xsfunding): cross-sectional funding-dispersion implementation plan (6 tasks → verdict matrix)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 22:58:52 +02:00
jgrusewski
31aa746369 docs(xsfunding): cross-sectional crypto funding-dispersion strategy design (spike PASSED — survivorship-free panel on disk)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 22:53:40 +02:00
jgrusewski
28934a214c feat: retire crossvenue forward track (falsified 3x — max-min artifact, no edge)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 20:56:50 +02:00
jgrusewski
7766071d06 fix(b3b-deploy): verdict Job pg egress via postgres podSelector (pod CIDR, not service CIDR)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:13:15 +02:00
jgrusewski
988743302d deploy(b3b): one-off Job to run the backtest + publish verdict to cockpit (pg egress netpol)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 19:04:39 +02:00
jgrusewski
72dd1e1e9f fix(b3b): None-safe backtest-verdict rendering in cockpit templates + detail-page verdict test
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:55:30 +02:00
jgrusewski
2c94c65953 feat(b3b): retire eqfactor_ls forward track (no edge per backtest); keep long/tilt + shared scores
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:48:41 +02:00
jgrusewski
82fad9c21e feat(b3b): surface backtest verdict (PASS/FAIL + Sharpe/DSR) in cockpit fleet view
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:44:17 +02:00
jgrusewski
b42177e853 feat(b3b): persist backtest verdict to cockpit (backtest_summary table + --persist-cockpit)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:39:24 +02:00
jgrusewski
b01da6865e fix(b3b): PIT path uses full trading calendar for hold days; CLI omits candidate_top_k under --pit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 10:16:27 +02:00
jgrusewski
feac27f98f feat(b3b): PIT-trailing universe selection — remove peak-liquidity lookahead (two-pass, memory-bounded)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 10:01:36 +02:00
jgrusewski
5029c4058b feat(b3b): delisting-return handling — book terminal return when held name's series terminates (fixes long-only inflation)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 09:42:49 +02:00