chore: untrack paper_trades runtime data + report per anno/mercato
- data/paper_trades/ rimosso dal tracking (dati runtime, gitignored) - scripts/analysis/yearly_market_report.py: accuracy/trades/PnL per anno×mercato Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user