docs: aggiorna strategie_attive.html + CLAUDE/TODO a v1.1.20 (XS01, real-truth, 19 sleeve)
- make_strategy_doc: nuova famiglia XSEC — card XS01 (meccanismo, dispersion-gate disp_min=0.0313, gate PORT06 OOS 10.07->10.37) con grafico book+gate e tabella per anno (engine canonico ungated); pesi aggiornati a 19 sleeve (5.69/5.26/2.94%); header con real-truth ledger e 4 book paper; bullet metodologia real-truth; ripuliti i riferimenti 'oggi' (EXIT-16 su DIP01, fix punto-10 SH01) - strategie_attive.html rigenerato: v1.1.20, backtest canonico FULL Sharpe 7.34 / DD 3.46% — OOS Sharpe 10.07 / DD 1.48% (19 sleeve, XS01 incluso) - CLAUDE.md: sezione XS01 (famiglia XSEC, gate, dispersion-gate live-only, FC01 scartata), copertura reale 15/19, varianti gioco options/session/grid in struttura - TODO.md: stato esecuzione aggiornato (6 pairs, XS01 paper, real-truth) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -379,13 +379,43 @@ def chart_sh01():
|
||||
return b64(fig)
|
||||
|
||||
|
||||
def chart_xs01():
|
||||
"""Book corrente (long perdenti/short vincenti) + dispersione cross-section col gate."""
|
||||
from scripts.strategies.XS01_cross_sectional import aligned_panel, UNIVERSE, LB
|
||||
M = aligned_panel()
|
||||
logC = np.log(M.values)
|
||||
ts = pd.to_datetime(M.index, unit="ms", utc=True)
|
||||
dm = logC[-1] - logC[-1 - LB]
|
||||
dm = dm - dm.mean()
|
||||
w = -dm / np.sum(np.abs(dm))
|
||||
fig, (ax, ax2) = plt.subplots(1, 2, figsize=(8.6, 3.4), width_ratios=[1, 1.5])
|
||||
ax.bar(UNIVERSE, w * 100, color=[C_TP if x > 0 else C_SL for x in w])
|
||||
ax.set_ylabel("peso book %")
|
||||
ax.tick_params(axis="x", rotation=60)
|
||||
ax.set_title("book: long i perdenti relativi,\nshort i vincenti (mom 48h demeaned)",
|
||||
loc="left", fontweight="bold", fontsize=9)
|
||||
D = logC[LB:] - logC[:-LB]
|
||||
disp = pd.Series(D.std(axis=1), index=ts[LB:]).iloc[-24 * 180:]
|
||||
ax2.plot(disp.index, disp.values, color="#333", lw=0.7)
|
||||
ax2.axhline(0.0313, color=C_SL, ls="--", lw=1.2)
|
||||
on = disp.values >= 0.0313
|
||||
ax2.fill_between(disp.index, 0, disp.values.max(), where=on, alpha=0.10, color=C_TP)
|
||||
ax2.annotate("disp_min 0.0313 (p50 TRAIN)\nentry solo sopra soglia",
|
||||
(disp.index[-1], 0.0313), xytext=(-150, 10),
|
||||
textcoords="offset points", color=C_SL, fontsize=8)
|
||||
ax2.set_title("dispersion-gate: std cross-section del momentum",
|
||||
loc="left", fontweight="bold", fontsize=9)
|
||||
fig.tight_layout()
|
||||
return b64(fig)
|
||||
|
||||
|
||||
def chart_weights():
|
||||
p = PORTFOLIOS["PORT06"]
|
||||
ids = p.sleeve_ids
|
||||
w = W.weight_vector("cap", ids, None, caps=p.caps)
|
||||
fam = {i: W.family_of(i) for i in ids}
|
||||
colors = {"FADE": "#1f6fd6", "HONEST": "#e08c1a", "PAIRS": "#9467bd",
|
||||
"TSM": "#5ab4ac", "SHAPE": "#d64545"}
|
||||
"TSM": "#5ab4ac", "SHAPE": "#d64545", "XSEC": "#8c564b"}
|
||||
order = sorted(ids, key=lambda i: (fam[i], i))
|
||||
fig, ax = plt.subplots(figsize=(8.6, 2.9))
|
||||
ax.bar(order, [w[i] * 100 for i in order], color=[colors[fam[i]] for i in order])
|
||||
@@ -547,6 +577,25 @@ def stats_multi():
|
||||
yearly_table({"TSM01 (universo 8)": equity_yearly(tsm)}, note))
|
||||
|
||||
|
||||
def stats_xs01():
|
||||
"""XS01 per-anno dall'engine canonico (UNGATED, come il backtest di portafoglio)."""
|
||||
from scripts.strategies.XS01_cross_sectional import xsec_sim
|
||||
r = xsec_sim()
|
||||
s = pd.Series(r["eq_v"], index=pd.to_datetime(r["eq_ts"], utc=True))
|
||||
years = {}
|
||||
for y in sorted(r["yearly"]):
|
||||
g = s[s.index.year == y]
|
||||
dd = float(((g.cummax() - g) / g.cummax()).max() * 100) if len(g) else 0.0
|
||||
years[int(y)] = {"n": r["yearly_n"].get(y, 0), "pnl": r["yearly"][y], "dd": dd}
|
||||
pk = s.cummax()
|
||||
note = ("PnL = Σ rendimenti netti per trade del book (%, gross 1, fee 0.20% RT/book = "
|
||||
"turnover 2×0.10%); DD dall'equity compounding (pos 0.15, leva 3x convenzione "
|
||||
"test). Engine canonico SENZA dispersion-gate (il gate agisce solo sul path "
|
||||
"live, come trend/hurst sulle fade → il live farà meglio del backtest).")
|
||||
return yearly_table({"XS01 (universo 8)": (years, float(((pk - s) / pk).max() * 100))},
|
||||
note)
|
||||
|
||||
|
||||
def stats_sh01():
|
||||
"""SH01 per-anno dal walk-forward EXPANDING (il regime validato e ora live)."""
|
||||
from scripts.analysis.shape_ml_research import ml_wf_entries
|
||||
@@ -580,8 +629,8 @@ box-shadow:0 1px 3px rgba(0,0,0,.05)}
|
||||
.badge{display:inline-block;font-size:11px;font-weight:700;padding:2px 9px;border-radius:10px;
|
||||
margin-right:6px;color:#fff}
|
||||
.b-fade{background:#1f6fd6}.b-honest{background:#e08c1a}.b-pairs{background:#9467bd}
|
||||
.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-real{background:#2e9e6b}
|
||||
.b-sim{background:#8a8f98}
|
||||
.b-tsm{background:#5ab4ac}.b-shape{background:#d64545}.b-xsec{background:#8c564b}
|
||||
.b-real{background:#2e9e6b}.b-sim{background:#8a8f98}
|
||||
img{max-width:100%;border:1px solid #eee;border-radius:6px;margin-top:10px}
|
||||
table{border-collapse:collapse;width:100%;font-size:13px;margin-top:8px}
|
||||
td,th{border:1px solid #e3e5e8;padding:5px 9px;text-align:left}
|
||||
@@ -609,6 +658,7 @@ def main():
|
||||
st_dip = stats_dip()
|
||||
t_pairs = stats_pairs()
|
||||
t_tr, t_rot, t_tsm = stats_multi()
|
||||
t_xs = stats_xs01()
|
||||
print(" SH01 walk-forward expanding (il piu' lento)...")
|
||||
st_sh = stats_sh01()
|
||||
|
||||
@@ -631,6 +681,7 @@ def main():
|
||||
g_pr = chart_pr01()
|
||||
g_tsm = chart_tsm01(panel)
|
||||
g_sh = chart_sh01()
|
||||
g_xs = chart_xs01()
|
||||
|
||||
# metriche canoniche del default per l'intestazione (sempre aggiornate)
|
||||
pr = PORTFOLIOS["PORT06"].backtest()
|
||||
@@ -665,7 +716,7 @@ estremo in un'ora), fada il movimento. Exit in multipli di ATR. È la fade più
|
||||
sono falsi negativi</b> — l'overshoot che buca lo stop e rientra è esattamente il movimento che
|
||||
la fade sta comprando. Con EXIT-16 lo SL intrabar è disattivato: si esce solo se il <b>close</b>
|
||||
della barra completata sfonda il livello di 0.5·ATR. Il TP intrabar resta. Impatto sul
|
||||
portafoglio: OOS Sharpe 8.82→10.06. Esteso oggi anche a DIP01 (grid 36/36).</p>""", g_e16)
|
||||
portafoglio: OOS Sharpe 8.82→10.06. Esteso anche a DIP01 (2026-06-07, grid 36/36).</p>""", g_e16)
|
||||
|
||||
c_dip = card("DIP01 — Dip Buy (BTC)", B("honest", "HONEST") + real, """
|
||||
<p>Compra il <b>dip</b>: quando lo z-score del prezzo incrocia sotto −2.5 (sell-off rapido),
|
||||
@@ -713,24 +764,41 @@ l'edge): la coda si gestisce dimezzando il peso della famiglia (cap 5.88%).</p>
|
||||
<p class='sub'>Esecuzione reale single-leg su Deribit testnet: niente TP/SL, chiusura a orizzonte
|
||||
H=12 (market reduce-only), disaster-bracket on-book come unica protezione di coda — è il
|
||||
diversificatore più decorrelato del portafoglio.</p>
|
||||
<p class='sub'>Fix di oggi (punto-10): il training live usa la storia COMPLETA dal parquet
|
||||
<p class='sub'>Fix punto-10 (2026-06-07): il training live usa la storia COMPLETA dal parquet
|
||||
locale (il regime corto a 365g non era robusto: trade-rate 22% vs 10% validato).</p>""", g_sh, yearly_table(st_sh))
|
||||
|
||||
c_xs = card("XS01 — Cross-Sectional Reversion (8 asset)", B("xsec", "XSEC") + sim, """
|
||||
<p><b>Famiglia nuova (2026-06-09)</b>: ogni 12 ore classifica 8 crypto (BTC, ETH, LTC, ADA,
|
||||
SOL, BNB, XRP, DOGE) per rendimento a 48 ore e va <b>long i perdenti relativi / short i
|
||||
vincenti</b> (peso ∝ −(ret − media cross-section)), market-neutral gross 1. Cattura il
|
||||
<i>fattore</i> reversione cross-sezionale — distinto dai pairs (pairwise) e dai fade
|
||||
(single-asset): correlazione ~0 con entrambi. Gate PORT06: OOS Sharpe 9.66→10.07,
|
||||
FULL DD 3.68→3.46. Plateau robusto (lb 12-72 × hold 6-24 tutte OOS+).</p>
|
||||
<p class='sub'><b>Dispersion-gate (2026-06-10, v1.1.20)</b>: entra solo se la dispersione
|
||||
cross-section del momentum ≥ 0.0313 (mediana TRAIN) — la reversione paga quando c'è
|
||||
dispersione da far rientrare. Diagnostica monotona TRAIN e OOS, plateau p30-p70,
|
||||
standalone Sharpe 2.50→3.46 (regge fee 2x), PORT06 OOS 10.07→<b>10.37</b> a DD pari.
|
||||
Solo path live (backtest canonico non filtrato → il live farà meglio del backtest).</p>
|
||||
<p class='sub'>8 gambe → niente esecuzione reale: gira PAPER come i book multi-asset
|
||||
(il rumore di arrotondamento a €2k dominerebbe). Worker validato (replay == backtest esatto).</p>""",
|
||||
g_xs, t_xs)
|
||||
|
||||
html = f"""<!doctype html><html lang="it"><head><meta charset="utf-8">
|
||||
<title>PythagorasGoal — Strategie attive PORT06</title><style>{CSS}</style></head>
|
||||
<body><div class="wrap">
|
||||
<h1>PythagorasGoal — Strategie attive</h1>
|
||||
<p class="sub">Portafoglio live <b>PORT06</b> — definizione {n_def} sleeve; <b>pool live real-only 15 sleeve</b>
|
||||
(i 3 book multi-asset girano in statistica, fuori dal capitale-pool). Capitale pool €2.000, leva 2x ·
|
||||
(i 4 book multi-asset TR01/ROT02/TSM01/XS01 girano in statistica, fuori dal capitale-pool).
|
||||
Capitale pool €2.000, leva 2x, <b>real-truth ledger</b> ·
|
||||
v{ver} · generato {now} · backtest canonico: {hdr}</p>
|
||||
<div class="card">
|
||||
<p>Tre famiglie principali quasi <b>scorrelate</b> fra loro (fade↔honest ~0.05, pairs ~0.02-0.09,
|
||||
shape ~0.08): la diversificazione è la leva anti-drawdown. Pesi equal con tetti per famiglia,
|
||||
ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip incluse ovunque;
|
||||
ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.</p>
|
||||
<p>Famiglie quasi <b>scorrelate</b> fra loro (fade↔honest ~0.05, pairs ~0.02-0.09,
|
||||
shape ~0.08, xsec ~0): la diversificazione è la leva anti-drawdown. Pesi equal con tetti
|
||||
per famiglia, ribilancio giornaliero su capitale pool condiviso. Fee Deribit 0.10% round-trip
|
||||
incluse ovunque; ogni meccanismo live è passato da un gate out-of-sample a livello di portafoglio.</p>
|
||||
<img src="data:image/png;base64,{g_w}"></div>
|
||||
|
||||
<h2>FADE — mean-reversion intraday 1h <span class="sub">(6 sleeve × 6.47%)</span></h2>
|
||||
<h2>FADE — mean-reversion intraday 1h <span class="sub">(6 sleeve × 5.69%)</span></h2>
|
||||
<div class="note"><b>Tesi della famiglia:</b> sui perpetui crypto l'edge è la <i>reversione</i>:
|
||||
i movimenti estremi rientrano (i breakout falliscono — l'intera famiglia squeeze-breakout è stata
|
||||
scartata come artefatto di look-ahead). Le fade vendono l'eccesso e comprano il panico, con tre
|
||||
@@ -741,14 +809,16 @@ non si fada un crollo/parabolica), <b>EXIT-16</b> (stop solo sul close confermat
|
||||
{c_mr02}
|
||||
{c_mr07}
|
||||
{c_e16}
|
||||
<h2>HONEST — long-only multi-regime <span class="sub">(3 sleeve × 6.47%)</span></h2>
|
||||
<h2>HONEST — long-only multi-regime <span class="sub">(3 sleeve × 5.69%)</span></h2>
|
||||
{c_dip}
|
||||
{c_tr}
|
||||
{c_rot}
|
||||
<h2>PAIRS — spread reversion market-neutral <span class="sub">(6 sleeve: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)</span></h2>
|
||||
<h2>PAIRS — spread reversion market-neutral <span class="sub">(6 sleeve × 5.26%: 5 coppie 1h + ETH/BTC 15m a mezza size, famiglia ≤33%)</span></h2>
|
||||
{c_pr}
|
||||
<h2>TSM — trend-following multi-orizzonte <span class="sub">(1 sleeve × 6.47%)</span></h2>
|
||||
<h2>TSM — trend-following multi-orizzonte <span class="sub">(1 sleeve × 5.69%)</span></h2>
|
||||
{c_tsm}
|
||||
<h2>XSEC — reversione cross-sectional <span class="sub">(1 sleeve × 5.69%)</span></h2>
|
||||
{c_xs}
|
||||
<h2>SHAPE — ML morfologico <span class="sub">(2 sleeve × 2.94%, famiglia ≤5.88%)</span></h2>
|
||||
{c_sh}
|
||||
|
||||
@@ -757,7 +827,8 @@ non si fada un crollo/parabolica), <b>EXIT-16</b> (stop solo sul close confermat
|
||||
<li><b>Fee sempre incluse</b>: 0.10% round-trip taker Deribit (misurate reali = assunte). Molte operazioni = morte per fee: ogni strategia regge lo stress a fee doppie.</li>
|
||||
<li><b>Niente look-ahead</b>: direzione e prezzo decisi solo con dati fino al close corrente; barre in formazione escluse (lezione EXIT-16). La famiglia squeeze (accuratezze 76-82%) è stata scartata proprio per questo artefatto.</li>
|
||||
<li><b>Gate out-of-sample</b>: nessun meccanismo va in produzione senza migliorare (o non degradare) il portafoglio FULL e OOS — robusto individualmente ≠ migliora PORT06.</li>
|
||||
<li><b>Esecuzione reale shadow (~83% del portafoglio)</b>: 15 sleeve eseguono ordini reali su Deribit testnet accanto al sim — i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. <b>ETH/BTC 15m flat-skip</b> (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL). Restano simulati solo i book multi-asset TR01/ROT02/TSM01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.</li>
|
||||
<li><b>Esecuzione reale shadow (15 sleeve su 19)</b>: i 6 fade + DIP01 (single-leg, TP limit al livello, disaster-stop −30% on-book), i 6 pairs incl. <b>ETH/BTC 15m flat-skip</b> (2 gambe, leg-risk unwind) e i 2 SH01 (single-leg, exit a orizzonte, niente TP/SL) eseguono ordini reali su Deribit testnet. Restano simulati solo i book multi-asset TR01/ROT02/TSM01/XS01 (bloccati dal capitale: serve ~€20k per il rumore di arrotondamento). Fee reali verificate dai trade; divergenze sim/reale ≥100bps alertate su Telegram.</li>
|
||||
<li><b>Real-truth ledger (2026-06-10)</b>: il capitale dei worker eseguiti si aggiorna col PnL dei <b>fill reali</b> (fee reali incluse), non col sim — equity, pesi e notional derivano dai soldi veri sul conto; il sim resta diagnostica nel log (fallback dichiarato solo se il trade reale non è mai esistito). Le decisioni di entry/exit restano guidate dal feed.</li>
|
||||
</ul></div>
|
||||
<p class="sub">Generato da <code>scripts/analysis/make_strategy_doc.py</code> — grafici da episodi reali sui dati parquet locali.</p>
|
||||
</div></body></html>"""
|
||||
|
||||
Reference in New Issue
Block a user