Files
PythagorasGoal/scripts/analysis/honest_yearly2.py
2026-05-28 23:52:25 +02:00

75 lines
2.5 KiB
Python

"""Tabella per-anno (PnL% e DD% intra-anno) delle versioni MIGLIORATE:
ROT02 (dual-momentum), le 3 sleeve e il PORTAFOGLIO combinato.
Tutto NETTO. Riusa gli engine di honest_improve / honest_improve2.
"""
from __future__ import annotations
import sys
from pathlib import Path
import numpy as np
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from scripts.analysis.honest_improve2 import ( # noqa: E402
dip_market_gated, _daily_equity, _norm, _tr_basket_daily, _rot_daily_equity,
)
def _year_dd(eq: pd.Series) -> dict[int, float]:
out = {}
for y, g in eq.groupby(eq.index.year):
peak = g.iloc[0]; dd = 0.0
for v in g:
peak = max(peak, v); dd = max(dd, (peak - v) / peak if peak > 0 else 0.0)
out[int(y)] = dd * 100
return out
def _year_pnl(eq: pd.Series) -> dict[int, float]:
out = {}
for y, g in eq.groupby(eq.index.year):
out[int(y)] = (g.iloc[-1] / g.iloc[0] - 1) * 100
return out
def table(name, eq):
eq = _norm(eq)
dd = _year_dd(eq); pnl = _year_pnl(eq)
print(f"\n {name}")
print(f" {'Anno':>6s}{'PnL%':>9s}{'DD%':>7s}")
print(" " + "-" * 22)
for y in sorted(pnl):
print(f" {y:>6d}{pnl[y]:>+9.0f}{dd[y]:>7.0f}")
tot = (eq.iloc[-1] / eq.iloc[0] - 1) * 100
print(f" {'TOT':>6s}{tot:>+9.0f}{_year_dd(eq) and max(_year_dd(eq).values()):>7.0f}(max anno)")
if __name__ == "__main__":
print("=" * 60)
print(" RISULTATI PER ANNO — versioni migliorate (NETTO)")
print("=" * 60)
# ROT02 dal 2020 (dati paniere)
idx_rot = pd.date_range("2020-09-01", "2026-05-26", freq="1D", tz="UTC")
eq_rot = _rot_daily_equity(idx_rot)
table("ROT02 — dual-momentum rotation (1d)", eq_rot)
# sleeve + portafoglio dal 2021
idx = pd.date_range("2021-01-01", "2026-05-26", freq="1D", tz="UTC")
d = dip_market_gated("BTC", market_n=0, return_equity=True)
eq_dip = _norm(_daily_equity(d["eq_ts"], d["eq_v"], idx))
eq_tr = _norm(_tr_basket_daily(["BNB", "BTC", "DOGE", "SOL", "XRP"], idx))
eq_r2 = _norm(_rot_daily_equity(idx))
table("Sleeve DIP01 — BTC (1h)", eq_dip)
table("Sleeve TR01 — basket (4h)", eq_tr)
table("Sleeve ROT02 (1d)", eq_r2)
drets = pd.DataFrame({"DIP": eq_dip.pct_change().fillna(0),
"TR": eq_tr.pct_change().fillna(0),
"ROT": eq_r2.pct_change().fillna(0)})
combo = (1 + drets.mean(axis=1)).cumprod()
table("PORTAFOGLIO equal-weight (daily rebal)", combo)