research(wave-0822): MONITOR-AUDIT — 4 monitor su 6 rotti, il gate STATARB si ribalta, ma la finestra e' rigenerabile e nessuna data si sposta
This commit is contained in:
@@ -21,6 +21,7 @@ null de-levering superato + eseguibilita' al capitale dichiarato.
|
|||||||
| — | **SLIP-AUDIT** (audit di fatto) | **SCARTATO** = nessun costo nascosto a questa taglia | i backtest a 10 bps RT restano **conservativi di ~1,5 bps/lato**; nessuna evidenza di impatto sopravvive al null (p=0,274; estremi avversi **1/18 contro 4,7 attesi**). **Ma la misura ha una data di scadenza** |
|
| — | **SLIP-AUDIT** (audit di fatto) | **SCARTATO** = nessun costo nascosto a questa taglia | i backtest a 10 bps RT restano **conservativi di ~1,5 bps/lato**; nessuna evidenza di impatto sopravvive al null (p=0,274; estremi avversi **1/18 contro 4,7 attesi**). **Ma la misura ha una data di scadenza** |
|
||||||
| — | **SCETTICO su GROWTH-POLICY** | **REGGE** (condizione bloccante DECADUTA) | la lente wick accoppiata **non cambia il gradino**: e' un ricarico moltiplicativo **costante ~3,5%** sul maxDD, non un'amplificazione (Δ/k **cala**). Ma su una regola a **UN giorno** close-only e' **esattamente cieca** (rapporto INF) -> la lezione 25/07 e' vera e **non si trasferisce** |
|
| — | **SCETTICO su GROWTH-POLICY** | **REGGE** (condizione bloccante DECADUTA) | la lente wick accoppiata **non cambia il gradino**: e' un ricarico moltiplicativo **costante ~3,5%** sul maxDD, non un'amplificazione (Δ/k **cala**). Ma su una regola a **UN giorno** close-only e' **esattamente cieca** (rapporto INF) -> la lezione 25/07 e' vera e **non si trasferisce** |
|
||||||
| 13 | BASIS-CALENDAR | **SCARTATO** + **1 dataset nuovo** | il basis dei futures datati **E' il funding del perp quotato diversamente** (7,33% contro 6,48%/anno): non e' un quarto lato del filone funding, e' lo stesso lato. Premio incassabile **+0,85%/anno con IC95 che contiene lo zero** |
|
| 13 | BASIS-CALENDAR | **SCARTATO** + **1 dataset nuovo** | il basis dei futures datati **E' il funding del perp quotato diversamente** (7,33% contro 6,48%/anno): non e' un quarto lato del filone funding, e' lo stesso lato. Premio incassabile **+0,85%/anno con IC95 che contiene lo zero** |
|
||||||
|
| — | **MONITOR-AUDIT** (produzione) | 🚨 **4 monitor su 6 rotti**, ma **la finestra NON e' persa** | `paper_statarb` registra **4 minuti al giorno** e il suo gate del **27/09 si ribalta su 2 criteri su 3** (Sharpe registrato **+1,96** contro **−2,02** ricostruito). **La riparazione e' "riparare + RIGENERARE", non "riparare e azzerare": nessuna data di gate si sposta** |
|
||||||
|
|
||||||
## Note che sopravvivono ai singoli filoni
|
## Note che sopravvivono ai singoli filoni
|
||||||
|
|
||||||
@@ -590,3 +591,50 @@ formula ma il binario**: meno gradi di liberta', **dimezza gli ordini** (miglior
|
|||||||
$635), 115% sul FULL — ma paga in fragilita' d'ancora (20/23 contro 23/23, banda che include −0,061,
|
$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):
|
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.**
|
niente qui giustifica di toccare pesi, cron o config.**
|
||||||
|
|
||||||
|
### MONITOR-AUDIT (r0822_monitor_audit.py) — audit di PRODUZIONE, 6 monitor, 4,7 s
|
||||||
|
✅ **Metodo che rende il risultato non contestabile:** l'audit **riesegue `advance()` di produzione
|
||||||
|
tale e quale**, sostituendo solo `_append` con un raccoglitore in memoria -> nessuna
|
||||||
|
reimplementazione, quindi **nessun drift fra audit e monitor**. Sola lettura verificata (gli mtime
|
||||||
|
di `data/paper_*` sono rimasti quelli del cron delle 00:35).
|
||||||
|
| monitor | barra parziale | barre coincidenti | corr | **min/giorno misurati** | gate | ricostruibile |
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
| `paper_statarb` | **SI'** | **0/46** | +0,297 | **4** | **STATARB 27/09** | **SI', bit-exact** |
|
||||||
|
| `paper_dvolspread` | **SI'** | 0/28 | +0,262 | **2** | DVOLSPREAD 24/10 | SI', bit-exact |
|
||||||
|
| `paper_xsr` | **SI'** | 1/28 | −0,045 | **41** | XSR01 23/10 | SI', bit-exact |
|
||||||
|
| `paper_portfolio` | **SI'** | 7/56 | +0,245 | 19 | — (dashboard) | si', non al bit |
|
||||||
|
| `paper_prevday` | si' (1 barra su 24) | **1259/1319** | **+0,997** | 1.438 | — | si', bit-exact |
|
||||||
|
| `paper_combo` | **NO** | 7/37 | +0,991 | 1.402 | — | si', non al bit |
|
||||||
|
📌 **La patologia e' la stessa, la TAGLIA varia di un fattore 20** — e dipende da quanto pesa la
|
||||||
|
barra piu' recente nel segnale, esattamente come la lezione del 26/07 su SKH01 contro TP01.
|
||||||
|
🚨 **Il gate STATARB del 27/09 si ribalta su DUE criteri su tre:** Sharpe registrato **+1,96** (sopra
|
||||||
|
la soglia 0,5) contro **−2,02** ricostruito; maxDD **2,2% contro 15,3%** (guardia <10%). *Fra 36
|
||||||
|
giorni si sarebbe deciso su una serie che misura 4 minuti di mercato al giorno.*
|
||||||
|
⚠️ XSR01 e DVOLSPREAD danno lo **stesso verdetto** oggi, ma su numeri implausibili (Sharpe −15,8 su
|
||||||
|
28 barre = oltre 4 SE). **`implausible_sharpe` esiste dal 26/07 e non e' mai stato puntato sulle
|
||||||
|
serie forward.**
|
||||||
|
✅ **LA BUONA NOTIZIA, ed e' misurata: la finestra forward NON va persa.** Il replay *e'* la serie
|
||||||
|
corretta sulla stessa finestra, con config congelata e codice di produzione. Le due condizioni sono
|
||||||
|
**provate due volte in modo indipendente**: (a) `paper_prevday` ha **1427/1488 barre identiche al
|
||||||
|
bit** dopo 62 notti di riscrittura (il feed **non tocca** le barre chiuse); (b) le 6 barre di
|
||||||
|
`paper_statarb` recuperate dopo un guasto coincidono **al bit**.
|
||||||
|
-> **La decisione non e' "riparare e azzerare" ma "riparare `advance()` + RIGENERARE", e nessuna
|
||||||
|
delle tre date di gate si sposta.** Anche nell'ipotesi pessimista (`--reset`) l'unico gate che
|
||||||
|
slitterebbe e' STATARB, di **+18 giorni**.
|
||||||
|
📌 **Dettaglio che vale una regola: le uniche barre corrette di `paper_statarb` esistono perche' il
|
||||||
|
feed si e' ROTTO.** `rebuild_history` e' abortito per 7 giri consecutivi (09-15/07, EPERM sul
|
||||||
|
backup, gia' riparato); al ripristino il monitor ha recuperato 7 barre in un colpo, **6 delle quali
|
||||||
|
gia' chiuse** -> coincidono col replay al bit. *Il guasto ha prodotto da solo il controllo che
|
||||||
|
serviva a diagnosticare l'altro guasto.*
|
||||||
|
📌 **`paper_combo` e' sano PER CASO:** aspetta la chiusura di una **borsa**, non per progetto.
|
||||||
|
Nessuna riga di codice chiede la barra chiusa — **se la sua griglia cambiasse diventerebbe rotto in
|
||||||
|
silenzio.**
|
||||||
|
✅ **Guardia raccomandata (NON implementata), e ha il pregio di essere banale:**
|
||||||
|
`ts_ultima_barra + cadenza <= mtime del file di serie`, grazia 5 min. **O(1)**, nessuna strategia da
|
||||||
|
rieseguire, usa solo cio' che il monitor gia' scrive; segnala **5/6** e **tace sul sano**; controllo
|
||||||
|
positivo sintetico **6/6 nei due versi**. Il vol-ratio va **dopo, non al posto**: copre un guasto
|
||||||
|
diverso (drift monitor-strategia) e **non vede `paper_prevday`** (rapporto 0,999).
|
||||||
|
⚠️ Limiti dichiarati: i "minuti/giorno" sono una lettura del **rapporto di varianza** (assume random
|
||||||
|
walk sull'intervallo troncato), non un cronometro — il cronometro diretto e' 32-35 min; e per
|
||||||
|
`paper_portfolio`/`paper_combo` la ricostruzione **non sara' al bit** perche' la gamba GTAA legge
|
||||||
|
`ADJUSTED_LAST` di IB, ri-aggiustato all'indietro.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ vol registrata 0,46% contro 2,74% ricalcolata.
|
|||||||
Il difetto non e' di XSR01: e' della FORMA `new = [i for i in range(len(ts)) if ts[i] > last_ts]`
|
Il difetto non e' di XSR01: e' della FORMA `new = [i for i in range(len(ts)) if ts[i] > last_ts]`
|
||||||
applicata a un pannello la cui ultima riga e' provvisoria. Quella forma e' copiata in sei file.
|
applicata a un pannello la cui ultima riga e' provvisoria. Quella forma e' copiata in sei file.
|
||||||
Tre decisioni PRE-REGISTRATE si leggono su queste serie:
|
Tre decisioni PRE-REGISTRATE si leggono su queste serie:
|
||||||
STATARB 2026-09-27 (r0724_statarb_deploy_gate: Sharpe di net_modeled >= 0.35)
|
STATARB 2026-09-27 (r0724_statarb_deploy_gate: Sharpe di net_modeled >= 0.5)
|
||||||
XSR01 2026-10-23 (r0725_xsr_deploy_gate: Sharpe >= 1.0 E haircut $5.000 <= 40%)
|
XSR01 2026-10-23 (r0725_xsr_deploy_gate: Sharpe >= 1.0 E haircut $5.000 <= 40%)
|
||||||
DVOLSPREAD 2026-10-24 kill / 2027-01-24 decisione (soglie dentro paper_dvolspread)
|
DVOLSPREAD 2026-10-24 kill / 2027-01-24 decisione (soglie dentro paper_dvolspread)
|
||||||
e `monitor_health` dichiara **OK** tutti e sei, perche' misura freschezza e buchi: una serie
|
e `monitor_health` dichiara **OK** tutti e sei, perche' misura freschezza e buchi: una serie
|
||||||
@@ -42,11 +42,18 @@ Poi:
|
|||||||
E. IL COSTO DELLA RIPARAZIONE per gate: giorni di finestra persi, data in cui il contatore
|
E. IL COSTO DELLA RIPARAZIONE per gate: giorni di finestra persi, data in cui il contatore
|
||||||
nuovo tornerebbe alla stessa numerosita', e se esiste una RICOSTRUZIONE a posteriori.
|
nuovo tornerebbe alla stessa numerosita', e se esiste una RICOSTRUZIONE a posteriori.
|
||||||
|
|
||||||
COSA MI ASPETTAVO PRIMA DI MISURARE: che i tre monitor giornalieri su feed crypto (xsr, statarb,
|
COSA MI ASPETTAVO PRIMA DI MISURARE, e cosa e' andato diversamente:
|
||||||
dvolspread) avessero la stessa patologia identica; che `paper_prevday`, essendo su griglia 1h con
|
* i tre monitor giornalieri su feed crypto (xsr, statarb, dvolspread) con la STESSA patologia,
|
||||||
24 barre al giorno, ne avesse una MOLTO piu' mite (una barra su 24 troncata); e che
|
intorno ai ~35 minuti al giorno di XSR01 -> **meta' giusto**: la patologia e' la stessa ma la
|
||||||
`paper_combo`, che vive sul calendario di borsa, fosse o rotto come gli altri o sano per caso.
|
TAGLIA no (2, 4 e 41 min/giorno). Un libro dollar-neutral perde molto piu' di un libro
|
||||||
Solo la terza aspettativa e' stata una sorpresa.
|
direzionale a parita' di troncamento, perche' su 35 minuti le due gambe si muovono insieme;
|
||||||
|
* `paper_prevday` MOLTO piu' mite (1 barra su 24) -> **confermato** (1.438 min/giorno su 1.440),
|
||||||
|
con un dettaglio non previsto: il difetto si propaga alla barra successiva quando il bersaglio
|
||||||
|
calcolato sulla barra parziale differisce;
|
||||||
|
* `paper_combo` rotto o sano per caso -> **sano, e per caso**: aspetta la chiusura di una BORSA;
|
||||||
|
* NON previsto: le uniche barre corrette di `paper_statarb` esistono perche' il feed si ROMPE
|
||||||
|
per 7 giorni a luglio e il monitor le recupera CHIUSE. Sono anche la prova che serviva per
|
||||||
|
dire che la finestra e' ricostruibile.
|
||||||
|
|
||||||
nice -n 19 timeout 900 uv run python scripts/research/r0822_monitor_audit.py
|
nice -n 19 timeout 900 uv run python scripts/research/r0822_monitor_audit.py
|
||||||
"""
|
"""
|
||||||
@@ -289,7 +296,8 @@ def b_xsr():
|
|||||||
print(f" inception {T[0].date()} = DOPO l'incidente del feed: la finestra e' gia' pulita.")
|
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]))
|
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",
|
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)")
|
src="hl_*_1d.parquet", cad_h=24.0, ric="SI bit-exact",
|
||||||
|
rec=rec, rep=sink.of("returns.jsonl"))
|
||||||
|
|
||||||
|
|
||||||
def b_statarb():
|
def b_statarb():
|
||||||
@@ -323,17 +331,18 @@ def b_statarb():
|
|||||||
print(f"\n 📌 LE UNICHE BARRE CORRETTE DELLA SERIE VENGONO DA UN GUASTO: le {int(ident.sum())} "
|
print(f"\n 📌 LE UNICHE BARRE CORRETTE DELLA SERIE VENGONO DA UN GUASTO: le {int(ident.sum())} "
|
||||||
f"identiche\n sono CONSECUTIVE ({gg[0]} -> {gg[-1]}) e cadono dentro l'incidente "
|
f"identiche\n sono CONSECUTIVE ({gg[0]} -> {gg[-1]}) e cadono dentro l'incidente "
|
||||||
"del feed.")
|
"del feed.")
|
||||||
ev = freeze_evidence()
|
ev = sorted(freeze_evidence())
|
||||||
print(f" Prova indipendente dal log del cron: `rebuild_history` e' abortito in "
|
print(f" Prova indipendente dal log del cron: `rebuild_history` e' abortito in "
|
||||||
f"{len(ev)} giri\n ({', '.join(sorted(ev)[:8])}{'...' if len(ev) > 8 else ''}) — "
|
f"{len(ev)} giri consecutivi")
|
||||||
"EPERM sul backup, difetto gia' riparato\n nel sorgente. Col feed fermo il monitor "
|
print(f" ({ev[0]} -> {ev[-1]}), EPERM sul backup — difetto gia' riparato nel sorgente.")
|
||||||
"non trovava barre nuove; al ripristino ne ha\n recuperate 7 in un colpo solo, di "
|
print(" Col feed fermo il monitor non trovava barre nuove; al ripristino ne ha")
|
||||||
"cui 6 GIA' CHIUSE -> coincidono col replay al bit.")
|
print(" recuperate 7 in un colpo solo, di cui 6 GIA' CHIUSE -> coincidono al bit.")
|
||||||
print(" Due conseguenze: (a) il 'min/giorno' globale e' GONFIATO da quelle barre — la")
|
print(" Due conseguenze: (a) il 'min/giorno' globale e' GONFIATO da quelle barre — la")
|
||||||
print(" riga 'ESCLUSO l'incidente' e' la stima onesta; (b) quelle 6 barre sono la prova")
|
print(" riga 'ESCLUSO l'incidente' e' la stima onesta; (b) quelle 6 barre sono la prova")
|
||||||
print(" che, su barre chiuse, il codice di produzione riproduce il replay ESATTAMENTE.")
|
print(" che, su barre chiuse, il codice di produzione riproduce il replay ESATTAMENTE.")
|
||||||
RES["paper_statarb"] = dict(parziale="SI", cmp=out["clean"], gate="STATARB 2026-09-27",
|
RES["paper_statarb"] = dict(parziale="SI", cmp=out["clean"], gate="STATARB 2026-09-27",
|
||||||
src="btc/eth 1h -> resample 1d", cad_h=24.0, ric="SI (bit-exact)")
|
src="btc/eth 1h -> resample 1d", cad_h=24.0, ric="SI bit-exact",
|
||||||
|
rec=rec, rep=sink.of("returns.jsonl"))
|
||||||
|
|
||||||
|
|
||||||
def b_dvolspread():
|
def b_dvolspread():
|
||||||
@@ -374,7 +383,7 @@ def b_dvolspread():
|
|||||||
RES["paper_dvolspread"] = dict(parziale="SI", cmp=out["clean"],
|
RES["paper_dvolspread"] = dict(parziale="SI", cmp=out["clean"],
|
||||||
gate="DVOLSPREAD 2026-10-24 / 2027-01-24",
|
gate="DVOLSPREAD 2026-10-24 / 2027-01-24",
|
||||||
src="btc/eth 1h -> resample 1d + dvol", cad_h=24.0,
|
src="btc/eth 1h -> resample 1d + dvol", cad_h=24.0,
|
||||||
ric="SI (bit-exact)")
|
ric="SI bit-exact", rec=rec, rep=sink.of("returns.jsonl"))
|
||||||
|
|
||||||
|
|
||||||
def b_prevday():
|
def b_prevday():
|
||||||
@@ -429,7 +438,7 @@ def b_prevday():
|
|||||||
print(" 📌 E il verdetto operativo e' l'opposto degli altri quattro: su griglia oraria il difetto")
|
print(" 📌 E il verdetto operativo e' l'opposto degli altri quattro: su griglia oraria il difetto")
|
||||||
print(" c'e' ma vale ~0.1% della varianza. `paper_prevday` NON e' da rigenerare.")
|
print(" c'e' ma vale ~0.1% della varianza. `paper_prevday` NON e' da rigenerare.")
|
||||||
RES["paper_prevday"] = dict(parziale="SI", cmp=out["clean"], gate="nessuno (lead in monitor)",
|
RES["paper_prevday"] = dict(parziale="SI", cmp=out["clean"], gate="nessuno (lead in monitor)",
|
||||||
src="btc/eth 1h grezzo", cad_h=1.0, ric="SI (bit-exact)")
|
src="btc/eth 1h grezzo", cad_h=1.0, ric="SI bit-exact")
|
||||||
|
|
||||||
|
|
||||||
def b_portfolio():
|
def b_portfolio():
|
||||||
@@ -457,8 +466,9 @@ def b_portfolio():
|
|||||||
if ident.any():
|
if ident.any():
|
||||||
print(f"\n ⚠ TRAPPOLA DA NON PRENDERE: delle {int(ident.sum())} barre 'identiche', "
|
print(f"\n ⚠ TRAPPOLA DA NON PRENDERE: delle {int(ident.sum())} barre 'identiche', "
|
||||||
f"{int(zeri.sum())} sono ZERO contro ZERO")
|
f"{int(zeri.sum())} sono ZERO contro ZERO")
|
||||||
print(" (" + ", ".join(str(x.date()) for x in T[zeri]) + ") = giorni in cui TUTTI e cinque")
|
print(" (" + ", ".join(str(x.date()) for x in T[zeri]) + ")")
|
||||||
print(" gli sleeve erano flat (TP01 risk-off, GTAA a borsa chiusa, VRP fuori scadenza).")
|
print(" = giorni in cui TUTTI e cinque gli sleeve erano flat insieme (TP01 risk-off,")
|
||||||
|
print(" GTAA a borsa chiusa nel weekend, VRP fuori scadenza).")
|
||||||
print(" Contarle come 'coincidono' sarebbe la trappola gia' codificata dal progetto —")
|
print(" Contarle come 'coincidono' sarebbe la trappola gia' codificata dal progetto —")
|
||||||
print(" barre ATTIVE, non barre di calendario (26/07, il gate che segnalo' VRP01 perche'")
|
print(" barre ATTIVE, non barre di calendario (26/07, il gate che segnalo' VRP01 perche'")
|
||||||
print(" contava il 94% di zeri). Su barre attive le coincidenze qui sono "
|
print(" contava il 94% di zeri). Su barre attive le coincidenze qui sono "
|
||||||
@@ -474,7 +484,7 @@ def b_portfolio():
|
|||||||
RES["paper_portfolio"] = dict(parziale="SI", cmp=out["clean"],
|
RES["paper_portfolio"] = dict(parziale="SI", cmp=out["clean"],
|
||||||
gate="nessuno (dashboard/book di ricerca)",
|
gate="nessuno (dashboard/book di ricerca)",
|
||||||
src="5 sleeve, il piu' recente su 1h->1d e HL 1d", cad_h=24.0,
|
src="5 sleeve, il piu' recente su 1h->1d e HL 1d", cad_h=24.0,
|
||||||
ric="SI* (equity IB ri-aggiustata)")
|
ric="SI non al bit")
|
||||||
|
|
||||||
|
|
||||||
def b_combo():
|
def b_combo():
|
||||||
@@ -514,7 +524,7 @@ def b_combo():
|
|||||||
print(" senza che nulla lo segnali.")
|
print(" senza che nulla lo segnali.")
|
||||||
RES["paper_combo"] = dict(parziale="NO", cmp=out["clean"], gate="nessuno (paper cross-venue)",
|
RES["paper_combo"] = dict(parziale="NO", cmp=out["clean"], gate="nessuno (paper cross-venue)",
|
||||||
src="TP01 1h->1d su griglia IB", cad_h=24.0,
|
src="TP01 1h->1d su griglia IB", cad_h=24.0,
|
||||||
ric="SI* (equity IB ri-aggiustata)")
|
ric="SI non al bit")
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================================
|
# ============================================================================================
|
||||||
@@ -522,7 +532,7 @@ def b_combo():
|
|||||||
# ============================================================================================
|
# ============================================================================================
|
||||||
GATE_INFO = {
|
GATE_INFO = {
|
||||||
"paper_xsr": ("XSR01 2026-10-23", "Sharpe>=1.0 E haircut $5.000<=40%"),
|
"paper_xsr": ("XSR01 2026-10-23", "Sharpe>=1.0 E haircut $5.000<=40%"),
|
||||||
"paper_statarb": ("STATARB 2026-09-27", "Sharpe di net_modeled >= 0.35"),
|
"paper_statarb": ("STATARB 2026-09-27", "Sharpe di net_modeled >= 0.5"),
|
||||||
"paper_dvolspread": ("DVOLSPREAD 24/10 kill", "Sharpe<-0.50 -> ritiro; 27/01 decisione piena"),
|
"paper_dvolspread": ("DVOLSPREAD 24/10 kill", "Sharpe<-0.50 -> ritiro; 27/01 decisione piena"),
|
||||||
"paper_prevday": ("-", "lead senza data"),
|
"paper_prevday": ("-", "lead senza data"),
|
||||||
"paper_portfolio": ("-", "dashboard"),
|
"paper_portfolio": ("-", "dashboard"),
|
||||||
@@ -537,22 +547,105 @@ def sezione_C():
|
|||||||
print("\n Le colonne sono calcolate ESCLUDENDO l'incidente del feed 09-15/07 (le barre")
|
print("\n Le colonne sono calcolate ESCLUDENDO l'incidente del feed 09-15/07 (le barre")
|
||||||
print(" recuperate a posteriori sono chiuse e attenuerebbero il difetto per la ragione")
|
print(" recuperate a posteriori sono chiuse e attenuerebbero il difetto per la ragione")
|
||||||
print(" sbagliata). 'min/g' = minuti di mercato al giorno effettivamente misurati, su 1440.")
|
print(" sbagliata). 'min/g' = minuti di mercato al giorno effettivamente misurati, su 1440.")
|
||||||
print(f"\n {'monitor':<19}{'parz.':>6}{'ident./tot':>13}{'corr':>9}{'min/g':>9}"
|
print(f"\n {'monitor':<19}{'barra parz.':>13}{'ident./tot':>13}{'corr':>9}{'min/g':>8}"
|
||||||
f"{'ricostruibile':>25} gate dipendente")
|
f"{'ricostruibile':>17} gate dipendente")
|
||||||
for k, v in RES.items():
|
for k, v in RES.items():
|
||||||
c = v["cmp"]
|
c = v["cmp"]
|
||||||
ratio = "{}/{}".format(c["ident"], c["n"])
|
ratio = "{}/{}".format(c["ident"], c["n"])
|
||||||
print(f" {k:<19}{v['parziale']:>6}{ratio:>13}{c['corr']:>+9.3f}"
|
print(f" {k:<19}{v['parziale']:>13}{ratio:>13}{c['corr']:>+9.3f}"
|
||||||
f"{c['minuti']:>9,.0f}{v['ric']:>25} {GATE_INFO[k][0]}")
|
f"{c['minuti']:>8,.0f}{v['ric']:>17} {GATE_INFO[k][0]}")
|
||||||
print("\n 'ricostruibile' = la serie CORRETTA sulla stessa finestra forward si puo' ricalcolare")
|
print("\n 'ricostruibile' = la serie CORRETTA sulla stessa finestra forward si puo' ricalcolare")
|
||||||
print(" oggi dai feed su disco: e' letteralmente la colonna 'replay' di questo script. '*' =")
|
print(" oggi dai feed su disco: e' letteralmente la colonna 'replay' di questo script.")
|
||||||
print(" ricostruibile ma NON al bit, perche' una gamba viene dal feed equity IB che e'")
|
print(" 'non al bit' = ricostruibile, ma una gamba viene dal feed equity IB, che e'")
|
||||||
print(" ri-aggiustato all'indietro (`ADJUSTED_LAST`).")
|
print(" ri-aggiustato all'indietro (`ADJUSTED_LAST`) -> i centesimi non torneranno uguali.")
|
||||||
print("\n LETTURA IN UNA RIGA: quattro monitor su sei registrano fra 2 e 41 minuti di mercato")
|
print("\n LETTURA IN UNA RIGA: quattro monitor su sei registrano fra 2 e 41 minuti di mercato")
|
||||||
print(" al giorno spacciandoli per 24 ore; i due che non lo fanno sono quello a griglia oraria")
|
print(" al giorno spacciandoli per 24 ore; i due che non lo fanno sono quello a griglia oraria")
|
||||||
print(" (dove il difetto vale una barra su 24) e quello che aspetta la chiusura di una BORSA.")
|
print(" (dove il difetto vale una barra su 24) e quello che aspetta la chiusura di una BORSA.")
|
||||||
|
|
||||||
|
|
||||||
|
def sezione_C2():
|
||||||
|
"""Il criterio di ciascun gate PRE-REGISTRATO resta leggibile? Le soglie NON sono ridichiarate
|
||||||
|
qui: si IMPORTANO dagli script di gate e dal monitor (regola del progetto — un sorvegliante
|
||||||
|
deriva il proprio bersaglio dal codice sorvegliato, mai lo ridichiara: 21/08, `fee_watch`)."""
|
||||||
|
print("\n" + "=" * 102)
|
||||||
|
print(" C2 — IL CRITERIO DEI TRE GATE PRE-REGISTRATI E' ANCORA LEGGIBILE?")
|
||||||
|
print("=" * 102)
|
||||||
|
import r0724_statarb_deploy_gate as GS # noqa: E402 (solo costanti: ha il main-guard)
|
||||||
|
import r0725_xsr_deploy_gate as GX # noqa: E402
|
||||||
|
pv = live("paper_dvolspread")
|
||||||
|
|
||||||
|
def metriche(rows: list[dict], key_m="net_modeled", key_r=None):
|
||||||
|
rm = np.array([float(r[key_m]) for r in rows])
|
||||||
|
eq = np.cumprod(1 + rm)
|
||||||
|
pk = np.maximum.accumulate(eq)
|
||||||
|
out = dict(sh=float(rm.mean() / rm.std() * np.sqrt(365)) if rm.std() > 0 else 0.0,
|
||||||
|
dd=float(np.max((pk - eq) / pk)), tot=float(np.prod(1 + rm) - 1))
|
||||||
|
if key_r:
|
||||||
|
rr = np.array([float(r.get(key_r, np.nan)) for r in rows])
|
||||||
|
rr = rr[np.isfinite(rr)]
|
||||||
|
out["tot_r"] = float(np.prod(1 + rr) - 1) if len(rr) else float("nan")
|
||||||
|
return out
|
||||||
|
|
||||||
|
def coppia(name):
|
||||||
|
rec = RES[name]["rec"]
|
||||||
|
rep = {int(r["ts"]): r for r in RES[name]["rep"]}
|
||||||
|
keep = [r for r in rec if int(r["ts"]) in rep]
|
||||||
|
return keep, [rep[int(r["ts"])] for r in keep]
|
||||||
|
|
||||||
|
print(f"\n {'gate':<26}{'metrica primaria':<26}{'soglia':>10}{'REGISTR.':>11}"
|
||||||
|
f"{'RICOSTR.':>11} verdetto")
|
||||||
|
|
||||||
|
# --- STATARB -------------------------------------------------------------------------
|
||||||
|
a, b = coppia("paper_statarb")
|
||||||
|
ma, mb = metriche(a, key_r="net_real"), metriche(b, key_r="net_real")
|
||||||
|
flip = (ma["sh"] >= GS.SH_DEPLOY) != (mb["sh"] >= GS.SH_DEPLOY)
|
||||||
|
print(f" {'STATARB ' + str(GS.DECISION):<26}{'Sharpe net_modeled':<26}"
|
||||||
|
f"{'>= ' + str(GS.SH_DEPLOY):>10}{ma['sh']:>+11.2f}{mb['sh']:>+11.2f} "
|
||||||
|
f"{'*** SI RIBALTA ***' if flip else 'stesso'}")
|
||||||
|
print(f" {'':<26}{'maxDD':<26}{'< ' + f'{GS.DD_MAX:.0%}':>10}{ma['dd']:>10.1%}"
|
||||||
|
f"{mb['dd']:>11.1%} "
|
||||||
|
f"{'*** SI RIBALTA ***' if (ma['dd'] < GS.DD_MAX) != (mb['dd'] < GS.DD_MAX) else 'stesso'}")
|
||||||
|
hp_a = abs((1 + ma["tot"]) - (1 + ma["tot_r"])) * 100
|
||||||
|
hp_b = abs((1 + mb["tot"]) - (1 + mb["tot_r"])) * 100
|
||||||
|
print(f" {'':<26}{'fill-haircut cum (pp)':<26}{'< ' + str(GS.HAIRCUT_MAX_PP):>10}"
|
||||||
|
f"{hp_a:>11.2f}{hp_b:>11.2f} "
|
||||||
|
f"{'*** SI RIBALTA ***' if (hp_a < GS.HAIRCUT_MAX_PP) != (hp_b < GS.HAIRCUT_MAX_PP) else 'stesso'}")
|
||||||
|
|
||||||
|
# --- XSR01 ---------------------------------------------------------------------------
|
||||||
|
a, b = coppia("paper_xsr")
|
||||||
|
K5 = "net_REAL-$5000"
|
||||||
|
ma, mb = metriche(a, key_r=K5), metriche(b, key_r=K5)
|
||||||
|
hc_a = (ma["tot"] - ma["tot_r"]) / abs(ma["tot"]) if ma["tot"] else float("nan")
|
||||||
|
hc_b = (mb["tot"] - mb["tot_r"]) / abs(mb["tot"]) if mb["tot"] else float("nan")
|
||||||
|
fl1 = (ma["sh"] >= GX.SH_DEPLOY) != (mb["sh"] >= GX.SH_DEPLOY)
|
||||||
|
fl2 = (hc_a <= GX.HAIRCUT_MAX) != (hc_b <= GX.HAIRCUT_MAX)
|
||||||
|
print(f" {'XSR01 ' + str(GX.DECISION):<26}{'Sharpe net_modeled':<26}"
|
||||||
|
f"{'>= ' + str(GX.SH_DEPLOY):>10}{ma['sh']:>+11.2f}{mb['sh']:>+11.2f} "
|
||||||
|
f"{'*** SI RIBALTA ***' if fl1 else 'stesso'}")
|
||||||
|
print(f" {'':<26}{'haircut $5.000':<26}{'<= ' + f'{GX.HAIRCUT_MAX:.0%}':>10}"
|
||||||
|
f"{hc_a:>10.1%}{hc_b:>11.1%} {'*** SI RIBALTA ***' if fl2 else 'stesso'}")
|
||||||
|
|
||||||
|
# --- DVOLSPREAD ----------------------------------------------------------------------
|
||||||
|
a, b = coppia("paper_dvolspread")
|
||||||
|
ma, mb = metriche(a), metriche(b)
|
||||||
|
fl = (ma["sh"] < pv.KILL_SHARPE) != (mb["sh"] < pv.KILL_SHARPE)
|
||||||
|
print(f" {'DVOLSPREAD ' + pv.KILL_DATE:<26}{'Sharpe fwd (kill se sotto)':<26}"
|
||||||
|
f"{'> ' + f'{pv.KILL_SHARPE:+.2f}':>10}{ma['sh']:>+11.2f}{mb['sh']:>+11.2f} "
|
||||||
|
f"{'*** SI RIBALTA ***' if fl else 'stesso (KILL in entrambe)'}")
|
||||||
|
|
||||||
|
print("""
|
||||||
|
⚠ QUESTA NON E' UNA LETTURA DEI GATE, e non deve diventarlo: le tre date sono nel futuro
|
||||||
|
(anticiparle sarebbe selezione-sul-forward, contro la regola del progetto) e con 28-54 barre
|
||||||
|
l'errore standard di uno Sharpe annualizzato e' 2,6-3,6. Serve a una cosa sola, e la mostra:
|
||||||
|
il difetto NON e' rumore centrato — sposta la metrica primaria abbastanza da attraversare la
|
||||||
|
soglia. Su STATARB la serie registrata dice +1,96 (sopra la soglia di deploy 0,5) e quella
|
||||||
|
ricostruita dice -2,02: **stesso codice, stessa finestra, verdetto opposto**.
|
||||||
|
⚠ E c'e' un secondo segnale, gratis: uno Sharpe registrato di -15,8 su 28 barre e' IMPOSSIBILE
|
||||||
|
(|Sharpe| oltre 4 SE). Il gate `implausible_sharpe` esiste gia' in `altlib` dal 26/07 ma
|
||||||
|
nessuno lo punta sulle serie FORWARD — solo sui candidati. Un numero fuori scala e' un
|
||||||
|
rilevatore di guasti a costo zero, e in questo caso era li' da leggere da settimane.""")
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================================
|
# ============================================================================================
|
||||||
# D — LA GUARDIA CHE MANCA A monitor_health
|
# D — LA GUARDIA CHE MANCA A monitor_health
|
||||||
# ============================================================================================
|
# ============================================================================================
|
||||||
@@ -608,8 +701,10 @@ def sezione_D():
|
|||||||
if v["parziale"] == "SI" and seg == "tace":
|
if v["parziale"] == "SI" and seg == "tace":
|
||||||
miss.append(k)
|
miss.append(k)
|
||||||
print(f" {k:<19}{c['sd_rec']:>9.2f}%{c['sd_rep']:>9.2f}%{rr:>10.3f} {seg}")
|
print(f" {k:<19}{c['sd_rec']:>9.2f}%{c['sd_rep']:>9.2f}%{rr:>10.3f} {seg}")
|
||||||
print(f" -> MANCA {len(miss)} monitor rotti su {sum(1 for v in RES.values() if v['parziale'] == 'SI')}"
|
rotti = sum(1 for v in RES.values() if v["parziale"] == "SI")
|
||||||
f": {', '.join(miss) if miss else '-'}")
|
print(f" -> segnala {rotti - len(miss)} dei {rotti} monitor che leggono una barra parziale,")
|
||||||
|
print(f" NON segnala il sano (`paper_combo`, 0.987), e MANCA {len(miss)}: "
|
||||||
|
f"{', '.join(miss) if miss else '-'}")
|
||||||
print(" Motivo strutturale, non taratura: su una griglia oraria il difetto tocca 1 barra")
|
print(" Motivo strutturale, non taratura: su una griglia oraria il difetto tocca 1 barra")
|
||||||
print(" su 24 e sposta la vol dell'1-2%, cioe' DENTRO il rumore di stima di una vol su")
|
print(" su 24 e sposta la vol dell'1-2%, cioe' DENTRO il rumore di stima di una vol su")
|
||||||
print(" poche settimane. Abbassare la soglia per prenderlo genererebbe falsi allarmi ogni")
|
print(" poche settimane. Abbassare la soglia per prenderlo genererebbe falsi allarmi ogni")
|
||||||
@@ -697,17 +792,23 @@ def sezione_E():
|
|||||||
("paper_dvolspread", "DVOLSPREAD (kill)", pd.Timestamp("2026-10-24"), "returns.jsonl"),
|
("paper_dvolspread", "DVOLSPREAD (kill)", pd.Timestamp("2026-10-24"), "returns.jsonl"),
|
||||||
("paper_dvolspread", "DVOLSPREAD (decisione)", pd.Timestamp("2027-01-24"), "returns.jsonl"),
|
("paper_dvolspread", "DVOLSPREAD (decisione)", pd.Timestamp("2027-01-24"), "returns.jsonl"),
|
||||||
]
|
]
|
||||||
print(f"\n {'monitor / gate':<34}{'barre oggi':>12}{'data gate':>13}{'se AZZERI':>12}"
|
print("\n IPOTESI PESSIMISTA — si ripara `advance()` e si fa `--reset` (la finestra riparte da")
|
||||||
|
print(" zero oggi). Con una barra al giorno, tornare a N barre richiede N giorni:")
|
||||||
|
print(f"\n {'monitor / gate':<42}{'barre':>7}{'data gate':>13}{'reset -> N barre':>18}"
|
||||||
f"{'ritardo':>10}")
|
f"{'ritardo':>10}")
|
||||||
|
ritardi = []
|
||||||
for mon, nome, gate, ser in righe:
|
for mon, nome, gate, ser in righe:
|
||||||
n = len(read_jsonl(ROOT / "data" / mon / ser))
|
n = len(read_jsonl(ROOT / "data" / mon / ser))
|
||||||
# con una barra al giorno, tornare a n barre richiede n giorni dal reset
|
|
||||||
rip = oggi + pd.Timedelta(days=n)
|
rip = oggi + pd.Timedelta(days=n)
|
||||||
rit = (rip - gate).days
|
rit = (rip - gate).days
|
||||||
print(f" {f'{mon} / {nome}':<34}{n:>12}{str(gate.date()):>13}"
|
ritardi.append((nome, rit))
|
||||||
f"{str(rip.date()):>12}{rit:>+9}g")
|
print(f" {f'{mon} / {nome}':<42}{n:>7}{str(gate.date()):>13}"
|
||||||
print("\n Cosi' letta, la riparazione sposta i tre gate di 1-2 mesi. MA la colonna giusta e'")
|
f"{str(rip.date()):>18}{rit:>+9}g")
|
||||||
print(" un'altra, e cambia la decisione:")
|
peggiore = max(ritardi, key=lambda x: x[1])
|
||||||
|
print(f"\n Anche nell'ipotesi pessimista il danno NON e' uniforme: l'unico gate che slitterebbe")
|
||||||
|
print(f" e' {peggiore[0]} ({peggiore[1]:+d} giorni) — gli altri hanno finestre cosi' giovani che")
|
||||||
|
print(" ricostruirebbero la propria numerosita' PRIMA della data di decisione. Ma la colonna")
|
||||||
|
print(" giusta e' ancora un'altra, e toglie di mezzo anche quel ritardo:")
|
||||||
print("""
|
print("""
|
||||||
✅ LA FINESTRA FORWARD **NON VA PERSA**: e' RICOSTRUIBILE, per tutti e sei i monitor.
|
✅ LA FINESTRA FORWARD **NON VA PERSA**: e' RICOSTRUIBILE, per tutti e sei i monitor.
|
||||||
Le ore mancanti non sono mai state registrate, ma non e' li' che vivono: vivono nei feed
|
Le ore mancanti non sono mai state registrate, ma non e' li' che vivono: vivono nei feed
|
||||||
@@ -719,10 +820,12 @@ def sezione_E():
|
|||||||
minuti.
|
minuti.
|
||||||
|
|
||||||
LE DUE CONDIZIONI, ed e' giusto chiedere che siano verificate e non assunte:
|
LE DUE CONDIZIONI, ed e' giusto chiedere che siano verificate e non assunte:
|
||||||
(1) il feed non riscrive le barre gia' chiuse. **MISURATO qui**: `paper_prevday` ha
|
(1) il feed non riscrive le barre gia' chiuse. **MISURATO qui, due volte e in modo
|
||||||
1426 barre su 1488 identiche BIT A BIT al replay dopo 62 giorni di riscritture
|
indipendente**: `paper_prevday` ha 1427 barre su 1488 identiche BIT A BIT al replay
|
||||||
notturne del parquet BTC/ETH (sezione B4). Per Hyperliquid la stessa cosa e' misurata
|
dopo 62 notti di riscrittura del parquet BTC/ETH (B4); e le 6 barre che `paper_statarb`
|
||||||
in `r0822_xsr_repro` T2 (Sharpe 2024 e 2025 riprodotti al centesimo su 731 barre).
|
recupero' durante l'incidente del feed coincidono anch'esse al bit (B2) — due percorsi
|
||||||
|
diversi, stesso verdetto. Per Hyperliquid la misura e' in `r0822_xsr_repro` T2 (Sharpe
|
||||||
|
2024 e 2025 riprodotti al centesimo su 731 barre).
|
||||||
(2) la config e' congelata e verificabile: `paper_dvolspread` lo controlla da solo
|
(2) la config e' congelata e verificabile: `paper_dvolspread` lo controlla da solo
|
||||||
(`frozen` nello stato, esce 1 se diverge); per gli altri il congelamento e' nel
|
(`frozen` nello stato, esce 1 se diverge); per gli altri il congelamento e' nel
|
||||||
sorgente ed e' in git.
|
sorgente ed e' in git.
|
||||||
@@ -743,11 +846,28 @@ def sezione_E():
|
|||||||
verificabili in git (lo sono).
|
verificabili in git (lo sono).
|
||||||
Il costo vero e' (c), non i giorni: nessuna delle tre date di gate si sposta.
|
Il costo vero e' (c), non i giorni: nessuna delle tre date di gate si sposta.
|
||||||
|
|
||||||
⚠ UNA COSA CHE LA RIGENERAZIONE CAMBIA DAVVERO, e va scritta nel diario: i libri REAL saltano i
|
⚠ UNA COSA CHE LA RIGENERAZIONE CAMBIA DAVVERO, ma di poco — e il "di poco" e' MISURATO, non
|
||||||
ribilanci sotto il min-order, e quella decisione dipende dal capitale corrente, quindi il
|
assunto. I libri REAL saltano i ribilanci sotto il min-order e quella decisione dipende dal
|
||||||
percorso REAL rigenerato non e' il percorso REAL registrato — non e' "lo stesso numero
|
capitale corrente: il percorso REAL rigenerato non e' "lo stesso numero calcolato meglio", e'
|
||||||
calcolato meglio", e' un secondo percorso deterministico. Per XSR01 conta: il gate del 23/10
|
un secondo percorso deterministico. Contava sapere quanto, perche' il gate XSR01 del 23/10
|
||||||
legge net_REAL-$5000 per l'haircut.""")
|
legge `net_REAL-$5000` per l'haircut: misurato in C2, **1,7% registrato contro 1,8%
|
||||||
|
ricostruito**. Trascurabile a $5.000 (i ticket superano il min-order comunque). Il caveat
|
||||||
|
resta vero in linea di principio e va scritto nel diario; non e' un ostacolo alla decisione.
|
||||||
|
|
||||||
|
COSA FARE, MONITOR PER MONITOR (raccomandazione, non azione — questo script non tocca nulla).
|
||||||
|
⚠ Le due cose sono SEPARATE: la RIPARAZIONE di `advance()` (fermarsi all'ultima barra chiusa)
|
||||||
|
ha senso su tutti e sei — su un monitor sano non cambia niente e lo protegge da un cambio di
|
||||||
|
griglia futuro; la RIGENERAZIONE della serie e' un'altra decisione, e va fatta solo dove il
|
||||||
|
difetto morde abbastanza da spostare cio' che si leggera':
|
||||||
|
paper_xsr rigenerare — 41 min/g, e il gate del 23/10 legge questa serie
|
||||||
|
paper_statarb rigenerare — 4 min/g, gate 27/09: e' il piu' vicino nel tempo
|
||||||
|
paper_dvolspread rigenerare — 2 min/g, il peggiore dei sei; kill-check il 24/10
|
||||||
|
paper_prevday LASCIARE — 1.438/1.440 min/g: la rigenerazione cambierebbe lo 0,1%
|
||||||
|
della varianza e azzererebbe 1.488 barre di storia
|
||||||
|
paper_portfolio rigenerare — 19 min/g; nessun gate, ma e' la serie che il dashboard
|
||||||
|
mostra e che finisce nei diari come "il book sta facendo X"
|
||||||
|
paper_combo LASCIARE — sano; semmai va PROTETTO con un test che rompa se la sua
|
||||||
|
griglia smette di essere il calendario di borsa""")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -763,6 +883,7 @@ def main() -> None:
|
|||||||
b_portfolio()
|
b_portfolio()
|
||||||
b_combo()
|
b_combo()
|
||||||
sezione_C()
|
sezione_C()
|
||||||
|
sezione_C2()
|
||||||
sezione_D()
|
sezione_D()
|
||||||
sezione_E()
|
sezione_E()
|
||||||
print("\n" + "=" * 102)
|
print("\n" + "=" * 102)
|
||||||
|
|||||||
@@ -362,11 +362,14 @@ def objective(w: dict, lev: float, firm: str, ev_idx: np.ndarray, fu_idx: np.nda
|
|||||||
|
|
||||||
|
|
||||||
def paired_delta(wA: dict, levA: float, wB: dict, levB: float, firm: str,
|
def paired_delta(wA: dict, levA: float, wB: dict, levB: float, firm: str,
|
||||||
ev_idx: np.ndarray, fu_idx: np.ndarray) -> tuple[float, float]:
|
ev_idx: np.ndarray, fu_idx: np.ndarray,
|
||||||
|
drift_mult: tuple = ()) -> tuple[float, float]:
|
||||||
"""Differenza APPAIATA di J fra due configurazioni (stessi indici di bootstrap) + errore
|
"""Differenza APPAIATA di J fra due configurazioni (stessi indici di bootstrap) + errore
|
||||||
standard della differenza. Il livello di J ha SE ~0.01; la DIFFERENZA molto meno."""
|
standard della differenza. Il livello di J ha SE ~0.01; la DIFFERENZA molto meno.
|
||||||
a = objective(wA, levA, firm, ev_idx, fu_idx)["jvec"]
|
⚠ `drift_mult` va passato: dimenticarlo confronta due configurazioni NON stressate e
|
||||||
b = objective(wB, levB, firm, ev_idx, fu_idx)["jvec"]
|
stampa un delta che non c'entra con la riga in cui compare (errore commesso in sessione)."""
|
||||||
|
a = objective(wA, levA, firm, ev_idx, fu_idx, drift_mult=drift_mult)["jvec"]
|
||||||
|
b = objective(wB, levB, firm, ev_idx, fu_idx, drift_mult=drift_mult)["jvec"]
|
||||||
d = a - b
|
d = a - b
|
||||||
return float(d.mean()), float(d.std(ddof=1) / np.sqrt(len(d)))
|
return float(d.mean()), float(d.std(ddof=1) / np.sqrt(len(d)))
|
||||||
|
|
||||||
@@ -721,7 +724,8 @@ def main() -> None:
|
|||||||
w_, lv_, o_ = max(rows, key=lambda x: x[2]["J"])
|
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,
|
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"])
|
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)
|
dd_, sd_ = paired_delta(w_, lv_, {"TP01": 0.75, "SKH01": 0.25}, lvL, "HYRO", ev_idx,
|
||||||
|
fu_idx, drift_mult=dmt)
|
||||||
print(f" {mult:>12.2f} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {o_['p_pass']:>8.1%} "
|
print(f" {mult:>12.2f} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {o_['p_pass']:>8.1%} "
|
||||||
f"{o_['p_alive']:>8.1%} {o_['e_payout']:>9,.0f}$ LIVE {oL['J']:.3f} "
|
f"{o_['p_alive']:>8.1%} {o_['e_payout']:>9,.0f}$ LIVE {oL['J']:.3f} "
|
||||||
f"delta {dd_:+.3f} +-{sd_:.3f}")
|
f"delta {dd_:+.3f} +-{sd_:.3f}")
|
||||||
@@ -736,18 +740,24 @@ def main() -> None:
|
|||||||
print(" l'audit 02/07 lo trova al 93-98° pctl di 23 offset, 'spike, non plateau'. Questa lente")
|
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(" 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(" 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} "
|
print(" Le ultime due righe sono il taglio CONGIUNTO su SKH01 E XS01 (i due sleeve che il")
|
||||||
f"{'delta appaiato':>16}")
|
print(" progetto misura come piu' fortunati / piu' recenti): e' il caso peggiore onesto.")
|
||||||
for mult in (1.00, 0.66, 0.50, 0.33):
|
print(f"\n {'taglio drift':>21} {'config':>16} {'leva':>6} {'J':>7} {'J del LIVE':>11} "
|
||||||
dmt = (("SKH01", mult),)
|
f"{'delta appaiato':>17}")
|
||||||
|
for dmt in ((("SKH01", 1.00),), (("SKH01", 0.66),), (("SKH01", 0.50),), (("SKH01", 0.33),),
|
||||||
|
(("SKH01", 0.50), ("XS01", 0.50)), (("SKH01", 0.33), ("XS01", 0.00))):
|
||||||
|
mult = dict(dmt)
|
||||||
rows = [(w, lv, objective(w, lv, "HYRO", ev_idx, fu_idx, drift_mult=dmt))
|
rows = [(w, lv, objective(w, lv, "HYRO", ev_idx, fu_idx, drift_mult=dmt))
|
||||||
for w in top_w for lv in LEVS]
|
for w in top_w for lv in LEVS]
|
||||||
w_, lv_, o_ = max(rows, key=lambda x: x[2]["J"])
|
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,
|
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"])
|
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",
|
dd_, sd_ = paired_delta(w_, lv_, {"TP01": 0.75, "SKH01": 0.25}, lvL, "HYRO",
|
||||||
ev_idx, fu_idx)
|
ev_idx, fu_idx, drift_mult=dmt)
|
||||||
print(f" {mult:>13.2f} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {oL['J']:>11.3f} "
|
lab = " ".join(f"{k.replace('01','')} x{v:.2f}" for k, v in mult.items())
|
||||||
|
assert abs(dd_ - (o_["J"] - oL["J"])) < 0.05, ( # guardia contro l'errore di sopra
|
||||||
|
f"delta appaiato {dd_:+.3f} incoerente con J {o_['J']:.3f} - {oL['J']:.3f}")
|
||||||
|
print(f" {lab:>21} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {oL['J']:>11.3f} "
|
||||||
f"{dd_:>+11.3f} +-{sd_:.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(" 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'.")
|
print(" un confronto onesto: entrambe le colonne perdono, la domanda e' quale perde di piu'.")
|
||||||
|
|||||||
Reference in New Issue
Block a user