"""VERIFICA su dati REALI — DIP01 e i 6 pairs hanno edge su prezzi veri?

Le 6 fade sono morte su mainnet/Binance (edge = artefatto-print testnet). Restano i
candidati piu' probabili a sopravvivere: i pairs (market-neutral sul log-ratio -> i
print di singolo asset si elidono in parte) e DIP01. Test: monkeypatch di load_data /
get_df -> serie 100% Binance spot (provato ~ mainnet: disc <0.13%), STESSO engine
canonico (pairs_sim / dip_market_gated). Cache in data/raw/_real_*.parquet (NON tocca
i canonici).
"""
from __future__ import annotations
import sys
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, ccxt

SYM = {"BTC": "BTC/USDT", "ETH": "ETH/USDT", "LTC": "LTC/USDT", "ADA": "ADA/USDT", "SOL": "SOL/USDT"}
START, END = "2020-06-01", "2026-05-26"
YEARS = [2021, 2022, 2023, 2024, 2025, 2026]
_EX = None
_CACHE: dict[tuple, pd.DataFrame] = {}


def _ex():
    global _EX
    if _EX is None:
        _EX = ccxt.binance({"enableRateLimit": True})
    return _EX


def fetch(asset, tf):
    key = (asset, tf)
    if key in _CACHE:
        return _CACHE[key]
    cache = PROJECT_ROOT / "data" / "raw" / f"_real_{asset.lower()}_{tf}.parquet"
    if cache.exists():
        df = pd.read_parquet(cache); _CACHE[key] = df; return df
    tf_ms = {"15m": 15, "1h": 60}[tf] * 60 * 1000
    start_ms = int(pd.Timestamp(START, tz="UTC").timestamp() * 1000)
    end_ms = int(pd.Timestamp(END, tz="UTC").timestamp() * 1000)
    rows, since = [], start_ms
    while since <= end_ms:
        r = _ex().fetch_ohlcv(SYM[asset], tf, since=since, limit=1000)
        if not r:
            break
        rows += r
        nxt = int(r[-1][0]) + tf_ms
        if nxt <= since:
            break
        since = nxt
    df = pd.DataFrame(rows, columns=["timestamp", "open", "high", "low", "close", "volume"])
    df = df.drop_duplicates("timestamp").sort_values("timestamp").reset_index(drop=True)
    df = df[df["timestamp"] <= end_ms].reset_index(drop=True)
    df.to_parquet(cache, index=False); _CACHE[key] = df
    return df


# ---- monkeypatch dei loader dei due engine canonici ----
def _patched_load_data(asset, tf="1h"):
    return fetch(asset, tf)


def _patched_get_df(asset, tf="1h"):
    return fetch(asset, tf)


def daily_from_eq(eq_ts, eq_v):
    idx = pd.date_range("2021-01-01", END, freq="1D", tz="UTC")
    s = pd.Series(eq_v, index=pd.to_datetime(eq_ts, utc=True)).resample("1D").last().reindex(idx).ffill().bfill()
    return s / s.iloc[0]


def metrics_from_daily(s, split_date="2024-10-12"):
    r = s.pct_change().fillna(0.0)
    def m(rr):
        eq = (1 + rr).cumprod(); peak = eq.cummax()
        dd = float(((peak - eq) / peak).max() * 100)
        sh = float(rr.mean() / rr.std() * np.sqrt(365)) if rr.std() > 0 else 0.0
        return (eq.iloc[-1] - 1) * 100, dd, sh
    sd = pd.Timestamp(split_date, tz="UTC")
    fF, ddF, shF = m(r)
    ro = r[r.index >= sd]
    fO, ddO, shO = m(ro)
    yr = {int(y): float(((1 + r[r.index.year == y]).prod() - 1) * 100) for y in YEARS}
    return yr, fF, ddF, shF, fO, ddO, shO


