research(wave-0822): GROWTH-POLICY — il libro gira al 7% di Kelly, e ogni gate del progetto e' cieco alla scala
This commit is contained in:
@@ -254,7 +254,8 @@ def sezione2(snap: pd.DataFrame) -> pd.DataFrame:
|
||||
g["p_x24"] = [bboot_p(d[d.odec == k].x24.values, block=48) for k in g.index]
|
||||
print(g.round(3).to_string())
|
||||
print(" av4/av24 = |ret| futuro medio: e' la gamba 'squeeze/cascata' dell'ipotesi")
|
||||
print(" (piu' vol dopo un estremo di OI). E' PIATTA: nessuna cascata prevedibile.")
|
||||
print(" (piu' vol dopo un estremo di OI). E' QUASI PIATTA (0.59-0.75%% a 4h, solo il decile 0")
|
||||
print(" leggermente sopra): la 'cascata' prevedibile non c'e'.")
|
||||
|
||||
print("\n--- CONTROLLO: e' solo 'il prezzo si e' appena mosso'? ---")
|
||||
z = lambda s: (s - s.mean()) / s.std() # noqa: E731
|
||||
@@ -293,9 +294,25 @@ def sezione2(snap: pd.DataFrame) -> pd.DataFrame:
|
||||
for a in ASSETS:
|
||||
sub = d[(d.asset == a) & (d.odec == 0)]
|
||||
cond = (d[d.asset == a].odec == 0).values
|
||||
ep = int(np.sum(cond[1:] & ~cond[:-1])) + int(cond[0])
|
||||
print(f" {a}: ore in decile0={len(sub)} episodi distinti={ep} "
|
||||
# AMPIEZZA EFFETTIVA: il numero di ORE non e' la taglia campionaria se la
|
||||
# condizione e' fatta di pochi episodi lunghi (lezione del filone gemello
|
||||
# dealer-gamma della stessa ondata: 73 "episodi" di cui 6-8 all'80% del tempo).
|
||||
lens, cur = [], 0
|
||||
for v in cond:
|
||||
if v:
|
||||
cur += 1
|
||||
elif cur:
|
||||
lens.append(cur); cur = 0
|
||||
if cur:
|
||||
lens.append(cur)
|
||||
L = np.array(sorted(lens)[::-1])
|
||||
print(f" {a}: ore in decile0={len(sub)} episodi distinti={len(L)} "
|
||||
f"durata mediana={np.median(L):.1f}h max={L.max()}h "
|
||||
f"quota ore negli 8 episodi piu' lunghi={L[:8].sum()/L.sum():.2f} "
|
||||
f"y4={100*sub.y4.mean():+.3f}% y24={100*sub.y24.mean():+.3f}%")
|
||||
print(" -> QUI l'ampiezza NON e' la patologia: 86-87 episodi corti (mediana 2h) e i")
|
||||
print(" primi 8 coprono solo il 20-25% delle ore. Il vincolo binding e' la")
|
||||
print(" LUNGHEZZA DEL CALENDARIO (90 giorni), non la concentrazione degli episodi.")
|
||||
print("\n scomposizione PER MESE (demean mensile) — il test che il progetto impone")
|
||||
print(" dopo il caso SOL ('un contributo positivo si scompone prima di crederci'):")
|
||||
tab = d[d.odec == 0].groupby("mese")[["y4", "y24"]].agg(["size", "mean"])
|
||||
@@ -475,6 +492,9 @@ def sezione4(snap: pd.DataFrame) -> None:
|
||||
print(" -> il candidato NON e' la statica travestita: il timing porta qualcosa.")
|
||||
|
||||
print("\n--- NULL 2: timing CASUALE a pari esposizione (shift circolare, 300 estrazioni) ---")
|
||||
print(" e' il null LOCATION-MATCHED nella dimensione del tempo: stessa esposizione, stessa")
|
||||
print(" struttura di episodi, stessa finestra — cambia SOLO QUANDO. Un null piu' ingenuo")
|
||||
print(" (posizione casuale iid) direbbe di si' a qualunque cosa in una finestra con drift.")
|
||||
base_trig = {}
|
||||
for a in ASSETS:
|
||||
df = A.get(a, "1h")
|
||||
@@ -504,12 +524,19 @@ def sezione4(snap: pd.DataFrame) -> None:
|
||||
sr = float(cd.mean() / cd.std() * np.sqrt(365.25))
|
||||
rep = A.marginal_vs_tp01(cd)
|
||||
print(f" candidate_daily : n={len(cd)} giorni, Sharpe={sr:.2f}")
|
||||
n_hold = int((cd.index >= A.HOLDOUT).sum())
|
||||
print(f" marginal_vs_tp01 : verdetto={rep.get('marginal_verdict')} "
|
||||
f"corr_beta_tp01={rep.get('beta_to_tp01')} has_insample_edge={rep.get('has_insample_edge')} "
|
||||
f"beta_to_tp01={rep.get('beta_to_tp01')} has_insample_edge={rep.get('has_insample_edge')} "
|
||||
f"is_hedge={rep.get('is_hedge')} robust_oos={rep.get('robust_oos')} "
|
||||
f"beats_noise_null={rep.get('beats_noise_null')} null_pctl_full={rep.get('null_pctl_full')}")
|
||||
print(" (robust_oos=False non e' un difetto del candidato: con 90 giorni NON ESISTE il")
|
||||
print(" multi-cut che il gate richiede. Il gate e' girato e il suo esito e' NEUTRAL.)")
|
||||
print(f" ATTENZIONE: giorni totali={len(cd)}, giorni dopo HOLDOUT({A.HOLDOUT.date()})"
|
||||
f"={n_hold} -> COINCIDONO")
|
||||
print(f" (cand_full_sharpe={rep.get('cand_full_sharpe')} == "
|
||||
f"cand_hold_sharpe={rep.get('cand_hold_sharpe')}). Il candidato vive INTERAMENTE")
|
||||
print(" dentro l'hold-out del progetto: FULL e HOLD-OUT sono la STESSA finestra e la")
|
||||
print(" meta' out-of-sample del gate e' strutturalmente INERTE (robust_oos=False non")
|
||||
print(" giudica il candidato, dice che il multi-cut non esiste). Da leggere come")
|
||||
print(" 'girato ma NON informativo sull'OOS', non come un NEUTRAL guadagnato sul campo.")
|
||||
all_sr = list(R.sharpe.values)
|
||||
d18 = A.deflated_sharpe(sr, all_sr, cd)
|
||||
d_all = A.deflated_sharpe(sr, all_sr * 7, cd)
|
||||
@@ -628,8 +655,10 @@ def main() -> None:
|
||||
giugno -0.64%, luglio -0.74%): 2 mesi su 3 non sono un plateau, sono due mesi.
|
||||
3. IL SEGNALE E' UN MASSIMO DI 18 CELLE SU 114 GIORNI: Sharpe 3.6 con SE(Sharpe)=2.0,
|
||||
deflated-Sharpe 0.10 (18 celle) / 0.004 (118 trial) contro un massimo atteso PER CASO di
|
||||
Sharpe 5.4; implausible_sharpe=True; marginal_vs_tp01 = NEUTRAL; e il P&L e' per il 71%
|
||||
di giugno e per il 60% concentrato in 3 giorni su 114.
|
||||
Sharpe 5.4; implausible_sharpe=True; e il P&L e' per il 71% di giugno e per il 60%
|
||||
concentrato in 3 giorni su 114. marginal_vs_tp01 gira e dice NEUTRAL, ma va dichiarato
|
||||
NON INFORMATIVO SULL'OOS: il candidato sta interamente dopo HOLDOUT(2025-01-01), quindi
|
||||
full e hold-out sono la stessa finestra (Sharpe identico) e il multi-cut non esiste.
|
||||
4. ED E' COMUNQUE MORTO ALLA NASCITA: la colonna su cui poggia non e' ricostruibile con i dati
|
||||
che raccogliamo (l'OI della catena e' quello delle OPZIONI, rango ~0.05 con la colonna) e
|
||||
la sorgente e' stata dismessa il 2026-07-30.
|
||||
|
||||
Reference in New Issue
Block a user