"""PIANO STORICO DERIBIT — quanta storia copre davvero il venue dove ESEGUIAMO?

Obiettivo: scegliere la fonte migliore per ricostruire lo storico di backtest, dato
che si esegue su Deribit. Principio (gia' misurato in multi_source_check): l'ancora
giusta e' il VENUE DI ESECUZIONE, non Binance/USDT. Qui rispondo con i numeri a:

  1. COPERTURA: da quando esiste OHLCV su Deribit MAINNET (ccxt pubblico, no token) per
     gli strumenti che tradiamo — inverse (BTC/ETH-PERPETUAL) e lineari USDC.
  2. TIMEFRAME nativi disponibili su Deribit.
  3. FEDELTA' inverse-vs-lineare (stesso indice? -> posso usare l'inverse, storia lunga,
     come price-series e i lineari recenti sono ridondanti per il PREZZO).
  4. GAP pre-Deribit: quanto indietro vanno le strategie e cosa manca -> da gap-fillare
     con Coinbase USD (spot, NON USDT).

Tutto via ccxt pubblico Deribit (= api.deribit.com mainnet, reale). Non modifica nulla.

    uv run python scripts/analysis/deribit_history_plan.py
"""
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
import pandas as pd
import ccxt

DERIBIT = ccxt.deribit({"enableRateLimit": True})
COINBASE = ccxt.coinbase({"enableRateLimit": True})


def earliest(symbol: str, tf: str = "1d") -> tuple[str | None, int, str | None]:
    """Trova la prima candela disponibile (probe since 2016) + n candele totali stimate."""
    since = int(pd.Timestamp("2016-01-01", tz="UTC").timestamp() * 1000)
    try:
        rows = DERIBIT.fetch_ohlcv(symbol, tf, since=since, limit=5000)
    except Exception as e:
        return None, 0, f"{type(e).__name__}: {str(e)[:60]}"
    if not rows:
        return None, 0, "no-data"
    first = pd.to_datetime(int(rows[0][0]), unit="ms", utc=True)
    last = pd.to_datetime(int(rows[-1][0]), unit="ms", utc=True)
    return f"{first.date()} -> {last.date()}", len(rows), None


def list_perps() -> dict:
    """Risolve i simboli ccxt reali dei perp Deribit per BTC/ETH (inverse + lineari)."""
    DERIBIT.load_markets()
    found = {}
    for sym, m in DERIBIT.markets.items():
        if not m.get("swap"):
            continue
        base = m.get("base")
        if base not in ("BTC", "ETH"):
            continue
        settle = m.get("settle")
        kind = "inverse" if m.get("inverse") else "linear"
        found[f"{base}-{kind}({settle})"] = sym
    return found


def fetch_series(ex, symbol, tf, start, end, limit=1000):
    start_ms = int(pd.Timestamp(start, tz="UTC").timestamp() * 1000)
    end_ms = int(pd.Timestamp(end, tz="UTC").timestamp() * 1000)
    tf_ms = ex.parse_timeframe(tf) * 1000
    out, since = {}, start_ms
    while since <= end_ms:
        try:
            rows = ex.fetch_ohlcv(symbol, tf, since=since, limit=limit)
        except Exception:
            break
        if not rows:
            break
        for r in rows:
            if start_ms <= int(r[0]) <= end_ms and r[4]:
                out[int(r[0])] = float(r[4])
        nxt = int(rows[-1][0]) + tf_ms
        if nxt <= since:
            break
        since = nxt
        if len(rows) < limit and since > end_ms:
            break
    return pd.Series(out)


def dev_bps(a: pd.Series, b: pd.Series) -> tuple[int, float, float, float]:
    df = pd.concat([a.rename("a"), b.rename("b")], axis=1, join="inner")
    if len(df) == 0:
        return 0, 0, 0, 0
    d = (df["a"] - df["b"]).abs() / df["b"] * 1e4
    return len(df), float(d.median()), float(d.quantile(.95)), float(d.max())


def main():
    print("=" * 84)
    print("  PIANO STORICO DERIBIT MAINNET (ccxt pubblico, reale)")
    print("=" * 84)

    print("\n[1] Simboli perp Deribit BTC/ETH risolti:")
    perps = list_perps()
    for k, v in perps.items():
        print(f"      {k:<22s} -> {v}")

    print("\n[2] COPERTURA storica (1d, probe da 2016):")
    print(f"      {'strumento':<22s}{'range disponibile':<28s}{'giorni':>8s}")
    cov = {}
    for k, sym in perps.items():
        rng, n, err = earliest(sym, "1d")
        cov[k] = (sym, rng, n)
        print(f"      {k:<22s}{(rng or err or '-'):<28s}{n:>8d}")

    print("\n[3] TIMEFRAME nativi Deribit (test su BTC inverse, oggi):")
    bsym = next((s for k, s in perps.items() if k.startswith("BTC-inverse")), "BTC/USD:BTC")
    tfs = []
    for tf in ("1m", "3m", "5m", "10m", "15m", "30m", "1h", "2h", "3h", "4h", "6h", "12h", "1d"):
        try:
            r = DERIBIT.fetch_ohlcv(bsym, tf, limit=3)
            tfs.append(tf if r else f"{tf}:vuoto")
        except Exception:
            tfs.append(f"{tf}:NO")
    print(f"      ok: {[t for t in tfs if ':' not in t]}")
    print(f"      ko: {[t for t in tfs if ':' in t]}")

    print("\n[4] FEDELTA' inverse-vs-lineare USDC (close 1h, ultimi ~40g):")
    for base in ("BTC", "ETH"):
        inv = next((s for k, s in perps.items() if k.startswith(f"{base}-inverse")), None)
        lin = next((s for k, s in perps.items() if k.startswith(f"{base}-linear")), None)
        if not inv or not lin:
            print(f"      {base}: manca inverse o lineare"); continue
        a = fetch_series(DERIBIT, inv, "1h", "2026-04-15", "2026-05-27")
        b = fetch_series(DERIBIT, lin, "1h", "2026-04-15", "2026-05-27")
        n, med, p95, mx = dev_bps(a, b)
        print(f"      {base}: barre={n}  inverse-vs-lineare  med {med:.1f} bps  p95 {p95:.1f}  max {mx:.1f}")

    print("\n[5] GAP pre-Deribit: Deribit inverse vs Coinbase USD su finestra PROFONDA (2020-06, 1d):")
    for base in ("BTC", "ETH"):
        inv = next((s for k, s in perps.items() if k.startswith(f"{base}-inverse")), None)
        a = fetch_series(DERIBIT, inv, "1d", "2020-06-01", "2020-09-01")
        b = fetch_series(COINBASE, f"{base}/USD", "1d", "2020-06-01", "2020-09-01", limit=300)
        n, med, p95, mx = dev_bps(a, b)
        cov_first = cov.get(f"{base}-inverse(BTC)" if base == "BTC" else f"{base}-inverse(ETH)", (None, "?", 0))[1]
        print(f"      {base}: Deribit-vs-Coinbase barre={n}  med {med:.1f} bps  p95 {p95:.1f}  max {mx:.1f}")


if __name__ == "__main__":
    main()
