14522262e6
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
124 lines
4.9 KiB
Python
124 lines
4.9 KiB
Python
"""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()
|