"""VERIFICA DEFINITIVA — la fade ha edge sul perp Deribit MAINNET REALE? Testnet feed = print fantasma (edge finto). Binance spot = fade morta. Resta da escludere che la fade viva sulla microstruttura del perp Deribit MAINNET reale (dove ESEGUE davvero). Scarico lo storico 15m reale (BTC/ETH-PERPETUAL mainnet via Cerbero v2, token .env.mainnet) e giro lo STESSO engine. Cache in data/raw/_mainnet_*.parquet (NON tocca i file canonici). """ from __future__ import annotations import sys from pathlib import Path from datetime import datetime, timedelta PROJECT_ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(PROJECT_ROOT)) import requests, numpy as np, pandas as pd from src.live.cerbero_client import TESTNET_TOKEN from scripts.analysis.risk_management import build_trades, strats_for URL = "https://cerbero-mcp.tielogic.xyz/mcp/tools/get_historical" START, END = "2020-06-01", "2026-05-26" YEARS = [2021, 2022, 2023, 2024, 2025, 2026] INSTR = {"BTC": "BTC-PERPETUAL", "ETH": "ETH-PERPETUAL"} def _token(): env = {} for ln in (PROJECT_ROOT / ".env.mainnet").read_text().splitlines(): ln = ln.strip() if ln and not ln.startswith("#") and "=" in ln: k, v = ln.split("=", 1); env[k] = v.strip() assert env["CERBERO_TOKEN"] != TESTNET_TOKEN, "token e' TESTNET, non mainnet!" return env["CERBERO_TOKEN"], env.get("CERBERO_BOT_TAG", "pythagoras-verify") def fetch_mainnet(asset, tf="15m"): cache = PROJECT_ROOT / "data" / "raw" / f"_mainnet_{asset.lower()}_{tf}.parquet" if cache.exists(): return pd.read_parquet(cache) tok, tag = _token() H = {"Authorization": f"Bearer {tok}", "X-Bot-Tag": tag, "Content-Type": "application/json"} cur, end = datetime.fromisoformat(START), datetime.fromisoformat(END) step = timedelta(days=30) rows = [] while cur < end: ce = min(cur + step, end) for attempt in range(3): try: r = requests.post(URL, headers=H, json={ "exchange": "deribit", "instrument": INSTR[asset], "interval": tf, "start_date": cur.strftime("%Y-%m-%d"), "end_date": ce.strftime("%Y-%m-%d")}, timeout=40) r.raise_for_status() rows += r.json().get("candles", []) break except Exception as e: if attempt == 2: print(f" SKIP {cur.date()}->{ce.date()}: {str(e)[:60]}") cur = ce df = pd.DataFrame(rows) if len(df) == 0: return df df["timestamp"] = df["timestamp"].astype("int64") df = df.drop_duplicates("timestamp").sort_values("timestamp").reset_index(drop=True) df.to_parquet(cache, index=False) return df def yearly(ts, trades, pos=0.15): by = {y: [] for y in YEARS} for i, j, r in trades: y = ts.iloc[i].year if y in by: by[y].append(r) out = {} for y in YEARS: cap = 1000.0 for r in by[y]: cap = max(cap + cap * pos * r, 10.0) out[y] = (cap / 1000 - 1) * 100 return out def full_oos(ts, trades, pos=0.15, split_date="2024-10-12"): sd = pd.Timestamp(split_date, tz="UTC") def comp(sub): cap = 1000.0; rets = [] for i, j, r in sub: cap = max(cap + cap * pos * r, 10.0); rets.append(r * pos) return cap, rets capF, rF = comp(trades) capO, rO = comp([(i, j, r) for i, j, r in trades if ts.iloc[i] >= sd]) shF = float(np.mean(rF)/np.std(rF)*np.sqrt(len(rF))) if len(rF) > 1 and np.std(rF) > 0 else 0.0 shO = float(np.mean(rO)/np.std(rO)*np.sqrt(len(rO))) if len(rO) > 1 and np.std(rO) > 0 else 0.0 return (capF/1000-1)*100, shF, (capO/1000-1)*100, shO def main(): print(f"Fetch Deribit MAINNET 15m REALE ({START}->{END})...\n") data = {} for a in ("BTC", "ETH"): df = fetch_mainnet(a) ts = pd.to_datetime(df["timestamp"], unit="ms", utc=True) print(f" {INSTR[a]}: {len(df)} candele {ts.min()} -> {ts.max()} " f"(anni: {sorted(ts.dt.year.unique().tolist())})") data[a] = df print("\n" + "=" * 94) print(" FADE su perp Deribit MAINNET REALE 15m | RET% per anno (pos 0.15, leva 3x, trend 3.0)") print("=" * 94) print(f" {'sleeve':<12s}" + "".join(f"{y:>9d}" for y in YEARS) + " | FULL% Shrp | OOS% Shrp") print(" " + "-" * 90) for asset in ("BTC", "ETH"): df = data[asset] ts = pd.to_datetime(df["timestamp"], unit="ms", utc=True) for code in ("MR01", "MR02", "MR07"): fn, params = strats_for(asset)[code] trades = build_trades(fn(df, **params), df, trend_max=3.0) trades = [(i, j, r) for i, j, r in trades if ts.iloc[i].year >= 2021] yr = yearly(ts, trades) fF, shF, fO, shO = full_oos(ts, trades) print(f" {code+'_'+asset:<12s}" + "".join(f"{yr[y]:>+9.0f}" for y in YEARS) + f" | {fF:>+8.0f} {shF:>5.2f} | {fO:>+6.0f} {shO:>5.2f}") if __name__ == "__main__": main()