research(wave-0822): VOL-SIZE — il p-value del null di permutazione si cita col segno, non col decimale (3 ancore su 23)
This commit is contained in:
@@ -466,35 +466,54 @@ def main() -> None:
|
||||
print(f"\n[3] XS01 — soglia PUBBLICATA ~$20.000 (origine: stima a occhio, 'rumore arrotondamento')")
|
||||
Wxs, dret, C, cols, dif = xs01_pesi()
|
||||
print(f" prova d'identita' col sleeve ufficiale `_xsec_returns()`: max|diff| = {dif:.3e}")
|
||||
from src.portfolio.sleeves import XS_CFG, _xsec_returns
|
||||
off_xs = _xsec_returns()
|
||||
m_off = metriche(off_xs.values, pd.DatetimeIndex(off_xs.index))
|
||||
gross_xs = np.abs(Wxs).sum(axis=1)
|
||||
att = gross_xs > 1e-9
|
||||
dW = np.abs(np.diff(Wxs, axis=0, prepend=np.zeros((1, Wxs.shape[1]))))
|
||||
tk_nz = dW[dW > 1e-9]
|
||||
# DUE popolazioni di ordini, e vanno separate: il RIBILANCIAMENTO del segnale (ogni H=10 giorni,
|
||||
# cambia il paniere 5+5) e la DERIVA del vol-target (ogni giorno, micro-aggiustamenti).
|
||||
H = XS_CFG["H"]
|
||||
is_reb = np.zeros(len(Wxs), bool); is_reb[::H] = True
|
||||
reb = dW[is_reb]; reb = reb[reb > 1e-9]
|
||||
drift = dW[~is_reb]; drift = drift[drift > 1e-9]
|
||||
print(f" sleeve ufficiale `_xsec_returns()`: Sharpe {m_off['sharpe']:.2f} "
|
||||
f"maxDD {m_off['maxdd']:.1f}% CAGR {m_off['cagr']:.1f}%")
|
||||
print(f" gambe simultanee: {int((np.abs(Wxs) > 1e-9).sum(axis=1)[att].max())} "
|
||||
f"(k=5 long + 5 short); lordo mediano {np.median(gross_xs[att]):.2f}x il capitale "
|
||||
f"(vol-target, cap 3x)")
|
||||
print(f" peso mediano mosso per gamba per ribilanciamento: {np.median(tk_nz)*100:.2f}% "
|
||||
f"del capitale; 10° pctl {np.percentile(tk_nz,10)*100:.2f}%")
|
||||
print(f"\n ticket per gamba (mediano) e % di gambe ESEGUIBILI, per capitale allocato a XS01:")
|
||||
print(f" {'cap XS01':>10}{'ticket med':>12}{'ticket p10':>12}"
|
||||
f"{'>=$5 [D]':>10}{'>=$10 [C]':>11}{'lotto ko':>10}")
|
||||
print(f"\n DUE popolazioni di ordini (separarle e' il punto: non hanno la stessa taglia):")
|
||||
print(f" RIBILANCIAMENTO (ogni {H}g, cambia il paniere): n={len(reb)} "
|
||||
f"peso mosso mediano {np.median(reb)*100:.2f}% p10 {np.percentile(reb,10)*100:.2f}%")
|
||||
print(f" DERIVA vol-target (giornaliera) : n={len(drift)} "
|
||||
f"peso mosso mediano {np.median(drift)*100:.3f}% p10 {np.percentile(drift,10)*100:.3f}%")
|
||||
print(f" -> {100*len(drift)/max(len(reb)+len(drift),1):.0f}% degli ordini sono DERIVA, "
|
||||
f"ed e' la deriva che il pavimento taglia.")
|
||||
print(f"\n ticket per gamba e % di ordini RICHIESTI eseguibili, per capitale allocato a XS01")
|
||||
print(f" (conto = capitale/0.15, perche' XS01 pesa 15% del book di ricerca):")
|
||||
print(f" {'cap XS01':>10}{'conto @15%':>12}{'tick reb':>10}{'tick drift':>12}"
|
||||
f"{'>=$5 [D]':>10}{'>=$10 [C]':>11}{'reb>=$10':>10}")
|
||||
R_xs = dret
|
||||
idx = C.index
|
||||
base = None
|
||||
for cap in CAPITALI:
|
||||
med = np.median(tk_nz) * cap
|
||||
p10 = np.percentile(tk_nz, 10) * cap
|
||||
pct5 = 100.0 * float((tk_nz * cap >= MIN_ORDER_ASSUNTO).mean())
|
||||
pct10 = 100.0 * float((tk_nz * cap >= MIN_ORDER_HL).mean())
|
||||
lot = np.array([meta.loc[s, "lot_usd"] if s in meta.index else 0.0 for s in cols])
|
||||
lotko = 100.0 * float((tk_nz * cap < np.median(lot)).mean())
|
||||
print(f" {cap:>10,.0f}{med:>12.2f}{p10:>12.2f}{pct5:>9.0f}%{pct10:>10.0f}%{lotko:>9.1f}%")
|
||||
pr10 = 100.0 * float((reb * cap >= MIN_ORDER_HL).mean())
|
||||
print(f" {cap:>10,.0f}{cap/0.15:>12,.0f}{np.median(reb)*cap:>10.2f}"
|
||||
f"{np.median(drift)*cap:>12.2f}{pct5:>9.0f}%{pct10:>10.0f}%{pr10:>9.0f}%")
|
||||
lot_xs = np.array([float(meta.loc[s, "lot_usd"]) if s in meta.index else 0.0 for s in cols])
|
||||
px_xs = np.array([float(meta.loc[s, "markPx"]) if s in meta.index else np.nan for s in cols])
|
||||
fee_xs_mod = 0.001 / 2.0 # [D] cio' che il sleeve modella: 5 bps/lato
|
||||
print(f"\n haircut di eseguibilita' (Sharpe modellato - Sharpe realistico), fee {fee_xs_mod*1e4:.1f} bps/lato:")
|
||||
print(f"\n haircut di eseguibilita' (Sharpe modellato - Sharpe realistico), fee {fee_xs_mod*1e4:.1f} bps/lato.")
|
||||
print(f" NB il 'Sh mod' qui INCLUDE la fee sulla deriva del vol-target, che lo sleeve "
|
||||
f"ufficiale NON addebita")
|
||||
print(f" (`turn=|dW|` prima dello scaling): e' il motivo per cui sta sotto il "
|
||||
f"{m_off['sharpe']:.2f} pubblicato.")
|
||||
print(f" {'cap XS01':>10}{'Sh mod':>9}{'Sh $5 [D]':>11}{'Sh $10 [C]':>12}"
|
||||
f"{'haircut $10':>13}{'esegui%':>9}")
|
||||
f"{'haircut $10':>13}{'ordini fatti':>14}")
|
||||
for cap in CAPITALI:
|
||||
m0 = sim_libro(Wxs, R_xs, None, cap, None, None, None, fee_xs_mod)
|
||||
m5 = sim_libro(Wxs, R_xs, None, cap, MIN_ORDER_ASSUNTO, None, None, fee_xs_mod)
|
||||
@@ -506,9 +525,29 @@ def main() -> None:
|
||||
|
||||
# ---------------------------------------------------------------- 4. XSR01
|
||||
print(f"\n[4] XSR01 — soglia PUBBLICATA ~$5.000, gate 2026-10-23 con haircut a $5.000 <= 40%")
|
||||
from scripts.live.paper_xsr import build_panel # stessa costruzione del monitor in produzione
|
||||
from scripts.live.paper_xsr import FEE_LEG, MIN_ORDER, _book, _step, build_panel
|
||||
ts, dtx, Wx, Rx, rbx, sx = build_panel()
|
||||
idxx = pd.DatetimeIndex(dtx)
|
||||
|
||||
# PROVA D'IDENTITA' col monitor IN PRODUZIONE: sim_libro deve riprodurre paper_xsr._step
|
||||
# barra per barra. Senza questa, i numeri qui sotto sarebbero di un'altra macchina.
|
||||
for mo in (None, MIN_ORDER):
|
||||
bk = _book(5000.0, len(sx))
|
||||
ref = np.array([_step(bk, Wx[i], Rx[i], float(rbx[i]), mo) for i in range(len(Wx))])
|
||||
mine = sim_libro(Wx, Rx, rbx, 5000.0, mo, None, None, FEE_LEG)["net"]
|
||||
print(f" identita' vs scripts/live/paper_xsr._step (min_order={mo}): "
|
||||
f"max|diff| = {np.abs(ref - mine).max():.3e}")
|
||||
assert abs(FEE_LEG - FEE_LEG_MODELLO) < 1e-12, "la config congelata di XSR01 e' cambiata"
|
||||
assert abs(MIN_ORDER - MIN_ORDER_ASSUNTO) < 1e-12, "il min-order del monitor e' cambiato"
|
||||
|
||||
# RICONCILIAZIONE col numero PUBBLICATO (1.82): la scoperta (r0725_statarb_basket_gate,
|
||||
# basket_from_positions) addebita "2 gambe per coppia" = 50 alt + 50 BTC. Ma il demeaning
|
||||
# ANNULLA la gamba BTC (sum dei pesi = 0): non si tradano 50 BTC, se ne trada UNA di taglia
|
||||
# zero. Il monitor in produzione lo sa (`d_btc = |sum(w_new) - sum(w_held)|` ~ 0) -> il
|
||||
# pubblicato SOVRASTIMA le fee di ~2x.
|
||||
net_x2 = sim_libro(Wx, Rx, rbx, 5000.0, None, None, None, 2 * FEE_LEG_MODELLO)["net"]
|
||||
print(f" riconciliazione col pubblicato 1.82: a fee RADDOPPIATA (= convenzione della "
|
||||
f"scoperta, 2 gambe/coppia) Sharpe {metriche(net_x2, idxx)['sharpe']:.2f}")
|
||||
lot_x = np.array([float(meta.loc[s, "lot_usd"]) if s in meta.index else 0.0 for s in sx])
|
||||
px_x = np.array([float(meta.loc[s, "markPx"]) if s in meta.index else np.nan for s in sx])
|
||||
dWx = np.abs(np.diff(Wx, axis=0, prepend=np.zeros((1, Wx.shape[1]))))
|
||||
@@ -516,7 +555,7 @@ def main() -> None:
|
||||
print(f" gambe {len(sx)} lordo mediano {np.median(np.abs(Wx).sum(axis=1)):.2f}x "
|
||||
f"peso mosso mediano/gamba {np.median(tkx)*100:.3f}% p10 {np.percentile(tkx,10)*100:.3f}%")
|
||||
print(f"\n {'cap':>9}{'ticket med':>12}{'Sh mod':>9}{'Sh $5 [D]':>11}{'Sh $10 [C]':>12}"
|
||||
f"{'haircut $5':>12}{'haircut $10':>13}{'esegui%':>9}")
|
||||
f"{'haircut $5':>12}{'haircut $10':>13}{'ordini fatti':>14}")
|
||||
hc10_5000 = np.nan
|
||||
for cap in CAPITALI:
|
||||
m0 = sim_libro(Wx, Rx, rbx, cap, None, None, None, FEE_LEG_MODELLO)
|
||||
|
||||
Reference in New Issue
Block a user