research(sweep): 5 thread paralleli — 0 nuovi sleeve, STATARB-RESID LEAD ortogonale+eseguibile
Ricerca onesta su aree inesplorate (harness altlib+xsec_v2_nonmom, tutti i gate incl. study_family_honest anti-selection-on-holdout). Branch main, nessun impatto live, test 143/143. 1 XSEC low-risk cousins (MAX/idio-vol/Amihud) -> 1 LEAD (IVOL), STAT-MODE, DSR 0.37<0.95 2 XSEC momentum-structure vs XS01 -> tutto REDUNDANT (sostituire XS01 distrugge hold) 3 Meta-allocazione dinamica (4 sleeve) -> pesi fissi vincono (gia quasi risk-parity) 4 Segnali ortogonali ETH/BTC (2 gambe) -> STATARB-RESID + DVOLSPREAD LEAD 5 1-gamba a segnale (MACD/RSI/Supertrend/...) -> 0/12 earns_slot (trend=TP01, MR morta, hedge) LEAD principale STATARB-RESID (mean-rev residuo ETH-b*BTC, OLS rolling, 2 gambe): primo stream INSIEME ortogonale (corr->book 0.027, beta-mkt 0.013) ED eseguibile a $600 (haircut ~0, NON STAT-MODE) -> cadono i 2 muri di XS01/opzioni. Resta solo il muro dell'edge (Sharpe 0.84, DSR 0.929 same-sign <0.95). Causalita+fee verificate dal coordinatore. Forward-monitor, non sleeve. Soffitto direzionale ~1.3 riconfermato. Diario 2026-06-29-strategy-search-5threads.md, CLAUDE.md agg. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
"""Test del filone C v3: cross-sectional 'low-risk cousins' (MAX / IVOL / AMIHUD) su Hyperliquid
|
||||
(scripts/research/xsec_v3_lowrisk). Verifica i GATE strutturali, non i numeri esatti (storia corta):
|
||||
- lo script importa ed esegue (catalogo meccanismi costruibile, una cella di engine gira);
|
||||
- i meccanismi sono CAUSALI (prefix-consistency bit-a-bit), incluso AMIHUD che richiede il
|
||||
riallineamento del volume sul prefisso (path piu' delicato);
|
||||
- la selezione 'robust_candidate' RIFIUTA il holdout-fitting (config negativa in-sample con HOLD
|
||||
alto) come prescritto dallo scorer indurito del progetto;
|
||||
- IVOL sui 19 major ha edge in-sample positivo (il LEAD principale).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
sys.path.insert(0, str(PROJECT_ROOT / "scripts" / "research"))
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
import importlib.util
|
||||
_spec = importlib.util.spec_from_file_location(
|
||||
"xsec_v3_lowrisk", PROJECT_ROOT / "scripts" / "research" / "xsec_v3_lowrisk.py")
|
||||
xv3 = importlib.util.module_from_spec(_spec)
|
||||
_spec.loader.exec_module(xv3)
|
||||
|
||||
xv = xv3.xv # harness collaudato riusato dal modulo v3
|
||||
from src.portfolio.portfolio import to_daily, metrics
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def majors():
|
||||
return xv.load_matrix(xv.XS_UNIVERSE)
|
||||
|
||||
|
||||
def test_imports_and_builds_mechanisms(majors):
|
||||
"""Lo script importa e il catalogo dei 3 'low-risk cousins' (+ entrambi i segni AMIHUD) e' costruibile."""
|
||||
_, VOL = majors
|
||||
mechs = xv3.build_mechanisms(VOL)
|
||||
assert set(mechs) == {"MAX", "IVOL", "AMIHUD_ILLIQ", "AMIHUD_LIQ"}
|
||||
for mn, (_builder, cfgs) in mechs.items():
|
||||
assert len(cfgs) == 12 # B{20,30,60} x H{5,10} x k{5,8}
|
||||
|
||||
|
||||
def test_engine_executes_a_cell(majors):
|
||||
"""Esegue una cella dell'engine (IVOL B30 H5 k8 sui 19 major): serie giornaliera finita, std>0,
|
||||
turnover>0 e Sharpe FULL positivo robusto (il LEAD documentato)."""
|
||||
PX, VOL = majors
|
||||
score_at, warm = xv3.make_ivol(PX, 30)
|
||||
s, turn = xv.xs_engine(PX, VOL, score_at, H=5, k=8, warmup=warm)
|
||||
d = to_daily(s)
|
||||
assert np.isfinite(d.values).all() and d.std() > 0
|
||||
assert turn > 0
|
||||
assert metrics(d)["sharpe"] > 0.5 # IVOL 19-major = LEAD (edge in-sample+OOS)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mech,cfg", [
|
||||
("MAX", dict(B=60, H=5, k=5)),
|
||||
("IVOL", dict(B=30, H=5, k=8)),
|
||||
("AMIHUD_ILLIQ", dict(B=30, H=10, k=5)), # path col riallineamento del volume
|
||||
])
|
||||
def test_mechanism_is_causal(majors, mech, cfg):
|
||||
"""Nessun look-ahead: ricostruito su un prefisso, la coda combacia bit-a-bit con la run completa.
|
||||
Per AMIHUD verifica anche che il volume sia riallineato al prefisso (non al full-sample)."""
|
||||
PX, VOL = majors
|
||||
builder, _ = xv3.build_mechanisms(VOL)[mech]
|
||||
res = xv.causality_prefix_check(PX, VOL, builder, cfg)
|
||||
assert res["ok"], f"{mech} look-ahead: max_tail_diff={res['max_tail_diff']}"
|
||||
assert res["max_tail_diff"] == 0.0
|
||||
|
||||
|
||||
def test_robust_candidate_rejects_holdout_fit():
|
||||
"""La selezione GIUDICATA scarta il holdout-fitting: una config NEGATIVA in-sample con HOLD alto
|
||||
non e' eleggibile; serve in-sample>=0.5 E HOLD>0. Se nessuna ha edge in-sample -> None."""
|
||||
rows = [
|
||||
dict(insample=-1.2, hold=1.0, full=0.1), # holdout-fit -> escluso
|
||||
dict(insample=0.9, hold=0.8, full=0.95), # edge in-sample + OOS -> eleggibile
|
||||
dict(insample=0.6, hold=-0.2, full=0.3), # HOLD<0 -> escluso
|
||||
]
|
||||
c = xv3.robust_candidate(rows)
|
||||
assert c is not None and c["insample"] == 0.9
|
||||
assert xv3.robust_candidate([dict(insample=0.1, hold=2.0, full=0.0)]) is None
|
||||
Reference in New Issue
Block a user