From 8426d05f1227bad21fc108be906961fd3489dba6 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Fri, 19 Jun 2026 21:00:00 +0000 Subject: [PATCH] research: espandere universo XS01 a 52 asset DILUISCE (negativo) -> XS01 blindato sui 19 major Esteso fetch_hyperliquid a 52 alt certificati (cross-venue vs Binance, flat 0%, 2024+; +gate delistato per MKR/FXS). Ma il cross-sectional momentum sui 52 e' NEGATIVO (FULL -0.1..-0.6, k grande non aiuta) vs +0.67/OOS0.91 sui 19 major (stessa finestra): i ~33 small-cap (WIF/JUP/ORDI/PYTH/TAO..) sono idiosincratici/mean-reverting e rovesciano il momentum relativo. "Piu' asset = piu' robusto" e' FALSO per l'XS momentum: la breadth utile e' quella dei major liquidi. Fix: lo sleeve _xsec_returns usa XS_UNIVERSE esplicito (19 major), non glob-all (aggiungere parquet certificati non lo rompe piu'). I 52 parquet restano su disco per ricerca futura, non per XS01. Portafoglio ripristinato e invariato: TP01 70% + XS01 30%, FULL Sh 1.41 / HOLD 1.15. 12 test ok. Diario 2026-06-19-xsec-universe-expansion.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-06-19-xsec-universe-expansion.md | 39 +++++++++++++++++++ scripts/analysis/fetch_hyperliquid.py | 19 +++++---- src/portfolio/sleeves.py | 19 ++++++--- 3 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 docs/diary/2026-06-19-xsec-universe-expansion.md diff --git a/docs/diary/2026-06-19-xsec-universe-expansion.md b/docs/diary/2026-06-19-xsec-universe-expansion.md new file mode 100644 index 0000000..eeda0f6 --- /dev/null +++ b/docs/diary/2026-06-19-xsec-universe-expansion.md @@ -0,0 +1,39 @@ +# 2026-06-19 — Espandere l'universo XS01: PIÙ asset DILUISCONO (i 19 major sono il sweet spot) + +Richiesta: aggiungere altri asset Hyperliquid certificati per rafforzare XS01 (cross-sectional +momentum). Fatto il lavoro, esito ONESTO: **non rafforza — diluisce.** + +## Cosa ho fatto +- Esteso `fetch_hyperliquid.py` a ~54 candidati alt maggiori (mappa Binance auto SYM/USDT, k-prefissi + esclusi). **52 certificati** (cross-venue 4-11 bps vs Binance, flat 0%, storia 2024+): aggiunti + ATOM DYDX APE CRV LDO STX GMX SNX BCH COMP WLD UNI TRX FIL RUNE ENA ORDI JUP WIF PYTH FET AR ETC + ALGO GALA SAND AXS DOT BLUR JTO PENDLE ONDO TAO. Esclusi MKR (delistato HL 2025-09) e FXS + (migrazione Frax 2026-01) via nuovo gate "ultima barra recente". + +## Il finding: il cross-section dei 52 è NEGATIVO; i 19 major sono positivi +Stessa finestra (2024-04 → 2026-06, 807g), mom L*/H10: + +| Universo | k | FULL Sharpe (L30/L60/L90) | +|---|---|---| +| **52 asset** | 5 | −0.13 / −0.21 / −0.35 | +| **52 asset** | 8-12 | tutti negativi (k grande non aiuta) | +| **19 major** | 5 | +0.30 / +0.36 / **+0.67** (OOS 0.91) | + +I ~33 small/new-cap aggiunti (WIF, JUP, ORDI, PYTH, TAO, GALA, AR, BLUR…) sono idiosincratici/ +mean-reverting: il loro rumore **rovescia** il momentum relativo. Cross-sectional momentum su crypto +funziona fra i MAJOR liquidi, non sul long tail. Allargare l'universo NON è gratis. + +## Azione +- **XS01 resta sui 19 major** (sweet spot già validato: plateau/fee/subset). Lo sleeve + `_xsec_returns` ora usa una **lista esplicita `XS_UNIVERSE` (19)**, non più glob-all (così + aggiungere parquet certificati non lo cambia/rompe — avevo inavvertitamente fatto vedere allo + sleeve 52 asset = negativo). +- I 52 parquet certificati restano su disco: dato valido per ricerca futura (uno strato diverso — + es. trend-following multi-asset, o un XS ristretto ai top-liquidità — potrebbe usarli), ma NON XS01. +- Portafoglio invariato e ripristinato: **TP01 70% + XS01 30%, FULL Sh 1.41 / HOLD 1.15.** + +## Lezione +"Più asset = più robusto" è FALSO per il cross-sectional momentum: il long tail di alt piccoli +diluisce/inverte l'edge. La breadth utile è quella dei major liquidi (corr-strutturata), non il +numero grezzo. Per rafforzare XS01 servirebbe semmai una selezione per LIQUIDITÀ/qualità, non più +nomi. (Coerente con la disciplina: nessuna espansione senza che migliori il gauntlet.) diff --git a/scripts/analysis/fetch_hyperliquid.py b/scripts/analysis/fetch_hyperliquid.py index 9ce0753..a568c72 100644 --- a/scripts/analysis/fetch_hyperliquid.py +++ b/scripts/analysis/fetch_hyperliquid.py @@ -18,12 +18,14 @@ import numpy as np, pandas as pd, requests, ccxt RAW = PROJECT_ROOT / "data" / "raw" START = "2024-01-01"; END = "2026-06-17" -# set liquido (volume recente alto + storia 2024); MATIC morto, HYPE 2025-only esclusi qui -SYMS = ["BTC","ETH","SOL","BNB","XRP","DOGE","AVAX","LINK","LTC","ADA","ARB","OP","SUI","APT","INJ","TIA","SEI","NEAR","AAVE"] -BINANCE = {"BTC":"BTC/USDT","ETH":"ETH/USDT","SOL":"SOL/USDT","BNB":"BNB/USDT","XRP":"XRP/USDT", - "DOGE":"DOGE/USDT","AVAX":"AVAX/USDT","LINK":"LINK/USDT","LTC":"LTC/USDT","ADA":"ADA/USDT", - "ARB":"ARB/USDT","OP":"OP/USDT","SUI":"SUI/USDT","APT":"APT/USDT","INJ":"INJ/USDT", - "TIA":"TIA/USDT","SEI":"SEI/USDT","NEAR":"NEAR/USDT","AAVE":"AAVE/USDT"} +# UNIVERSO ESTESO: alt liquidi noti su Hyperliquid (mappa Binance auto = SYM/USDT). Il gate di +# certificazione (cross-venue + liquidita' + flat) scarta i non-conformi. k-prefissi esclusi +# (scaling 1000x complica il cross-venue). MATIC morto escluso. +SYMS = ["BTC","ETH","SOL","BNB","XRP","DOGE","AVAX","LINK","LTC","ADA","ARB","OP","SUI","APT", + "INJ","TIA","SEI","NEAR","AAVE","ATOM","DYDX","APE","CRV","LDO","STX","GMX","SNX","BCH", + "COMP","MKR","WLD","UNI","TRX","FIL","RUNE","ENA","ORDI","JUP","WIF","PYTH","FET","AR", + "ETC","ALGO","GALA","SAND","AXS","DOT","FXS","BLUR","JTO","PENDLE","ONDO","TAO"] +BINANCE = {s: f"{s}/USDT" for s in SYMS} def _h(): @@ -78,7 +80,10 @@ def main(): bps=(m["a"]-m["b"]).abs()/m["b"]*1e4 med=bps.median(); g1=(bps>100).mean()*100 else: med=g1=float("nan") - clean = (not np.isnan(med)) and med<60 and g1<3 and flat<5 + # gate "delistato/migrato": l'ultima barra dev'essere recente (entro ~21g da END), + # altrimenti l'asset tronca l'universo cross-sectional (es. MKR fermo a 2025-09, FXS 2026-01). + recent = (pd.Timestamp(END, tz="UTC") - ts.iloc[-1]) <= pd.Timedelta("21D") + clean = (not np.isnan(med)) and med<60 and g1<3 and flat<5 and recent v = "PULITO" if clean else "scarta" print(f" {s:<6}{len(df):>7}{str(ts.iloc[0].date()):>12}{flat:>6.1f}%{med:>9.1f}{g1:>6.1f}%{v:>12}") if clean: diff --git a/src/portfolio/sleeves.py b/src/portfolio/sleeves.py index 13fc183..b633cf2 100644 --- a/src/portfolio/sleeves.py +++ b/src/portfolio/sleeves.py @@ -54,16 +54,25 @@ import glob as _glob from pathlib import Path as _Path XS_CFG = dict(L=30, H=10, k=5, mode="mom", target_vol=0.20) _HL_DIR = _Path(__file__).resolve().parents[2] / "data" / "raw" +# UNIVERSO ESPLICITO = 19 ALT LIQUIDI MAJOR. NB (2026-06-19): allargare a 52 asset (incluso +# small-cap WIF/JUP/ORDI/PYTH/TAO...) DILUISCE l'edge -> momentum cross-section NEGATIVO sui 52. +# I major sono il sweet spot. NON usare glob-all (i parquet extra certificati servono ad altra +# ricerca, non a XS01). Vedi diario 2026-06-19-xsec-universe-expansion.md. +XS_UNIVERSE = ["BTC", "ETH", "SOL", "BNB", "XRP", "DOGE", "AVAX", "LINK", "LTC", "ADA", + "ARB", "OP", "SUI", "APT", "INJ", "TIA", "SEI", "NEAR", "AAVE"] def _xsec_returns() -> pd.Series: cols = {} - for p in sorted(_glob.glob(str(_HL_DIR / "hl_*_1d.parquet"))): + for sym in XS_UNIVERSE: + p = _HL_DIR / f"hl_{sym.lower()}_1d.parquet" + if not p.exists(): + continue d = pd.read_parquet(p) - cols[_Path(p).stem] = pd.Series(d["close"].values.astype(float), - index=pd.to_datetime(d["timestamp"], unit="ms", utc=True)) - if not cols: - raise FileNotFoundError("universo Hyperliquid assente: gira scripts/analysis/fetch_hyperliquid.py") + cols[sym] = pd.Series(d["close"].values.astype(float), + index=pd.to_datetime(d["timestamp"], unit="ms", utc=True)) + if len(cols) < 10: + raise FileNotFoundError("universo Hyperliquid XS01 incompleto: gira scripts/analysis/fetch_hyperliquid.py") C = pd.concat(cols, axis=1, join="inner").sort_index().dropna() px = C.values; n, A = px.shape L, H, k, mode, tv = XS_CFG["L"], XS_CFG["H"], XS_CFG["k"], XS_CFG["mode"], XS_CFG["target_vol"]