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>
75 lines
3.3 KiB
Python
75 lines
3.3 KiB
Python
"""Statistica storica PER ANNO degli sleeve TUTTORA in LIVE REALE (no paper).
|
|
|
|
Config live = micro-test mainnet PORT06 Fase 1 (portfolios.yml): nel POOL reale
|
|
ci sono SOLO i 7 single-leg con esecuzione reale su Deribit mainnet:
|
|
- 6 FADE 15m: MR01/MR02/MR07 x BTC/ETH
|
|
- DIP01 (BTC 1h)
|
|
Tutto il resto (pairs PR01, SH01, TR01/ROT02/TSM01/XS01) e' PAPER -> escluso.
|
|
|
|
Backtest NETTO fee, leva 3x, pos 15%/sleeve, finestra 2021-2026, OOS = ultimo 30%.
|
|
NB: i fade live girano col filtro trend 3.0 (gia' applicato in fade_daily_equity);
|
|
i guard live (EXIT-16 confirm, freeze-gate, ecc.) agiscono SOLO sul path live ->
|
|
il backtest canonico NON e' filtrato (il live fa MEGLIO sul DD).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(PROJECT_ROOT))
|
|
|
|
from scripts.analysis.combine_portfolio import (
|
|
build_all_sleeves, port_returns, metrics, yearly_returns, SPLIT, OOS_DATE, IDX,
|
|
)
|
|
|
|
YEARS = sorted(set(IDX.year))
|
|
|
|
# I 7 sleeve eseguiti reale (vedi portfolios.yml -> execution.sleeves + DIP01).
|
|
LIVE_REAL = ["MR01_BTC", "MR01_ETH", "MR02_BTC", "MR02_ETH",
|
|
"MR07_BTC", "MR07_ETH", "DIP01_BTC"]
|
|
|
|
|
|
def main():
|
|
print("Costruzione equity giornaliere (puo' richiedere ~1-2 min)...\n")
|
|
S = build_all_sleeves()
|
|
live = {k: S[k] for k in LIVE_REAL} # filtra ai soli 7 reali
|
|
|
|
# ---------- (A) RET% NETTO per anno, per sleeve ----------
|
|
print("=" * 96)
|
|
print(" (A) RET% NETTO PER ANNO — sleeve in LIVE REALE (no paper) | leva 3x, fee netta, pos 15%")
|
|
print("=" * 96)
|
|
print(f" {'sleeve':<14s}" + "".join(f"{y:>9d}" for y in YEARS))
|
|
print(" " + "-" * 90)
|
|
yr_each = {k: yearly_returns(v.pct_change().fillna(0.0)) for k, v in live.items()}
|
|
for k in LIVE_REAL:
|
|
print(f" {k.replace('_',' '):<14s}" + "".join(f"{yr_each[k].get(y, 0):>+9.0f}" for y in YEARS))
|
|
# pool equal-weight dei 7 (== il pool reale del micro-test)
|
|
pool = port_returns(live)
|
|
print(" " + "-" * 90)
|
|
yr_pool = yearly_returns(pool)
|
|
print(f" {'POOL-7 (eq)':<14s}" + "".join(f"{yr_pool.get(y, 0):>+9.0f}" for y in YEARS))
|
|
|
|
# ---------- (B) metriche FULL / OOS per sleeve + pool ----------
|
|
print("\n" + "=" * 96)
|
|
print(f" (B) METRICHE — FULL (2021->) | OOS da {OOS_DATE} (ultimo 30%)")
|
|
print("=" * 96)
|
|
print(f" {'sleeve':<14s}{'Ret%':>9s}{'CAGR':>7s}{'DD%':>7s}{'Shrp':>7s}"
|
|
f" | {'oRet%':>9s}{'oDD%':>7s}{'oShrp':>7s}")
|
|
print(" " + "-" * 80)
|
|
for k in LIVE_REAL:
|
|
dr = live[k].pct_change().fillna(0.0)
|
|
f, o = metrics(dr), metrics(dr, lo=SPLIT)
|
|
print(f" {k.replace('_',' '):<14s}{f['ret']:>+9.0f}{f['cagr']:>7.0f}{f['dd']:>7.1f}{f['sharpe']:>7.2f}"
|
|
f" | {o['ret']:>+9.0f}{o['dd']:>7.1f}{o['sharpe']:>7.2f}")
|
|
print(" " + "-" * 80)
|
|
f, o = metrics(pool), metrics(pool, lo=SPLIT)
|
|
print(f" {'POOL-7 (eq)':<14s}{f['ret']:>+9.0f}{f['cagr']:>7.0f}{f['dd']:>7.1f}{f['sharpe']:>7.2f}"
|
|
f" | {o['ret']:>+9.0f}{o['dd']:>7.1f}{o['sharpe']:>7.2f}")
|
|
print("\n NB: il backtest canonico NON applica i guard live (EXIT-16 confirm, freeze-gate,")
|
|
print(" TP_PHANTOM, ...) -> sul DD il live fa MEGLIO del backtest. Numeri leva 3x.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|