def main():
    print("Fetch Binance spot (1h: BTC/ETH/LTC/ADA/SOL ; 15m: BTC/ETH)...\n")
    for a in SYM:
        fetch(a, "1h")
    for a in ("BTC", "ETH"):
        fetch(a, "15m")

    import scripts.analysis.pairs_research as PR
    import scripts.analysis.honest_improve2 as HI
    PR.load_data = _patched_load_data
    HI.get_df = _patched_get_df
    from scripts.analysis.pairs_research import pairs_sim, pairs_sim_flat, OOS_FRAC
    from scripts.strategies.PR01_pairs_reversion import PAIRS

    # ---------- DIP01 ----------
    print("=" * 96)
    print("  DIP01 (BTC 1h dip-buy) su Binance spot REALE | RET% per anno + FULL/OOS (leva 3x)")
    print("=" * 96)
    d = HI.dip_market_gated("BTC", market_n=0, return_equity=True)
    s = daily_from_eq(d["eq_ts"], d["eq_v"])
    yr, fF, ddF, shF, fO, ddO, shO = metrics_from_daily(s)
    print(f"  {'':<10s}" + "".join(f"{y:>9d}" for y in YEARS) + "   |   FULL%  DD%  Shrp |  OOS%  Shrp")
    print(f"  {'DIP01_BTC':<10s}" + "".join(f"{yr[y]:>+9.0f}" for y in YEARS) +
          f"   | {fF:>+7.0f}{ddF:>5.0f}{shF:>6.2f} | {fO:>+6.0f}{shO:>6.2f}")

    # ---------- PAIRS (5 univ + BLEND 15m) ----------
    print("\n" + "=" * 96)
    print("  PAIRS PR01 su Binance spot REALE | fee 0.20% RT/coppia, leva 3x | (canonico CLAUDE.md fra parentesi)")
    print("=" * 96)
    print(f"  {'coppia':<12s}{'trd':>6s}{'win%':>6s}{'CAGR%':>7s}{'DD%':>6s}{'Shrp':>6s}{'oDD%':>6s}{'anni+':>7s}")
    canon = {"ETH/BTC": 4.36, "LTC/ETH": 3.08, "ADA/ETH": 2.69, "BTC/LTC": 2.36, "ETH/SOL": 1.96}
    for a, b, p in PAIRS:
        f = pairs_sim(a, b, **p)
        o = pairs_sim(a, b, **p, split_frac=1 - OOS_FRAC)
        yrs = f["yearly"]; pos_y = sum(1 for v in yrs.values() if v > 0)
        name = f"{a}/{b}"
        print(f"  {name:<12s}{f['trades']:>6d}{f['win']:>6.1f}{f['cagr']:>7.0f}{f['dd']:>6.0f}"
              f"{f['sharpe']:>6.2f}{o['dd']:>6.0f}{pos_y:>5d}/{len(yrs)}   (canon Sh {canon.get(name,'?')})")
    # BLEND ETH/BTC 15m (mezza size, flat-skip) come nel portafoglio
    r15 = pairs_sim_flat("ETH", "BTC", tf="15m", n=66, z_in=1.674, z_exit=1.0,
                         max_bars=35, flat_skip=True, pos=0.075)
    o15 = pairs_sim_flat("ETH", "BTC", tf="15m", n=66, z_in=1.674, z_exit=1.0,
                         max_bars=35, flat_skip=True, pos=0.075, split_frac=1 - OOS_FRAC)
    yrs = r15["yearly"]; pos_y = sum(1 for v in yrs.values() if v > 0)
    print(f"  {'ETH/BTC 15m':<12s}{r15['trades']:>6d}{r15['win']:>6.1f}{r15['cagr']:>7.0f}{r15['dd']:>6.0f}"
          f"{r15['sharpe']:>6.2f}{o15['dd']:>6.0f}{pos_y:>5d}/{len(yrs)}   (BLEND mezza size)")


if __name__ == "__main__":
    main()
