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) <noreply@anthropic.com>
This commit is contained in:
@@ -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.)
|
||||||
@@ -18,12 +18,14 @@ import numpy as np, pandas as pd, requests, ccxt
|
|||||||
|
|
||||||
RAW = PROJECT_ROOT / "data" / "raw"
|
RAW = PROJECT_ROOT / "data" / "raw"
|
||||||
START = "2024-01-01"; END = "2026-06-17"
|
START = "2024-01-01"; END = "2026-06-17"
|
||||||
# set liquido (volume recente alto + storia 2024); MATIC morto, HYPE 2025-only esclusi qui
|
# UNIVERSO ESTESO: alt liquidi noti su Hyperliquid (mappa Binance auto = SYM/USDT). Il gate di
|
||||||
SYMS = ["BTC","ETH","SOL","BNB","XRP","DOGE","AVAX","LINK","LTC","ADA","ARB","OP","SUI","APT","INJ","TIA","SEI","NEAR","AAVE"]
|
# certificazione (cross-venue + liquidita' + flat) scarta i non-conformi. k-prefissi esclusi
|
||||||
BINANCE = {"BTC":"BTC/USDT","ETH":"ETH/USDT","SOL":"SOL/USDT","BNB":"BNB/USDT","XRP":"XRP/USDT",
|
# (scaling 1000x complica il cross-venue). MATIC morto escluso.
|
||||||
"DOGE":"DOGE/USDT","AVAX":"AVAX/USDT","LINK":"LINK/USDT","LTC":"LTC/USDT","ADA":"ADA/USDT",
|
SYMS = ["BTC","ETH","SOL","BNB","XRP","DOGE","AVAX","LINK","LTC","ADA","ARB","OP","SUI","APT",
|
||||||
"ARB":"ARB/USDT","OP":"OP/USDT","SUI":"SUI/USDT","APT":"APT/USDT","INJ":"INJ/USDT",
|
"INJ","TIA","SEI","NEAR","AAVE","ATOM","DYDX","APE","CRV","LDO","STX","GMX","SNX","BCH",
|
||||||
"TIA":"TIA/USDT","SEI":"SEI/USDT","NEAR":"NEAR/USDT","AAVE":"AAVE/USDT"}
|
"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():
|
def _h():
|
||||||
@@ -78,7 +80,10 @@ def main():
|
|||||||
bps=(m["a"]-m["b"]).abs()/m["b"]*1e4
|
bps=(m["a"]-m["b"]).abs()/m["b"]*1e4
|
||||||
med=bps.median(); g1=(bps>100).mean()*100
|
med=bps.median(); g1=(bps>100).mean()*100
|
||||||
else: med=g1=float("nan")
|
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"
|
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}")
|
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:
|
if clean:
|
||||||
|
|||||||
@@ -54,16 +54,25 @@ import glob as _glob
|
|||||||
from pathlib import Path as _Path
|
from pathlib import Path as _Path
|
||||||
XS_CFG = dict(L=30, H=10, k=5, mode="mom", target_vol=0.20)
|
XS_CFG = dict(L=30, H=10, k=5, mode="mom", target_vol=0.20)
|
||||||
_HL_DIR = _Path(__file__).resolve().parents[2] / "data" / "raw"
|
_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:
|
def _xsec_returns() -> pd.Series:
|
||||||
cols = {}
|
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)
|
d = pd.read_parquet(p)
|
||||||
cols[_Path(p).stem] = pd.Series(d["close"].values.astype(float),
|
cols[sym] = pd.Series(d["close"].values.astype(float),
|
||||||
index=pd.to_datetime(d["timestamp"], unit="ms", utc=True))
|
index=pd.to_datetime(d["timestamp"], unit="ms", utc=True))
|
||||||
if not cols:
|
if len(cols) < 10:
|
||||||
raise FileNotFoundError("universo Hyperliquid assente: gira scripts/analysis/fetch_hyperliquid.py")
|
raise FileNotFoundError("universo Hyperliquid XS01 incompleto: gira scripts/analysis/fetch_hyperliquid.py")
|
||||||
C = pd.concat(cols, axis=1, join="inner").sort_index().dropna()
|
C = pd.concat(cols, axis=1, join="inner").sort_index().dropna()
|
||||||
px = C.values; n, A = px.shape
|
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"]
|
L, H, k, mode, tv = XS_CFG["L"], XS_CFG["H"], XS_CFG["k"], XS_CFG["mode"], XS_CFG["target_vol"]
|
||||||
|
|||||||
Reference in New Issue
Block a user