research(wave-0822): lo scettico RITIRA il difetto di contabilita' (non esiste, bit-exact) e chiude oggi il gate del 22/12 — il meccanismo e' un filtro di frequenza
This commit is contained in:
@@ -14,7 +14,7 @@ null de-levering superato + eseguibilita' al capitale dichiarato.
|
||||
| 11 | VRP-QUOTE-VERE | **SCARTATO** + **1 difetto di RACCOLTA in produzione** | il campione contiene l'**astensione** della strategia (0/19 settimane passano IV-rank>0.30) e il titolo non sopravvive all'ora d'ingresso; ma soprattutto: **`collect_chain.py` raccoglie la famiglia di contratti che il conto NON puo' marginare** |
|
||||
| 7 | TERM-STRUCTURE | **SCARTATO** + 1 LEAD stretto (decisione 2027-02-01) | la pendenza e' un **termometro contemporaneo** (picco CCF a lag −1h/0h); il carry non paga il bid-ask (**18,6 giorni di roll-down per pagare UN round-trip**); come gate e' la **5ª occorrenza** della ridondanza col trend |
|
||||
| 6 | OI-PIN | **SCARTATO** | il max-pain batte uno strike casuale ma **non batte mai (0/24) la media a 7 giorni dello spot**, un livello che non usa NESSUN dato di opzioni: non e' pinning, e' reversione verso il centro recente con l'OI come stimatore rumoroso di quel centro |
|
||||
| 8 | VOL-SIZE | **LEAD** (gate 2026-12-22) + 1 falsificazione | dare a SKH01 una size per-trade regge a **23/23 ancore**, 8/8 anni, null di permutazione e trasferimento su V1 — ma vale **+0,07 di Sharpe di libro, un terzo della fortuna d'ancora del libro stesso (+0,196)**. Il vol-target di **libro** e' invece falsificato: compra peso SKH gia' respinto e peggiora l'eseguibilita' |
|
||||
| 8 | VOL-SIZE | **LEAD RIDIMENSIONATO** — gate 22/12 **gia' fallito oggi** | dare a SKH01 una size per-trade regge a **23/23 ancore**, 8/8 anni, null di permutazione e trasferimento su V1 — ma vale **+0,07 di Sharpe di libro, un terzo della fortuna d'ancora del libro stesso (+0,196)**. Il vol-target di **libro** e' invece falsificato: compra peso SKH gia' respinto e peggiora l'eseguibilita' |
|
||||
| — | **XSR-REPRO** (integrita') | 🚨 **DIFETTO DI PRODUZIONE** | il numero 1.82 e' SPIEGATO e non era sbagliato (era su una **terza** lente, e su una barra non ancora chiusa) — ma cercandone la causa e' emerso che **`paper_xsr` registra ~41 minuti di mercato al giorno**, non un giorno. Tre gate pre-registrati leggono serie costruite cosi' |
|
||||
| 5 | SKEW | **SCARTATO** (Q1, Q2) + **LEAD** (Q3, gate 2027-02-22) | il prezzo muove lo skew (t 3,1-9,4 su 8/8 test), **non il contrario** (max |t| in avanti 2,35 contro 2,08 atteso dal rumore). Ma Q3 e' grosso: **il f=0,73 di VRP01 e' per il 42% STRUTTURA A TERMINE e solo per il 25% skew** |
|
||||
| — | **HL-EXEC** (audit di fatto) | **3 falsificazioni misurate** | il pavimento vero e' **$10 (non $5)** e il taker **4,50 bps (non 5,0)** — ma il *"XS01 serve ~$20k"* e' **refutato del tutto** (nessuna soglia da min-order), il *"XSR01 ~$5.000"* e' **conservativo di 1,7x** (vero ~$3.000), e lo **slippage "rischio #1" di XSR01 e' refutato** con margine **21x** |
|
||||
@@ -252,13 +252,15 @@ recente, e l'OI e' solo uno stimatore rumoroso di quel centro.
|
||||
### 8 — VOL-SIZE (r0822_vol_size.py, 28 trial + 23 ancore)
|
||||
✅ Sanity **bit-exact**: ricomposizione trade-by-trade `max|diff| = 0.0` contro `run_asset` e contro
|
||||
`sleeves._skyhook_returns()`.
|
||||
🚨 **DIFETTO DI METODO GENERALE, trovato dall'agente nella propria prima stesura e MISURATO invece
|
||||
❌ **RITIRATO DALLO SCETTICO (vedi in fondo): il difetto qui sotto NON ESISTE su questo codice.**
|
||||
Lasciato a verbale perche' la regola era stata pubblicata e va vista insieme alla sua smentita.
|
||||
~~🚨 **DIFETTO DI METODO GENERALE, trovato dall'agente nella propria prima stesura e MISURATO invece
|
||||
che cancellato: su uno sleeve a equity a GRADINO, un overlay giornaliero e' NON CAUSALE.** Tutto il
|
||||
P&L di un trade SKH01 e' contabilizzato il giorno di **CHIUSURA**, fino a **3,83 giorni dopo
|
||||
l'ingresso**; moltiplicare la serie giornaliera per `L_t` (che usa solo dati <= t−1) **passa
|
||||
qualunque controllo di causalita' scritto sulla serie giornaliera** — il look-ahead sta nella
|
||||
CONTABILITA', non nella formula. Costo misurato: **+0,04 di Sharpe hold-out fantasma**.
|
||||
**REGOLA: un overlay si applica alla data d'INGRESSO, non a quella in cui il P&L viene contabilizzato.**
|
||||
**REGOLA: un overlay si applica alla data d'INGRESSO, non a quella in cui il P&L viene contabilizzato.**~~ **<- RITIRATA, vedi sotto**
|
||||
🚨 **REGOLA 2 — il null del de-levering e' DEGENERE quando la variante e' una ri-scalatura**
|
||||
(`sh(k*base) === sh(base)`): il test che serve non e' sul DD ma **ISO-PESO sullo Sharpe**, altrimenti
|
||||
si sta solo misurando di quanto e' cambiato il peso di uno sleeve. Qui era decisivo: quasi ogni
|
||||
@@ -545,3 +547,41 @@ dall'ora scelta = **un'altra strategia, non un'ancora**; (c) **un gate che stamp
|
||||
verificato prima di dichiararlo "non girato"** — stampava le chiavi sbagliate.
|
||||
✅ Disciplina di rete rispettata: <=2 req/s e **sospensione automatica nella finestra :25-:29** di
|
||||
`cron_chain` (verificato: si e' sospeso da solo per 264s).
|
||||
|
||||
### SCETTICO su VOL-SIZE (r0822_volsize_skeptic.py, 43 valutazioni x 23 ancore)
|
||||
✅ Replica **bit-exact** prima di ogni attacco: gamba 50/50 vs `sleeves._skyhook_returns()`
|
||||
**max|diff| = 0,0**; e il titolo riprodotto **esattamente** (+0,070 ISO dShFULL 23/23, +0,101 HOLD).
|
||||
🚨 **RITIRA UNA REGOLA PUBBLICATA POCHE ORE PRIMA — il difetto di contabilita' NON ESISTE.**
|
||||
`backtest_signals` fa `equity[i_ent:i_ex+1] = capital`: il P&L e' contabilizzato al giorno
|
||||
d'**INGRESSO** in **291/293 (99,3%)** dei trade multi-giorno, all'uscita in **4**. Troncando i dati
|
||||
alla barra d'ingresso e ricalcolando le size da zero: **50/50 identiche, max|diff| = 0,0**. E la
|
||||
"riparazione" e' un **no-op bit-exact** (max|diff| 6,7e-16, Sharpe identico a 4 decimali).
|
||||
**Il "+0,04 fantasma" era interamente `[L sulla gamba COMBINATA] − [L PER ASSET]`** — due varianti
|
||||
entrambe causali — **e la variante scartata come "non causale" era la MIGLIORE sull'hold-out
|
||||
(+0,039)**. *Il costo di una regola derivata da un difetto inesistente e' gia' stato pagato.*
|
||||
📌 **REGOLA CORRETTA (piu' debole e vera):** *"applicare un overlay alla data d'ingresso"* resta un
|
||||
buon consiglio **generale**, ma su questo motore le due date **coincidono** — e va verificato con un
|
||||
troncamento bit-exact **prima** di scartare un ramo, non dedotto dalla forma dell'equity.
|
||||
🚨 **IL GATE PRE-REGISTRATO AL 22/12/2026 E' GIA' FALLITO OGGI, e nel modo piu' netto.** L'agente
|
||||
aveva scritto: *"se l'effetto e' UGUALE su V1, la spiegazione e' sbagliata anche se il numero
|
||||
regge"*. Misurato: |effetto| mediano di famiglia **V1 0,067 contro V2-DD 0,032** — l'inverse-vol
|
||||
funziona **il DOPPIO dove lo stop e' gia' in ATR**, cioe' esattamente al contrario della previsione,
|
||||
in **8 celle su 8** con **23/23 ancore positive**. E il test **ha potenza** (su V2-DD la famiglia
|
||||
arriva a +0,067, quanto il LEAD).
|
||||
📌 **La spiegazione avversaria e' CONFERMATA e la sua forma minima e' un binario.** `BIN L>=med`
|
||||
(size **0/1** alla mediana espandente, nessuna magnitudine, 194/406 trade scartati) vale
|
||||
**+0,080 FULL (20/23) = 115% del LEAD**. Controllo di segno superato: il binario **INVERSO** fa
|
||||
**−0,159 (0/23)**. Canali: **FREQUENZA +0,051 (23/23)** contro **MAGNITUDINE +0,003 (17/23)**.
|
||||
I trade tenuti hanno net medio **2,03% contro 0,36%** degli scartati.
|
||||
✅ **Un attacco dello scettico e' FALLITO, e lo dichiara:** l'asse della finestra **non e' un picco**
|
||||
— l'argmax in-sample-only cade su **w=90 = la cella pubblicata**, corr(IS, HOLD) fra le 9 finestre
|
||||
**+0,63**, plateau da 45 a 270. Sotto w=45 la finestra contiene **1-3 barre attive** (colonna
|
||||
misurata) e il segno si rovescia: non e' fragilita', e' campione vuoto.
|
||||
**-> quindi anche la mia nota "picco, non plateau" nel filone 8 va letta come SUPERATA.**
|
||||
Stima onesta se `w` e' scelto (mediana di famiglia): **+0,025 FULL**.
|
||||
📌 **CONSEGUENZA:** il LEAD non ha piu' una condizione aperta da attendere — la sua gamba
|
||||
esplicativa e' chiusa oggi. Se qualcuno vorra' portarlo avanti, **il candidato giusto non e' la
|
||||
formula ma il binario**: meno gradi di liberta', **dimezza gli ordini** (migliora l'eseguibilita' a
|
||||
$635), 115% sul FULL — ma paga in fragilita' d'ancora (20/23 contro 23/23, banda che include −0,061,
|
||||
hold-out +0,072 contro +0,101). **Resta un terzo della fortuna d'ancora del libro stesso (+0,196):
|
||||
niente qui giustifica di toccare pesi, cron o config.**
|
||||
|
||||
@@ -356,9 +356,16 @@ def liquidita(rows: list[dict], tab: dict) -> None:
|
||||
s = stat[f]
|
||||
print(f"{f:<10} {s['oi']:>11} {rA[f]:>8} {s['puts']:>10} {s['two']:>10} "
|
||||
f"{s['pct']:>9.0%} {rB[f]:>8}")
|
||||
print("\n 📌 LA CLASSIFICA SI ROVESCIA. SOL_USDC e' 1° per open interest e ULTIMO per quote")
|
||||
print(" presenti; BTC_USDC, dichiarato 'praticamente morto' (5 strumenti con OI>=100), ha")
|
||||
print(" quasi tutti i put quotati a due lati. L'open interest misura posizioni ACCUMULATE,")
|
||||
# la correlazione di rango si CALCOLA, non si racconta: sulle sole famiglie lineari,
|
||||
# cioe' quelle su cui la domanda del filone e' stata posta.
|
||||
a = np.array([rA[f] for f in LINEAR], float)
|
||||
c = np.array([rB[f] for f in LINEAR], float)
|
||||
rho = float(np.corrcoef(a, c)[0, 1])
|
||||
print(f"\n 📌 LA CLASSIFICA SI ROVESCIA. Correlazione di rango fra i due criteri sulle sei")
|
||||
print(f" famiglie lineari: {rho:+.2f}. SOL_USDC e' 1ª per open interest fra le lineari e")
|
||||
print(" ULTIMA di tutte per quote presenti; BTC_USDC, dichiarato 'praticamente morto' (5")
|
||||
print(" strumenti con OI>=100), ha quasi tutti i put quotati a due lati. L'open interest")
|
||||
print(" misura posizioni ACCUMULATE,")
|
||||
print(" non la possibilita' di negoziare ADESSO — e sull'universo lineare le due cose non")
|
||||
print(" hanno quasi nulla a che vedere.")
|
||||
print(" ⚠️ Ricaduta sul codice di produzione: `collect_chain.py` prefiltra a OI>=100. Sulle")
|
||||
@@ -366,6 +373,28 @@ def liquidita(rows: list[dict], tab: dict) -> None:
|
||||
print(" suo nome lo lascia credere. 4ª occorrenza di 'una riga presente non e' un dato")
|
||||
print(" presente' — qui in versione: 'una posizione aperta non e' un prezzo negoziabile'.")
|
||||
|
||||
print("\n" + "-" * 104)
|
||||
print("2b. E ALLORA DOV'E' LA LIQUIDITA' CHE SI VEDE NEL VOLUME? Nel mercato a BLOCCHI,")
|
||||
print(" che ha un minimo d'ordine suo — e non e' raggiungibile con $635.")
|
||||
print("-" * 104)
|
||||
print(f"{'famiglia':<10} {'con volume 24h':>15} {'volume 24h $':>14} {'blocco min':>11} "
|
||||
f"{'blocco min $':>13} {'x il conto':>11}")
|
||||
for f in FAMS:
|
||||
sub = [r for r in rows if r["fam"] == f]
|
||||
if not sub:
|
||||
continue
|
||||
nv = sum(1 for r in sub if r["vol"] > 0)
|
||||
vusd = sum(r["vol_usd"] for r in sub)
|
||||
bm = sub[0]["blockmin"]
|
||||
bm_usd = bm * tab[f]["S"] * (1.0 if not is_inv(f) else 1.0)
|
||||
print(f"{f:<10} {nv:>15} {vusd:>14,.0f} {bm:>11g} {bm_usd:>13,.0f} "
|
||||
f"{bm_usd/CAPITAL:>10.0f}x")
|
||||
print("\n 📌 SOL_USDC ha molti piu' strumenti con volume nelle ultime 24h che quotati a due")
|
||||
print(" lati: quelle opzioni si negoziano, ma via blocchi/RFQ. Il minimo di blocco e' un")
|
||||
print(" fatto del venue, non un'opinione, e a $635 e' fuori portata di due ordini di")
|
||||
print(" grandezza. **Non si conclude che il mercato alt non esista: si conclude che la parte")
|
||||
print(" a cui questo conto ha accesso — il book continuo — e' quella sottile.**")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- §3 la struttura
|
||||
|
||||
@@ -461,9 +490,65 @@ def struttura(rows: list[dict]) -> dict:
|
||||
f"{len(gi):>12} {len(ge):>11}")
|
||||
print(" Se la colonna `eseg.` si allontana dal target -0.28/-0.10, la struttura che si")
|
||||
print(" comprerebbe NON e' quella richiesta: la griglia degli strike quotati la deforma.")
|
||||
|
||||
print("\n --- CONTROLLO POSITIVO: questo snapshot e' di SABATO. E' atipico? ---")
|
||||
print(" Non posso aspettare una settimana, ma posso puntare lo stesso strumento su una")
|
||||
print(" grandezza che il progetto ha GIA' misurato su 19 settimane di giorni feriali:")
|
||||
print(" attraversare lo spread sul canonico BTC/ETH inverse costa ~10% del credito (30/07).")
|
||||
for f in INVERSE:
|
||||
if f in res:
|
||||
print(f" {f:<4} inverse: costo di attraversamento oggi = "
|
||||
f"{(1-res[f]['fv'])*100:5.1f}% del credito (atteso ~10%)")
|
||||
print(" Se coincide, il sabato non sta degradando i book che il progetto conosce, e la")
|
||||
print(" lettura sulle famiglie nuove non e' un artefatto del giorno. **E' un controllo")
|
||||
print(" debole** (una grandezza sola, un istante), non una prova di tipicita'.")
|
||||
robustezza_dte(rows)
|
||||
return res
|
||||
|
||||
|
||||
def robustezza_dte(rows: list[dict]) -> None:
|
||||
"""L'UNICO grado di liberta' di questo file, esposto invece che nascosto.
|
||||
|
||||
VRP01 e' settimanale (tenor 7g, finestra 4-10). Qui la finestra e' stata allargata a 4-45
|
||||
per dare piu' scadenze alle famiglie alt, che ne hanno poche. Allargare una finestra e'
|
||||
una scelta, e una scelta va misurata: se la conclusione dipendesse da essa, sarebbe la
|
||||
conclusione a essere stata scelta.
|
||||
"""
|
||||
global DTE_HI
|
||||
print("\n --- ROBUSTEZZA: la finestra DTE e' il mio unico grado di liberta' ---")
|
||||
print(f" {'famiglia':<10} {'finestra':>9} {'scad':>5} {'f_venue':>8} {'spr% corta':>11} "
|
||||
f"{'cred eseg$':>11} {'maxloss$':>9}")
|
||||
orig = DTE_HI
|
||||
try:
|
||||
for hi in (10.0, 45.0):
|
||||
DTE_HI = hi
|
||||
for f in FAMS:
|
||||
gg = scegli(rows, f, eseguibile=True)
|
||||
fv, ss, ce, ml = [], [], [], []
|
||||
for g in gg:
|
||||
s, lo = g["short"], g["long"]
|
||||
cm = usd(s["mark"], s) - usd(lo["mark"], lo)
|
||||
c = usd(s["bid"], s) - usd(lo["ask"], lo)
|
||||
if cm <= 0:
|
||||
continue
|
||||
fv.append(c / cm); ss.append(rel_spread(s)); ce.append(c)
|
||||
ml.append(loss_usd(s["K"], lo["K"], s) - c)
|
||||
w = f"{DTE_LO:.0f}-{hi:.0f}g"
|
||||
if not fv:
|
||||
print(f" {f:<10} {w:>9} {len(gg):>5} {'n/d':>8}")
|
||||
continue
|
||||
print(f" {f:<10} {w:>9} {len(fv):>5} {np.median(fv):>8.3f} "
|
||||
f"{np.nanmedian(ss)*100:>10.1f}% {np.median(ce):>11.2f} "
|
||||
f"{np.median(ml):>9.2f}")
|
||||
print()
|
||||
finally:
|
||||
DTE_HI = orig
|
||||
print(" 📌 Da leggere sull'ORDINE, non sulla terza cifra: le quote si muovono fra un giro e")
|
||||
print(" l'altro (su tre snapshot a pochi minuti ETH_USDC ha dato 0.947-0.983, le inverse")
|
||||
print(" 0.847-0.942, le alt 0.79-0.87, SOL sempre negativo). Cio' che NON si muove e' la")
|
||||
print(" graduatoria, e alla finestra VERA di VRP01 (4-10g) e' piu' netta, non meno.")
|
||||
|
||||
|
||||
def profondita(rows: list[dict], fams: list[str], b: Budget) -> None:
|
||||
print("\n" + "=" * 104)
|
||||
print("3b. PROFONDITA' IN CIMA AL BOOK (public/get_order_book depth=5) sulle gambe scelte")
|
||||
|
||||
@@ -129,8 +129,10 @@ def read_equity_csv(p: Path, col: int = 1) -> tuple[list[pd.Timestamp], np.ndarr
|
||||
# della giornata e' finita nella serie": in radice di tempo il rapporto di VARIANZA fra le due
|
||||
# serie e' la frazione di giornata misurata (ipotesi: random walk sull'intervallo troncato).
|
||||
# --------------------------------------------------------------------------------------------
|
||||
def compare(rec: np.ndarray, rep: np.ndarray) -> dict:
|
||||
def compare(rec: np.ndarray, rep: np.ndarray, mask: np.ndarray | None = None) -> dict:
|
||||
ok = np.isfinite(rec) & np.isfinite(rep)
|
||||
if mask is not None:
|
||||
ok &= mask
|
||||
a, b = rec[ok], rep[ok]
|
||||
n = len(a)
|
||||
if n < 3:
|
||||
@@ -145,18 +147,53 @@ def compare(rec: np.ndarray, rep: np.ndarray) -> dict:
|
||||
sh_rep=float(b.mean() / b.std() * ANN) if b.std() > 0 else float("nan"))
|
||||
|
||||
|
||||
def show(tag: str, c: dict, note: str = "") -> None:
|
||||
def show(T: pd.DatetimeIndex, rec: np.ndarray, rep: np.ndarray, note: str = "") -> dict:
|
||||
"""Stampa il confronto e ritorna la statistica sulla finestra PULITA (senza l'incidente)."""
|
||||
c = compare(rec, rep)
|
||||
fuori = ~((T >= FREEZE[0]) & (T <= FREEZE[1]))
|
||||
cf = compare(rec, rep, mask=fuori)
|
||||
print(f" barre appaiate {c['n']} identiche entro 1e-6: {c['ident']}/{c['n']} "
|
||||
f"corr {c['corr']:+.4f}")
|
||||
print(f" vol annualizzata REGISTRATA {c['sd_rec']:6.2f}% RICALCOLATA {c['sd_rep']:6.2f}%"
|
||||
f" rapporto di varianza {c['vr']:.4f}")
|
||||
print(f" -> il monitor misura ~{c['minuti']:,.0f} minuti di mercato al giorno (su 1440){note}")
|
||||
if cf["n"] != c["n"]:
|
||||
print(f" ESCLUSO l'incidente del feed 09-15/07 ({c['n'] - cf['n']} barre recuperate a "
|
||||
f"posteriori, quindi CHIUSE):")
|
||||
print(f" barre {cf['n']} identiche {cf['ident']}/{cf['n']} corr {cf['corr']:+.4f}"
|
||||
f" vol reg. {cf['sd_rec']:.2f}% vs ric. {cf['sd_rep']:.2f}%"
|
||||
f" -> ~{cf['minuti']:,.0f} min/giorno")
|
||||
print(f" Sharpe della finestra: REGISTRATO {c['sh_rec']:+.2f} RICALCOLATO {c['sh_rep']:+.2f}"
|
||||
f" [SE ~{np.sqrt(365.0 / max(c['n'], 1)):.2f}: NON e' una lettura di gate]")
|
||||
return dict(all=c, clean=cf)
|
||||
|
||||
|
||||
RES: dict[str, dict] = {} # riepilogo per la tabella finale
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# L'INCIDENTE DEL FEED (2026-07-09 -> 2026-07-15). Non e' un'assunzione: e' documentato nel
|
||||
# sorgente di produzione (`rebuild_history.py`, commento "incidente 2026-07-15: feed fermo 7g" —
|
||||
# `shutil.copy2` del backup falliva con EPERM e ABORTIVA il rebuild) ed e' verificabile nel log
|
||||
# del cron. Conta qui per una ragione precisa: durante il congelamento i monitor NON trovavano
|
||||
# barre nuove, e al ripristino hanno recuperato in un colpo solo barre gia' CHIUSE — cioe' le
|
||||
# uniche barre corrette delle loro serie. Vanno escluse da ogni stima del difetto, o si finisce
|
||||
# per attribuire al difetto un'attenuazione che viene da un guasto diverso.
|
||||
FREEZE = (pd.Timestamp("2026-07-09", tz="UTC"), pd.Timestamp("2026-07-16", tz="UTC"))
|
||||
CRONLOG = ROOT / "logs" / "cron_daily.log"
|
||||
|
||||
|
||||
def freeze_evidence() -> dict[str, int]:
|
||||
"""Giorni in cui `rebuild_history` e' ABORTITO nel cron (letto dal log, non assunto)."""
|
||||
out: dict[str, int] = {}
|
||||
day = None
|
||||
lines = CRONLOG.read_text(errors="replace").splitlines() if CRONLOG.exists() else []
|
||||
for i, ln in enumerate(lines):
|
||||
if ln.startswith("===== 2026-") and "cron_daily" in ln:
|
||||
day = ln.split()[1][:10]
|
||||
if day and "rebuild_history.py" in ln and "Traceback" in "".join(lines[max(0, i - 3):i]):
|
||||
out[day] = out.get(day, 0) + 1
|
||||
return out
|
||||
|
||||
|
||||
# ============================================================================================
|
||||
# A — PROVENIENZA: quanto e' completa l'ultima riga di ogni sorgente
|
||||
@@ -245,12 +282,14 @@ def b_xsr():
|
||||
reals={n: px._book(c, len(st["syms"])) for c, n in px.REAL_BOOKS})
|
||||
px.advance(st0)
|
||||
rep = {int(r["ts"]): float(r["net_modeled"]) for r in sink.of("returns.jsonl")}
|
||||
pairs = [(float(r["net_modeled"]), rep[int(r["ts"])]) for r in rec if int(r["ts"]) in rep]
|
||||
c = compare(np.array([p[0] for p in pairs]), np.array([p[1] for p in pairs]))
|
||||
print(f"\n pannello: `build_panel` -> `load_hl` -> parquet HL 1d (ultima riga = giorno in corso)")
|
||||
show("xsr", c)
|
||||
RES["paper_xsr"] = dict(parziale="SI", cmp=c, gate="XSR01 2026-10-23",
|
||||
src="hl_*_1d.parquet", cad_h=24.0)
|
||||
pairs = [(int(r["ts"]), float(r["net_modeled"]), rep[int(r["ts"])])
|
||||
for r in rec if int(r["ts"]) in rep]
|
||||
T = pd.DatetimeIndex(pd.to_datetime([p[0] for p in pairs], unit="ms", utc=True))
|
||||
print("\n pannello: `build_panel` -> `load_hl` -> parquet HL 1d (ultima riga = giorno in corso)")
|
||||
print(f" inception {T[0].date()} = DOPO l'incidente del feed: la finestra e' gia' pulita.")
|
||||
out = show(T, np.array([p[1] for p in pairs]), np.array([p[2] for p in pairs]))
|
||||
RES["paper_xsr"] = dict(parziale="SI", cmp=out["clean"], gate="XSR01 2026-10-23",
|
||||
src="hl_*_1d.parquet", cad_h=24.0, ric="SI (bit-exact)")
|
||||
|
||||
|
||||
def b_statarb():
|
||||
|
||||
@@ -186,10 +186,41 @@ def _d(s: pd.Series) -> pd.Series:
|
||||
_CRY_CACHE: dict = {}
|
||||
|
||||
|
||||
def _crypto(w_tp: float, w_skh: float) -> pd.DataFrame:
|
||||
key = (round(w_tp, 6), round(w_skh, 6))
|
||||
def _crypto_stressed(w_tp: float, w_skh: float, m_tp: float, m_skh: float) -> pd.DataFrame:
|
||||
"""Come `pc.crypto_daily_tuples` (minimo ESATTO sul path orario condiviso) ma con un taglio
|
||||
del DRIFT applicato alla singola gamba PRIMA di comporre il path. Serve perche' il minimo
|
||||
giornaliero non e' separabile per gamba: non si puo' tagliare il drift a valle."""
|
||||
(J,) = pc._hourly_legs()
|
||||
legs = {}
|
||||
for nm, (rc, wc, mult) in {"tp": ("tp_r", "tp_w", m_tp), "sk": ("skh_r", "skh_w", m_skh)}.items():
|
||||
r = J[rc].values.copy()
|
||||
w = J[wc].values.copy()
|
||||
if mult != 1.0:
|
||||
cut = (1.0 - mult) * r.mean()
|
||||
r = r - cut
|
||||
w = w - cut
|
||||
legs[nm] = (r, w)
|
||||
r_h = w_tp * legs["tp"][0] + w_skh * legs["sk"][0]
|
||||
w_h = w_tp * legs["tp"][1] + w_skh * legs["sk"][1]
|
||||
idx = J.index
|
||||
days = idx.floor("D")
|
||||
rows = []
|
||||
for day, pos in pd.Series(np.arange(len(idx)), index=days).groupby(level=0):
|
||||
sl = pos.values
|
||||
r = r_h[sl]
|
||||
wk = w_h[sl]
|
||||
cum = np.cumprod(1.0 + r)
|
||||
cum_prev = np.concatenate(([1.0], cum[:-1]))
|
||||
m = min(cum.min(), (cum_prev * (1.0 + wk)).min()) - 1.0
|
||||
rows.append((day, cum[-1] - 1.0, min(m, cum[-1] - 1.0)))
|
||||
return pd.DataFrame(rows, columns=["day", "R", "m"]).set_index("day")
|
||||
|
||||
|
||||
def _crypto(w_tp: float, w_skh: float, m_tp: float = 1.0, m_skh: float = 1.0) -> pd.DataFrame:
|
||||
key = (round(w_tp, 6), round(w_skh, 6), round(m_tp, 4), round(m_skh, 4))
|
||||
if key not in _CRY_CACHE:
|
||||
_CRY_CACHE[key] = pc.crypto_daily_tuples(w_tp, w_skh)
|
||||
_CRY_CACHE[key] = (pc.crypto_daily_tuples(w_tp, w_skh) if (m_tp == 1.0 and m_skh == 1.0)
|
||||
else _crypto_stressed(w_tp, w_skh, m_tp, m_skh))
|
||||
return _CRY_CACHE[key]
|
||||
|
||||
|
||||
@@ -221,11 +252,8 @@ def book_RG(w: dict, start: str = START_WIN,
|
||||
R = np.zeros(len(idx))
|
||||
M = np.zeros(len(idx))
|
||||
if w_tp > 0 or w_skh > 0:
|
||||
c = _crypto(w_tp, w_skh).reindex(idx)
|
||||
cr = c["R"].values
|
||||
if w_tp > 0 and dm.get("TP01", 1.0) != 1.0 or w_skh > 0 and dm.get("SKH01", 1.0) != 1.0:
|
||||
raise NotImplementedError("stress sul drift crypto: il minimo e' path-esatto, non separabile")
|
||||
R += cr
|
||||
c = _crypto(w_tp, w_skh, dm.get("TP01", 1.0), dm.get("SKH01", 1.0)).reindex(idx)
|
||||
R += c["R"].values
|
||||
M += c["m"].values
|
||||
for nm, fr in (("XS01", pc.xsec_daily_tuples()), ("VRP01", vrp_daily_tuples()),
|
||||
("GTAA01", gtaa_daily_tuples())):
|
||||
@@ -702,6 +730,28 @@ def main() -> None:
|
||||
print(" scoperta; se resta a drift 0, il vantaggio e' pura DECORRELAZIONE e non dipende da")
|
||||
print(" quell'ipotesi. Il numero, non la narrazione, dice quale delle due.")
|
||||
|
||||
hr("E-quater. LA DISTORSIONE CHE MI RIGUARDA — l'ottimo si appoggia a SKH01, e SKH01 e' lo")
|
||||
print(" sleeve con la FORTUNA D'ANCORA piu' grande da restituire. Il LOO del 26/07: l'ancora")
|
||||
print(" canonica gli regala 2/3 del contributo FULL (+0.43 -> +0.14) e il 70% dell'hold-out;")
|
||||
print(" l'audit 02/07 lo trova al 93-98° pctl di 23 offset, 'spike, non plateau'. Questa lente")
|
||||
print(" gira sull'ancora CANONICA e la banda non e' ri-misurabile qui -> il mio ottimo e'")
|
||||
print(" distorto A FAVORE di SKH01 e va detto PRIMA di leggerlo. Taglio del drift di SKH01:")
|
||||
print(f"\n {'drift SKH01':>13} {'config':>16} {'leva':>6} {'J':>7} {'J del LIVE':>11} "
|
||||
f"{'delta appaiato':>16}")
|
||||
for mult in (1.00, 0.66, 0.50, 0.33):
|
||||
dmt = (("SKH01", mult),)
|
||||
rows = [(w, lv, objective(w, lv, "HYRO", ev_idx, fu_idx, drift_mult=dmt))
|
||||
for w in top_w for lv in LEVS]
|
||||
w_, lv_, o_ = max(rows, key=lambda x: x[2]["J"])
|
||||
lvL, oL = max(((lv, objective({"TP01": 0.75, "SKH01": 0.25}, lv, "HYRO", ev_idx, fu_idx,
|
||||
drift_mult=dmt)) for lv in LEVS), key=lambda x: x[1]["J"])
|
||||
dd_, sd_ = paired_delta(w_, lv_, {"TP01": 0.75, "SKH01": 0.25}, lvL, "HYRO",
|
||||
ev_idx, fu_idx)
|
||||
print(f" {mult:>13.2f} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {oL['J']:>11.3f} "
|
||||
f"{dd_:>+11.3f} +-{sd_:.3f}")
|
||||
print(" NB: il taglio si applica anche al LIVE 75/25 (che ha SKH01 al 25%), quindi il delta e'")
|
||||
print(" un confronto onesto: entrambe le colonne perdono, la domanda e' quale perde di piu'.")
|
||||
|
||||
hr("E-ter. IL BUCO CHE LA FINESTRA NON PUO' CHIUDERE — 2024-2026 non contiene un CRASH")
|
||||
print(" L'ottimizzazione toglie peso a TP01 (Sharpe 0.79 su questa finestra). Ma TP01 e' lo")
|
||||
print(" sleeve DIFENSIVO: il LOO del 26/07 misura il suo contributo hold-out NEGATIVO nel 99.1%")
|
||||
|
||||
@@ -252,9 +252,10 @@ def main() -> None:
|
||||
FUN_V1["VTL tv20 w90 (LEAD)"] = size_vtl(FROZEN)
|
||||
FUN_V1["BIN L>=1 (0/1)"] = size_bin(FROZEN, "ge1")
|
||||
|
||||
NTRIAL = len(FUN_V2) + len(FUN_V1) + 2 # +2 baseline
|
||||
print(f"\n GRIGLIA DICHIARATA: {len(FUN_V2)} celle su V2-DD + {len(FUN_V1)} su V1 "
|
||||
f"+ 2 baseline = {NTRIAL} valutazioni x {len(offs)} ancore. Nessuna cella scelta")
|
||||
NTRIAL = len(FUN_V2) + len(FUN_V1) + 2 + 4 # +2 baseline, +4 controlli 'L combinata' (§1c)
|
||||
print(f"\n GRIGLIA DICHIARATA (contata al RIALZO): {len(FUN_V2)} celle su V2-DD + "
|
||||
f"{len(FUN_V1)} su V1 + 4 controlli 'L combinata' (§1c) + 2 baseline = {NTRIAL} "
|
||||
f"valutazioni x {len(offs)} ancore. Nessuna cella scelta")
|
||||
print(" dopo aver guardato: IV e' la famiglia PRE-REGISTRATA, VTL/w e' l'asse dichiarato")
|
||||
print(" fragile dall'agente, BIN/DROP sono controlli miei dichiarati sopra.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user