"""STRATO TREND MULTI-ASSET sui 52 alt Hyperliquid certificati (diversificazione del trend).

TP01 e' TSMOM vol-target long-flat su BTC+ETH (2 asset). Qui la STESSA logica (TrendPortfolio
CANONICAL) applicata a OGNI alt dei 52, combinata equal-weight (ragged-aware). Idea: un trend
piu' diversificato. Test onesto: e' correlato a TP01 (entrambi trend)? aggiunge al portafoglio
TP01+XS01 nel hold-out? Causale, netto fee.

    uv run python scripts/portfolio/trend_multiasset.py
"""
from __future__ import annotations
import sys, glob
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np, pandas as pd
from src.strategies.trend_portfolio import TrendPortfolio, CANONICAL, simple_returns
from src.portfolio.portfolio import to_daily, metrics, HOLDOUT, Sleeve, StrategyPortfolio
from src.portfolio.sleeves import tp01_sleeve, xsec_sleeve

RAW = PROJECT_ROOT / "data" / "raw"


def alt_trend_returns(min_assets=8):
    """Net returns per-asset (TSMOM CANONICAL long-flat vol-target) -> book equal-weight ragged."""
    eng = TrendPortfolio(**CANONICAL)
    series = {}
    for p in sorted(glob.glob(str(RAW / "hl_*_1d.parquet"))):
        sym = Path(p).stem.replace("hl_", "").replace("_1d", "").upper()
        d = pd.read_parquet(p)
        d = d.copy(); d["datetime"] = pd.to_datetime(d["timestamp"], unit="ms", utc=True)
        c = d["close"].values.astype(float)
        r = simple_returns(c); tgt = eng.target_series(d)
        held = np.zeros(len(tgt)); held[1:] = tgt[:-1]
        net = held * r - eng.fee_side * np.abs(np.diff(held, prepend=0.0)); net[0] = 0.0
        series[sym] = pd.Series(np.clip(net, -0.99, None), index=d["datetime"])
    M = pd.concat(series, axis=1, join="outer").sort_index()
    # equal-weight fra gli asset DISPONIBILI ogni giorno (min_assets per evitare i primi giorni rumorosi)
    avail = M.notna().sum(axis=1)
    book = M.mean(axis=1, skipna=True).where(avail >= min_assets)
    return book.dropna(), M


def ev(d, label):
    f = metrics(d); h = metrics(d[d.index >= HOLDOUT])
    yr = [float((1 + g).prod() - 1) for _, g in d.groupby(d.index.year)]
    pct = sum(v > 0 for v in yr) / len(yr) if yr else 0
    print(f"  {label:<28} FULL Sh {f['sharpe']:>5.2f} ret {f['ret']*100:>+6.0f}% DD {f['maxdd']*100:>4.0f}% | "
          f"HOLD Sh {h['sharpe']:>5.2f} | anni+ {pct*100:.0f}%")
    return f, h


def main():
    print("=" * 96)
    print("  STRATO TREND MULTI-ASSET (52 alt Hyperliquid, TSMOM CANONICAL long-flat vol-target)")
    print("=" * 96)
    book, M = alt_trend_returns()
    bd = to_daily(book)
    print(f"  universo {M.shape[1]} alt, book [{bd.index[0].date()} -> {bd.index[-1].date()}]\n")
    ev(bd, "TREND-52alt standalone")

    tp = tp01_sleeve().daily(); xs = xsec_sleeve().daily()
    def corr(a, b):
        J = pd.concat({"a": a, "b": b}, axis=1, join="inner").dropna()
        return float(J["a"].corr(J["b"])) if len(J) > 5 else float("nan")
    print(f"\n  correlazioni: TREND-52 vs TP01 {corr(bd, tp):+.2f} | vs XS01 {corr(bd, xs):+.2f}")

    # contributo: portafoglio attuale (TP01+XS01) vs +TREND-52, finestra comune
    print("\n  CONTRIBUTO al portafoglio (finestra comune):")
    base = StrategyPortfolio([tp01_sleeve(0.70), xsec_sleeve(0.30)]).backtest()
    J = pd.concat({"tp": tp, "xs": xs, "tr": bd}, axis=1, join="inner").dropna()
    print(f"    [comune {J.index[0].date()} -> {J.index[-1].date()}]")
    # baseline sulla finestra comune (TP01 0.7 + XS 0.3 rinormalizzato)
    base_c = 0.7 * J["tp"] + 0.3 * J["xs"]
    bf, bh = metrics(base_c), metrics(base_c[base_c.index >= HOLDOUT])
    print(f"    TP01 70 + XS 30 (attuale)     FULL Sh {bf['sharpe']:.2f} DD {bf['maxdd']*100:.0f}% | HOLD Sh {bh['sharpe']:.2f}")
    for wtr in (0.2, 0.3):
        wt, wx = 0.7 * (1 - wtr), 0.3 * (1 - wtr)
        comb = wt * J["tp"] + wx * J["xs"] + wtr * J["tr"]
        cf, ch = metrics(comb), metrics(comb[comb.index >= HOLDOUT])
        print(f"    +TREND-52 w{wtr:.0%}              FULL Sh {cf['sharpe']:.2f} ({cf['sharpe']-bf['sharpe']:+.2f}) DD {cf['maxdd']*100:.0f}% | HOLD Sh {ch['sharpe']:.2f} ({ch['sharpe']-bh['sharpe']:+.2f})")

    print("\n  -> aggiungere se: scorrelato a TP01/XS01 e migliora FULL E HOLD. Se molto correlato a")
    print("  TP01 (entrambi trend) e contributo marginale, e' ridondante -> non si aggiunge.")


if __name__ == "__main__":
    main()
