"""Report accuracy per ANNO × MERCATO delle strategie migliori. Esegue ogni strategia vincente su BTC e ETH e produce tabella accuracy/trades per ogni anno. Permette di vedere robustezza temporale e differenze tra mercati. """ from __future__ import annotations import sys sys.path.insert(0, ".") import importlib.util from pathlib import Path STRATEGIES_DIR = Path("scripts/strategies") def load_class(module_file, class_name): path = STRATEGIES_DIR / f"{module_file}.py" spec = importlib.util.spec_from_file_location(module_file, path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return getattr(mod, class_name) # (label, module, class, params, hold) STRATEGIES = [ ("SQ02 antifake+vol", "SQ02_squeeze_antifake_vol", "SqueezeAntifakeVol", {}, 3), ("MT01 ema20+vol", "MT01_squeeze_mtf_momentum", "SqueezeMTFMomentum", {"ema_period": 20, "min_slope": 0.001, "vol_filter": True}, 3), ("PD01 vtb3 vm1.3", "PD01_price_volume_divergence", "PriceVolumeDivergence", {}, 3), ("CM01 cb6+vol", "CM01_cross_market_momentum", "CrossMarketMomentum", {"cross_bars": 6, "mom_min": 0.001, "use_vol": True}, 3), ("AD01 lt.65 ht.95", "AD01_adaptive_squeeze", "AdaptiveSqueeze", {"low_thr": 0.65, "high_thr": 0.95, "use_vol": True}, 3), ] ASSETS = ["BTC", "ETH"] TF = "15m" ALL_YEARS = list(range(2018, 2027)) def run(): results = {} # (label, asset) -> BacktestResult for label, module, cls_name, params, hold in STRATEGIES: try: cls = load_class(module, cls_name) except Exception as e: print(f"SKIP {label}: {e}") continue strat = cls() for asset in ASSETS: try: r = strat.backtest(asset, TF, hold=hold, **params) if r: results[(label, asset)] = r except Exception as e: print(f" errore {label} {asset}: {e}") # ── Tabella ACCURACY per anno × mercato ────────────────────────── print(f"\n{'=' * 140}") print(f" ACCURACY PER ANNO × MERCATO — {TF} (fee 0.2% RT, leva 3x, pos 15%)") print(f"{'=' * 140}") header = f" {'Strategia':<22s} {'Mkt':>3s}" for y in ALL_YEARS: header += f" {y:>7d}" header += f" │ {'TOT':>6s} {'DD%':>5s} {'Worst':>10s}" print(header) print(f" {'─' * 136}") for label, module, cls_name, params, hold in STRATEGIES: for asset in ASSETS: r = results.get((label, asset)) if not r: continue yd = {ys.year: ys for ys in r.yearly} line = f" {label:<22s} {asset:>3s}" for y in ALL_YEARS: if y in yd: line += f" {yd[y].accuracy:>5.0f}%↑" if yd[y].accuracy >= 80 else f" {yd[y].accuracy:>5.0f}% " else: line += f" {'—':>7s}" worst = r.worst_year worst_str = f"{worst.year}({worst.accuracy:.0f}%)" if worst else "N/A" line += f" │ {r.accuracy:>5.1f}% {r.max_dd:>4.1f}% {worst_str:>10s}" print(line) print(f" {'·' * 136}") # ── Tabella TRADES per anno × mercato ──────────────────────────── print(f"\n{'=' * 140}") print(f" NUMERO TRADES PER ANNO × MERCATO") print(f"{'=' * 140}") header = f" {'Strategia':<22s} {'Mkt':>3s}" for y in ALL_YEARS: header += f" {y:>7d}" header += f" │ {'TOT':>6s} {'€/day':>6s}" print(header) print(f" {'─' * 130}") for label, module, cls_name, params, hold in STRATEGIES: for asset in ASSETS: r = results.get((label, asset)) if not r: continue yd = {ys.year: ys for ys in r.yearly} line = f" {label:<22s} {asset:>3s}" for y in ALL_YEARS: if y in yd: line += f" {yd[y].trades:>7d}" else: line += f" {'—':>7s}" line += f" │ {r.trades:>6d} {r.daily_pnl:>+6.2f}" print(line) print(f" {'·' * 130}") # ── Tabella PnL per anno × mercato ────────────────────────────── print(f"\n{'=' * 140}") print(f" PnL € PER ANNO × MERCATO (su €1000, no compounding tra anni)") print(f"{'=' * 140}") header = f" {'Strategia':<22s} {'Mkt':>3s}" for y in ALL_YEARS: header += f" {y:>7d}" header += f" │ {'TOT€':>8s}" print(header) print(f" {'─' * 132}") for label, module, cls_name, params, hold in STRATEGIES: for asset in ASSETS: r = results.get((label, asset)) if not r: continue yd = {ys.year: ys for ys in r.yearly} line = f" {label:<22s} {asset:>3s}" for y in ALL_YEARS: if y in yd: line += f" {yd[y].pnl:>+7.0f}" else: line += f" {'—':>7s}" line += f" │ {r.pnl:>+8.0f}" print(line) print(f" {'·' * 132}") # ── Sintesi: media per anno (tutte le strategie) ──────────────── print(f"\n{'=' * 140}") print(f" SINTESI — Accuracy media per anno (tutte le strategie, BTC+ETH)") print(f"{'=' * 140}") year_acc = {y: [] for y in ALL_YEARS} for (label, asset), r in results.items(): for ys in r.yearly: if ys.trades >= 10: year_acc[ys.year].append(ys.accuracy) line_y = f" {'Anno':<22s} " line_a = f" {'Acc media':<22s} " for y in ALL_YEARS: accs = year_acc[y] avg = sum(accs) / len(accs) if accs else 0 line_y += f" {y:>7d}" line_a += f" {avg:>6.1f}%" print(line_y) print(line_a) if __name__ == "__main__": run()