111 Commits

Author SHA1 Message Date
Adriano Dal Pastro b691f48f43 docs(diary): incident 2026-07-09 — "BOOK LIVE conto offline" = cert Traefik di default
Traefik auto-upgrade (latest+Watchtower -> 3.7.7) ha scartato il resolver ACME
per acme.json a 660 (3.x pretende 600) -> cert self-signed su tutto il VPS ->
DeribitRead SSLError -> book online=False. Zero trade persi (target flat, gate
di sicurezza OK). Fix: chmod 600 acme.json + restart; pin traefik:3.7 nel compose.
Diario con diagnosi, verifica end-to-end e runbook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:09:41 +00:00
Adriano Dal Pastro 822aa1307e research(crt): video-claim "CRT top-down 74% win rate" SCARTATO — il 74% e' un knob, non un edge
Meccanizzato e falsificato il claim ICT/SMC top-down (H1 setup CRT -> M15/M5
conferma -> entry, uscita parziale+BE+runner) su BTC/ETH certificati.

- Setup H1 CRT gia' triplo-refutato (onda 2026-07-02); qui testato l'angolo nuovo:
  la gestione d'uscita e il "74% WR".
- WR reale 30-37% a RR 1.5-2, SOTTO il null gambler's-ruin 40% -> il ritest tocca
  il target meno di una moneta (conferma "il ritest e' informazione negativa").
- Il 74% si fabbrica avvicinando il target: sweep rr1 0.5->2.0 = WR sale, expectancy
  R INVARIANTE e negativa (-1.2..-3.3R netto). DSR 0.000; a fee 0 ancora negativa
  -> non morte-per-fee, l'edge lordo non c'e'.
- Non eseguibile pulito a $600 (3-4 ordini/trade, alcuni sub-min-order).
- Regola candidata: convertire ogni claim "WR X%" da schema parziale+BE in
  expectancy R netto fee (WR ~= 1/(1+rr1), non un merito).

Nessuna modifica a src/config/live/tests. Book e pesi INVARIATI.
Diario: docs/diary/2026-07-07-crt-topdown-74winrate.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 06:02:38 +00:00
Adriano Dal Pastro cf7de40dc0 feat(live): cap/asset dinamico = equity/2 — operazionalizza la decisione frontier (inerte a $600)
Il cap notional per-asset non e' piu' fisso a $300: con max_notional_per_asset_frac
in config diventa equity/2, cosi' cresce col capitale e un deposito futuro non resta
strozzato (frontiera 2026-07-03). Guardrail: dinamico SOLO con equity reale fidata;
su fallback/offline si torna al cap fisso (protezione downside quando E e' ignota).
Live dry-run: cap $299 a equity $598 -> inerte oggi. Suite 172 passed (+4 test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 09:42:13 +00:00
Adriano Dal Pastro eef200cf14 research(frontier): frontiera onesta del book — il 6% e' un miraggio di regime, gira gia' alla vol nativa
Misura (non ricerca segnali) della frontiera CAGR/DD/P-rovina vs
target-vol, pesata per confidenza per-sleeve, a 2k/5k. 7 agenti (3
filoni + refuter fat-tail + scettico), sanity bit-exact dei due book.

Reframe decisivo: il "6% attuale" NON e' un target, e' la vol realizzata
in risk-off; a lambda=1 il book LIVE 2-sleeve gira gia' a ~11% vol/9.4%
DD -> "saltare a 10%" e' assumere non-risk-off, non aggiungere leva.

- Target-vol fidato book LIVE (TP01+SKH01, unico eseguibile <20k):
  ~10% (banda 8-11%, lambda ~0.9). Scale-invariante: stesso % a 2k/5k.
- P(rovina-50%) e' la metrica SBAGLIATA (slack a 22%); il vincolo che
  morde e' P(DD>30%), super-lineare. Muro onesto ~12% (gap-through SKH
  reale non nei rendimenti modellati; 2-sleeve 4x crash-sensibile).
- Vol differenziata-per-confidenza REFUTATA: taglia la diversificazione;
  la bassa fiducia va nel DE-MEAN (haircut media), non nella leva.
- Reward onesto (HOLD<<FULL): ~EUR 0.3-0.7/g@2k, 0.8-1.8/g@5k; warm-up
  vs 6% risk-off = ~+EUR 0.2/g@2k. EUR 50/g resta ~130k (capitale+tempo).
- UNICA azione config (proposta, NON applicata): cap $300 -> equity/2,
  altrimenti a 5k il cap raffredda paradossalmente il book sotto il punto
  fidato (6% vol ceiling).

config/live.json NON toccato. Book invariato. 168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 08:43:59 +00:00
Adriano Dal Pastro 116abf5203 docs(diary): snapshot stato completo del progetto (2026-07-03)
Foto d'insieme dopo il blocco di ricerca 1-3 luglio: book live
(TP01+SKH01 flat, $598), portafoglio research 5-sleeve (de-luckato
HOLD ~2.0), anchor-audit completo 4/4, edge morti da non ri-testare,
~10 gate anti-illusione codificati, mappa capital-scaling 2-5k,
aperti/prossimi passi. Punto di riferimento unico dello stato.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:16:17 +00:00
Adriano Dal Pastro 26f8d27a61 research(wave-0703): migliora+proteggi VRP01 — 7 filoni, 0 miglioramenti, anchor-audit VRP01 chiuso (4/4 sleeve)
Goal: migliorare la strategia short-vol (famiglia Albimarini/VRP01) e
proteggerla dai DD. Workflow 26 agenti (7 filoni + 2 lenti avversariali
+ scettico incrociato). Esito: NON migliorabile; la protezione DD si
compra SOLO con la size.

- Griglia 288 strutture: nessuna batte VRP01 (DSR 0.000; meta' griglia
  = 3a occorrenza "0-perdite/Sharpe implausibile" dopo CC01/ALB-A).
- 4 overlay DD (exit-spike/SL-MTM/ala-coda/cooldown): 4/4 REFUTED dal
  null de-levering — la protezione crash vive gia' nel gate IV-rank.
- Gate nuovi: 4o fallimento su 4 (l'alpha e' il binario IV-rank>0.30).
- Sizing: 12% deploy ~ 0.27 Kelly onesto (anti-rovina); disambiguazione
  unita' obbligatoria vs 12% peso book (0.014 Kelly, fattore 19x).
- Gate term-structure VIX/VXV su SPX (dSh +0.90, DSR 0.992) = confound
  di modello al 100% -> nuova regola: riprezzare term-structure-consistent
  prima di credere a un gate vol su strutture BS-flat.
- ANCHOR-AUDIT VRP01 CHIUSO: primo sleeve SENZA luck (fase canonica =
  peggiore delle 7 -> numeri di ammissione conservativi). Audit anchor
  ora completo su 4/4 sleeve ancorati.

Book/pesi INVARIATI. Nessun nuovo sleeve. 168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 07:05:19 +00:00
Adriano Dal Pastro 76120b59c2 research(wave-0702bis): ondata video-claims — Elliott 3/3 e Albimarini 2/2 scartati, mappa capital scaling 2-5k
Sei agenti, nessun sopravvissuto:
- ELL-A range-cycle: rumore (0/24 Bonferroni; nessuna cella weekly regge
  a tutte le 7 ancore). Lezione pandas: resample("7D", origin) IGNORA
  origin -> usare "168h" per le bande d'ancora weekly.
- ELL-B Fibonacci: l'edge apparente e' la POSIZIONE dei livelli, non i
  numeri (null location-matched: pctl 0.39-0.68); confluenza FAIL 4/4.
- ELL-C canale: Donchian travestito (non batte il Donchian equivalente,
  DSR 0.685, IS 1.40 -> HOLD -0.87; target 1.618 = caso; anchor-luck 4h).
- ALB-A diagonale: il condor stessa-scadenza la batte a ogni f; senza
  gate IV-rank tutte le strutture perdono (3a conferma: l'alpha del VRP
  e' il gate); fee-negativa su Deribit a qualsiasi size; 2o caso
  "0-perdite = Sharpe implausibile" dopo CC01.
- ALB-B claims: 82%/PF 5.16/"420%" consistente con zero skill (P=20-45%,
  78.6% delle finestre 6-mesi lo produce); replay con code reali =
  rovina 1998/2002/2020; la diagonale passa il 12-40% della perdita naked.
- Capital scaling 600->2-5k: unico vincolo binding = cap $300/asset
  (a 5k book al 49% del target) -> AL DEPOSITO alzare a equity/2;
  min_order $5 lasciare; XS01 ~20k confermata; aspettativa onesta
  de-luckata 2k ~EUR 0.6-0.8/g, 5k ~EUR 1.4-2/g.

Nessun nuovo sleeve, book live invariato. 168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 23:31:38 +00:00
Adriano Dal Pastro a74cc69583 research(anchor-audit): timing-luck confermato su XS01 e SKH01 — 3/3 sleeve ancorati, book de-luckato HOLD ~2.0
Chiude il pendente dell'ondata timing 2026-07-02. Due audit indipendenti
(sanity replica bit-exact, ancore a priori, zero tuning per-fase, bootstrap):

- XS01 (10 fasi ciclo H=10): fortuna nel DD (15° pctl: 10.8% vs 15.5% tipico,
  29% peggiore) e FULL (85°), non nell'hold-out (65°); P(spike)~0.91-0.94.
  Lens onesta = ensemble di fase FULL 1.25 / HOLD 1.31 / DD 11%. Ammissione
  @15% regge, i numeri 1.50/1.71/11% no.
- SKH01 (23 offset griglia 230m/690m): canonico = 93-98° pctl di OGNI metrica,
  minHold/blend/book-HOLD = massimo dei 23; il gate DD<30% (criterio di
  selezione V2-DD) fallisce in 15/23 offset. Regge: uplift blend positivo a
  tutte le 23 fasi (min +0.18) + corr ~0.08 -> ADDS ridimensionato. Path live
  reale (cron orario + exit software): book FULL 1.46->1.19 / HOLD 1.64->1.15 /
  DD 18->25%, gap-through-stop nei crash (sl2% -> -11/-23%).
- Book 5-sleeve: HOLD 2.46 eredita ~+0.10/+0.17/+0.5 di fortuna d'ancora
  (TP01/XS01/SKH01) -> stima de-luckata HOLD ~1.9-2.1, FULL ~2.0-2.2, DD ~6%.

Nessun cambio operativo (pesi/book live invariati; ogni cambio passa
weights_tilt_null). Narrativa aggiornata (CLAUDE.md, docstring skyhook).
Follow-up: anchor_luck_band() in altlib, cadenza 230m, peso SKH live.
168 test verdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:34:35 +00:00
Adriano Dal Pastro 73d74c5e53 research(wave-0702): ondata timing + CRT — 8 filoni, 0 nuovi sleeve, finding anchor timing-luck TP01
Goal: "altre strategie su Deribit con timing differenti". 8 filoni multi-agente + scettico:
- event-clock bars, expiry calendar Deribit, clock lenti/bande, regime-speed: SCARTATI
- CRT (Candle Range Theory) base/multi-TF/contesto: SCARTATA 3/3 (DSR~0, ritest =
  informazione negativa; sottoprodotto: FOLLOW>FADE sui livelli prior-day ogni anno,
  conferma il lead prevday)
- FINDING (confermato da scettico indipendente): hold-out 0.31 di TP01 = migliore delle
  24 ancore orarie (mediana 0.04, banda [-0.13,+0.30]) -> narrativa corretta in CLAUDE.md
  e docstring: l'hold-out non risolve l'edge di ritorno, regge il taglio DD a ogni ancora.
  Tranching K=2/4 = solo varianza della stima, no deploy a $600. Audit d'ancora pendente
  su XS01/SKH01. Book live e portafoglio INVARIATI. Test 168/168.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:12:22 +00:00
Adriano Dal Pastro e6657fcb16 feat(portfolio): GTAA01 promosso a 5° sleeve @20% — FULL 2.12→2.24, HOLD 2.21→2.46, DD 7.8→6.2%
Il diversificatore strutturale validato il 2026-06-22 (trend difensivo equity
6-ETF su IB, 30y storia, OOS 2015+ indipendente dall'hold-out crypto, corr al
book ~+0.10) era rimasto in paper_combo senza mai essere valutato come sleeve.
Valutazione onesta (r0701_gtaa_5th_sleeve): uplift positivo in-sample e su
TUTTE le finestre disgiunte (+0.05/+0.19/+0.25), multi-cut +0.21..+0.25,
plateau monotono w10-30% — passa dove EW-STR era morto. Ingresso @20% (IS-best
30%, scelta strutturale dichiarata). Convenzioni: weekend equity=0 (capitale
IB fermo, non riciclato), attivazione all'era book 2019-03. Il book live
Deribit (TP01+SKH01) NON cambia. Suite 168/168.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:31:38 +00:00
Adriano Dal Pastro 491411ac77 research(wave-0701): 6 filoni multi-agente — 0 nuovi sleeve, pesi confermati, gate weights_tilt_null
Ondata onesta su angoli non coperti: funding-TS (chiude il filone funding su 3
lati), breadth alt (non-ridondante ma DSR 0.43, rivisitabile con storia),
XS-residmom (REDUNDANT), pesi+guardia-DD (EW-STR refutato dallo scettico come
selezione-sull'hold-out di 2° ordine, firma best-of-15), VRP-refine (filone
esaurito), stagionalità-XS (morta allo step statistico).

Lezione codificata: weights_tilt_null + combine_outer in src/portfolio
(ogni cambio-pesi vs null di tilt casuali cap-respecting + delta in-sample>=0);
5 test nuovi, suite 165/165.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:21:59 +00:00
Adriano Dal Pastro ccf5e38101 feat(dashboard): banner alert operativi del book live (SKH/posizione/equity)
Il dashboard non mostrava nessuno dei tre segnali di health introdotti nei
commit 31369b3 (skh_error) e 5670469 (pos_error/eq_fallback): finivano solo su
Telegram + log cron, invisibili a chi guarda il monitor. pos_error/eq_fallback
erano gia' in shadow_report (usato dal dashboard) ma ignorati dal template;
skh_error non era nemmeno recuperato (il dashboard usa shadow_report, non
book_report).

Fix:
- _alerts_banner(): helper puro (verde "nessun alert" se pulito, rosso con una
  riga per errore) che rispecchia i tre alert di book_execute.
- build(): raccoglie pos_error/eq_fallback dallo shadow gia' fetchato + skh_error
  da book_report(offline=True) (feed certificato, nessuna rete extra).
- html(): renderizza il banner in cima alla sezione ① LIVE.
- tests/test_dashboard.py: +4 (verde, 3 alert, parziale, chiave-ignota).

Suite 160/160. Render end-to-end verde (conto sano $598.06 flat). Chiude la
copertura: i 3 pattern di errore silenzioso ora visibili su log + Telegram + dashboard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 22:47:35 +00:00
Adriano Dal Pastro 567046953d fix(book): gate fail-safe posizione + diagnostica equity — niente errori silenziosi nel path live
Terza+quarta chiusura del pattern "eccezione ingoiata -> stato safe silenzioso"
in src/live, dopo skh_error (31369b3). Emerse durante la verifica del gate SKH01.

Opzione A (gate fail-safe posizione):
- shadow._positions: se la read della posizione reale Deribit lancia, assume flat
  MA ora ritorna un pos_error esplicito (prima solo una note mai propagata).
- Propagato shadow_report -> book_report -> book_execute: se ONLINE ma posizione
  IGNOTA, l'esecutore NON opera a cieco (return + alert), come gia' per 'online'.

Opzione B (diagnostica equity, no halt):
- shadow._equity/shadow_report: se ONLINE ma equity reale non leggibile, il book
  ripiega su paper_cap (~$2000) invece del conto reale (~$598) -> sovradimensiona
  ~33%, ma l'hard-cap $300/asset limita il downside. Nuovo flag eq_fallback ->
  book_execute stampa warning + alert Telegram MA prosegue (niente gate: la scelta
  e' solo diagnostica, l'hard-cap gia' protegge).

Test: +8 (4 gate A, 4 diagnostica B). Suite 156/156. Path live pulito
(skh_error/pos_error/eq_fallback = None). Diario 2026-07-01-book-live-error-surfacing.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 22:39:59 +00:00
Adriano Dal Pastro 31369b358c fix(book): esponi skh_error nel book live — niente flat SKH silenzioso
book_report scriveva skh_error in un dict locale MAI incluso nel return ->
r.get("skh_error") era sempre None. E book_execute non lo leggeva comunque.
Risultato: se il feed SKH (fresh_5m) fallisse, il book forzava SKH a flat in
silenzio, indistinguibile da un flat legittimo -> entry SKH reale mancato,
nessun alert.

Fix:
- src/live/book.py: skh_error come variabile esplicita, esposta nel dict di
  ritorno (None normalmente). Il fail-safe (SKH->flat, TP01 indipendente sul
  suo feed certificato) resta invariato.
- scripts/live/book_execute.py: emette la riga di log + alert Telegram quando
  skh_error e' presente.
- tests: book_report cattura-e-flagga l'errore; book_execute lo fa emergere
  (log + notify). Suite 148/148.

Contesto: verifica del gate SKH01 dopo 193 run flat dal 06-23 (gate SANO —
335/341 entry storici, shorta i crash; flat legittimo: ultimo entry 06-06
chiuso ~06-08 pre-arming). Questo chiude il rischio latente scoperto durante
la verifica.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 22:26:02 +00:00
Adriano Dal Pastro 88f5f5a02a docs(memory): CLAUDE.md — completa il log dei filoni 2026-06-29 (1ª ondata A/C/D)
Aggiunge il bullet riassuntivo dei filoni della prima ondata del 29-06 (gia' nei diari
ma mancanti dal log curato in CLAUDE.md): A DVOL-direzionale=HEDGE, B intraday ERM=falso
positivo (gia' coperto dal gate), C xsec-v2 low-vol=debole/STAT-MODE, D macro-gate=ridondante.
Memoria curata ora completa per la sessione 2026-06-29.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 21:29:37 +00:00
Adriano Dal Pastro ee82e0a056 feat(dashboard): box forward-monitor STATARB-RESID (lead ortogonale+eseguibile)
Aggiunge il forward-monitor STATARB-RESID al dashboard accanto a PREVDAY (sezione
③·c FORWARD-MONITOR): carica data/paper_statarb/state.json, mostra doppio libro
MODELED/REAL-$600, ret/maxDD/fill-haircut, posizione spread corrente e giorni forward.
Warn aggiornato: LEAD sotto deflated-Sharpe -> forward per confermare l'edge, non deploy.

Smoke-test html() OK (box presente, dati live). Test 146/146.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 21:20:56 +00:00
Adriano Dal Pastro c52e0ab3f8 feat(forward): cabla STATARB-RESID nel forward-monitor PAPER (lead ortogonale ETH/BTC)
Forward-monitor del LEAD dello sweep 2026-06-29 (relative-value ETH/BTC, dollar-neutral 2 gambe),
il primo stream insieme ORTOGONALE (corr->book 0.027, beta-mkt 0.013) ED eseguibile a $600.

- scripts/live/paper_statarb.py: forward-only, doppio libro MODELED($2000)/REAL-$600 (haircut fill),
  riusa il segnale ESATTO di orthogonal_signals.py (niente reimplementazione). Config CONGELATA
  W=45 sgn=+1.
- Cablato in scripts/cron_daily.sh accanto a paper_prevday. Stato runtime in data/paper_statarb/
  (gitignored).
- test tests/test_paper_statarb.py (frozen config + advance forward/idempotente + haircut $600 basso).

Correzione di etichetta (verificata): la cella vincente e' sgn=+1 -> NON mean-reversion ma
relative-MOMENTUM sul residuo (dislocazioni ETH-vs-BTC continuano a 1d; sgn=-1 perde -1.4 IS).
Diario + CLAUDE.md aggiornati. Test 146/146. Nessun deploy, forward-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 20:58:29 +00:00
Adriano Dal Pastro cff5fa2bf5 research(sweep): 5 thread paralleli — 0 nuovi sleeve, STATARB-RESID LEAD ortogonale+eseguibile
Ricerca onesta su aree inesplorate (harness altlib+xsec_v2_nonmom, tutti i gate incl.
study_family_honest anti-selection-on-holdout). Branch main, nessun impatto live, test 143/143.

1 XSEC low-risk cousins (MAX/idio-vol/Amihud) -> 1 LEAD (IVOL), STAT-MODE, DSR 0.37<0.95
2 XSEC momentum-structure vs XS01            -> tutto REDUNDANT (sostituire XS01 distrugge hold)
3 Meta-allocazione dinamica (4 sleeve)       -> pesi fissi vincono (gia quasi risk-parity)
4 Segnali ortogonali ETH/BTC (2 gambe)       -> STATARB-RESID + DVOLSPREAD LEAD
5 1-gamba a segnale (MACD/RSI/Supertrend/...) -> 0/12 earns_slot (trend=TP01, MR morta, hedge)

LEAD principale STATARB-RESID (mean-rev residuo ETH-b*BTC, OLS rolling, 2 gambe): primo stream
INSIEME ortogonale (corr->book 0.027, beta-mkt 0.013) ED eseguibile a $600 (haircut ~0, NON
STAT-MODE) -> cadono i 2 muri di XS01/opzioni. Resta solo il muro dell'edge (Sharpe 0.84,
DSR 0.929 same-sign <0.95). Causalita+fee verificate dal coordinatore. Forward-monitor, non sleeve.

Soffitto direzionale ~1.3 riconfermato. Diario 2026-06-29-strategy-search-5threads.md, CLAUDE.md agg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 20:50:33 +00:00
Adriano Dal Pastro 02d875b07b merge(research): equity IB screeners + 4 filoni crypto 2026-06-29 + gate selection-on-holdout
Ricerca onesta, branch separato (nessun impatto sul book live). Test 119/119 verdi.

Equity (IB/Yahoo):
- scalping 'sottoquotate' su IB + check dati dalla rete (forward, edge non provato)
- screener short 'fond/news neg ma prezzo su' (forward, edge non provato)

Crypto BTC/ETH + universo HL (harness altlib, causale, fee 0.10% RT, marginal vs TP01):
- A DVOL direzionale  -> LEAD hedge/DD-dampener, NON sleeve
- B Intraday ERM      -> falso positivo: earns_slot da selezione-sull'hold-out + coda 2026
- C Cross-sectional non-mom (low-vol HL) -> DEBOLE/forward-monitor (deflated-Sh 0.13) STAT-MODE
- D Macro regime-gate -> RIDONDANTE col trend (corr->TP01 0.989), SCARTATO

Harness indurito (LESSON 4 in altlib): deflated_sharpe + select_cell_insample +
study_family_honest -> chiude il punto cieco "selection-on-holdout".
2026-06-29 20:09:18 +00:00
Adriano Dal Pastro b4ec92734c research(intraday): de-bias del lead ERM (filone B) — falso positivo + gate selection-on-holdout
L'analisi di robustezza affonda lo "earns_slot=True" di ERM: era prodotto da
selezione-sull'hold-out + coda 2026 + multiple-testing non corretto.
  A) deflated-Sharpe FAIL: 0.00 (tutti 122 trial) / 0.16 (no-TOD) / 0.24 (solo-ERM) << 0.95
  B) selezione in-sample-only -> ALTRA cella (long-flat, corr->TP01 0.53) = NEUTRAL, no slot
  C) ensemble del plateau (no cherry-pick) -> ADDS ma robust_oos=False -> no slot
  D) uplift FULL solo +0.10, negativo 2021/2022; uplift HOLD +0.30 concentrato nel 2026
=> ERM SCARTATO come sleeve. Conferma ennesima del soffitto BTC/ETH-direzionale ~1.3.

Lezione CODIFICATA in altlib (LESSON 4, test in tests/test_harness_realism.py):
  - deflated_sharpe()       Bailey & Lopez de Prado, PASS >= 0.95
  - select_cell_insample()  scelta cella col solo Sharpe pre-HOLDOUT (no peeking)
  - study_family_honest()   gate combinato: earns_slot[cella in-sample] AND DSR>=0.95
Regola: una strategia direzionale grid-searched si giudica con study_family_honest,
non chiamando study_marginal sulla cella a max hold-out. Verificato end-to-end su ERM
(earns_slot_honest=False). Chiude il punto cieco gemello di CC01.

Diario aggiornato (verdetto downgrade), CLAUDE.md aggiornato. Test 119/119 verdi.
Nessun impatto live (branch separato).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 20:04:36 +00:00
Adriano Dal Pastro aad69f9790 research(crypto): 4 filoni 2026-06-29 — ERM lead sub-daily (forward), 3 scartati/deboli
Ricerca onesta su BTC/ETH + universo HL, branch separato (nessun impatto live).
Harness condiviso altlib (causale, fee 0.10% RT, marginal vs TP01, day-boundary,
haircut $600). Test 19/19 verdi.

- A DVOL direzionale  -> LEAD hedge/DD-dampener, NON sleeve (buy-the-fear; is_hedge).
- B Intraday ERM 8h   -> LEAD forte / forward-monitor: earns_slot=True, ADDS oltre
                         SKH01 (TP01+SKH+ERM 60/25/15 FULL 1.88/HOLD 1.46/DD 8.9%).
                         Caveat: plateau hold-out single-row, multiple-testing non
                         deflazionato, exec 8h. Controllo TOD = FAIL atteso.
- C Cross-sectional non-mom (low-vol HL) -> DEBOLE/forward-monitor (deflated-Sh 0.13,
                         storia 2.5a, non eseguibile $600) STAT-MODE.
- D Macro regime-gate -> RIDONDANTE col trend (corr->TP01 0.989), SCARTATO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 19:48:36 +00:00
Adriano Dal Pastro a158d0e2ae research(equity): screener short 'fond/news neg ma prezzo su' (forward, edge non provato)
Goal chiarito: short su titoli con fondamentali/notizie negativi ma prezzo in salita.

Gate dati (v2.0.0): NON backtestabile -> fondamentali da rete = snapshot correnti,
applicarli a prezzi passati = look-ahead. Come la term-structure: solo screener forward.

Costruito screener da dati di rete tokenless: fondamentali strutturati Yahoo
(quoteSummary via crumb: recommendationMean/surprise/revGrowth/sell-skew) + sentiment
headline + momentum 1m/3m. SHORT cand = (fond/news neg) AND prezzo su. Run live oggi:
nessun candidato (mercato in flessione ampia -> gamba 'prezzo su' non scatta).

Intuizione chiave: shortare la FORZA combatte momentum + PEAD; il rialzo 'malgrado'
brutte notizie spesso prezza info che i fondamentali trailing non hanno -> e' la
versione contrarian/rischiosa dell'anomalia. La versione pulita = short su fondamentali
deboli quando il prezzo CONFERMA (scende), non quando diverge.

Eseguibilita': borrow/squeeze/perdita illimitata/PDT 5k/IB instabile/00 -> non deployabile.

- scripts/research/eq_fundnews_short.py (+ forward log data/raw/fundnews_short_screen.parquet)
- tests/test_eq_fundnews_short.py (scoring puro offline)
- docs/diary/2026-06-26-equity-fundnews-short.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:51:22 +00:00
Adriano Dal Pastro e28176efef research(equity): scalping 'sottoquotate' su IB + check dati dalla rete
Goal: comprare azioni IB quando sottoquotate, con verifica incrociata dei dati.

1) CHECK DATI DALLA RETE (il pezzo richiesto): IB certificato (eq_*, ADJUSTED) vs
   Yahoo adjclose (sorgente rete indipendente, tokenless). Tutti CONCORDE <=1.2bps
   sui rendimenti. Teaching: un confronto naif (adjusted vs grezzo) falso-allarmava
   4/6 ticker a 30-52bps = TUTTO stacco dividendo -> ogni divergenza va SPIEGATA
   prima di gridare 'feed sporco' (v2.0.0). Strumento riutilizzabile (validatore feed
   / pre-trade price-check).

2) Scalping 'sottoquotate': NON testabile (no dati intraday) ne' eseguibile (PDT rule
   5k blocca il day-trading; IB instabile). Versione testabile = swing MR (Connors
   RSI2<10 + MA200, exit MA5): Sharpe modesto (SPY 0.75/0.70) ma NON batte il buy&hold
   (B&H hold 0.81), expo 13%, CAGR 2-5%, fee-sensitive. Niente edge schierabile.

- scripts/research/eq_meanrev_ib.py
- tests/test_eq_meanrev.py (incl. network check)
- docs/diary/2026-06-26-equity-meanrev-network-check.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:42:14 +00:00
Adriano Dal Pastro 8d559c6f33 merge(research): gamma-scalp + cash-carry + TP01×DVOL + vol-termstructure
Analisi onesta di 5 angoli (tutti su dati certificati, leak-free, netto fee,
scoring marginale vs TP01, vincoli eseguibilita' a $600):
- gamma scalping (scalp+opzioni)  -> SCARTATO (specchio del VRP, perde ogni freq)
- funding cross-sectional (FC01)  -> gia' morto (DILUTES)
- cash-and-carry (CC01)           -> premio reale ma Sharpe artefatto, STAT-MODE -> lead
- TP01 x DVOL vol-targeting       -> non migliora (de-levering, non timing)
- calendar-vol / term-structure   -> dato storico non pubblico -> forward logger (gia' su main)

Zero impatto sul codice live: solo script di ricerca + test + diari + note CLAUDE.md.
Il forward logger era gia' stato cablato in cron su main (555977d).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:28:54 +00:00
Adriano Dal Pastro 555977d987 feat(research): forward logger della vol term-structure + cron giornaliero
La storia per-scadenza non e' pubblica su Deribit -> calendar-vol non backtestabile
ora (data-first gate). Unica via: costruire il dato in avanti. Aggiunto logger
idempotente (interpola ATM IV a tenor fissi {7,30,60,90,180}g -> data/raw/vol_term_*)
+ wrapper cron giornaliero. SOLO ricerca forward: non tocca il book live ne' i dati
certificati. Analisi completa (gamma scalp/cash-carry/dvol/feasibility) sul branch
research/gamma-scalp-options.

- scripts/research/log_vol_termstructure.py + probe_vol_termstructure.py
- scripts/cron_vol_term.sh
- tests/test_vol_termstructure.py

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:27:15 +00:00
Adriano Dal Pastro 8c3868cb31 research(vol): calendar-vol non backtestabile — data-first gate + forward logger
Angolo term-structure DVOL / calendar-vol. Scan di fattibilita' PRIMA del backtest:
la storia per-scadenza NON e' pubblica su Deribit (DVOL solo 30g; trade-history IV
solo per strumenti vivi; il front rotola/espira -> serie continua front-vs-back
irricostruibile). Per la metodologia (niente edge senza OOS su dati certi) -> STOP,
niente backtest su uno snapshot.

Unica via legittima: costruire il dato IN AVANTI. Aggiunto logger forward idempotente
che interpola l'ATM IV a tenor fissi {7,30,60,90,180}g e accumula data/raw/vol_term_*.
Seminati i primi snapshot (oggi: contango lieve su BTC/ETH). Non auto-cablato in cron.

- scripts/research/probe_vol_termstructure.py (scan fattibilita')
- scripts/research/log_vol_termstructure.py (forward dataset builder)
- tests/test_vol_termstructure.py (interpolazione offline)
- docs/diary/2026-06-26-vol-termstructure-feasibility.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:18:59 +00:00
Adriano Dal Pastro 9d586eeb58 research(tp01): DVOL vol-targeting non migliora TP01 (de-levering, non timing)
Angolo ESEGUIBILE (tocca il book live): DVOL (vol implicita forward-looking) come
denominatore del vol-target invece della realizzata. Finestra comune 2021-2026.

Le varianti DVOL abbassano DD (12.3->9.2%) ma anche Sharpe FULL (0.75->0.70) e CAGR.
Controllo decisivo: realized @ vol-tgt 15% eguaglia quel DD (9.4%) a Sharpe piu' alto
(0.75) -> il taglio di DD del DVOL e' solo DE-LEVERING, replicabile meglio con un
target_vol piu' basso. Hold-out +0.06 = single-window (storia DVOL <5y), sotto la
soglia multi-cut. Gate DVOL-spike ridondante col trend (TP01 gia' flat nei crash).

Lezione: per meno DD sul live la leva e' target_vol, non un overlay DVOL.

- scripts/research/tp01_dvol_overlay.py (realized/dvol/blend/max/derisk + controllo target_vol)
- tests/test_tp01_dvol_overlay.py
- docs/diary/2026-06-26-tp01-dvol-overlay.md
- CLAUDE.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 18:56:56 +00:00
Adriano Dal Pastro 69e3517f1b research(carry): cash-and-carry CC01 — premio reale, Sharpe artefatto, non deployabile
Provato l'angolo basis/cash-and-carry (l'altro proposto; il funding cross-sectional
FC01 era gia' SCARTATO 2026-06-22). Delta-neutral long-spot/short-perp -> r=funding,
zero esposizione prezzo.

Premio di funding REALE (~+8-14%/anno aggregato, positivo ogni anno in-sample,
ortogonale a TP01). MA Sharpe modellato 11-13 = ARTEFATTO: rischi di coda fuori
dal dataset (manca il 2022; procyclico +23% 2024 -> +1.7% 2026; liquidazione/slippage
non modellati). Il mark-to-market della base (premium col) sgonfia solo 13->11 ->
il basis-from-data non e' il rischio vero. NON eseguibile a $600 (spot+perp, funding
HL non Deribit) -> STAT-MODE. LEAD da rivedere a scala, non uno sleeve.

Sottoprodotto: CC01 passa ogni gate del marginal scorer -> punto cieco (manca un
gate 'Sharpe implausibile -> rischio nascosto').

- scripts/research/cash_carry_hl.py (CC-static/gated, BTC-ETH + 19-major, basis MtM, reality-check)
- tests/test_cash_carry.py (lock del fatto economico, non dello Sharpe)
- docs/diary/2026-06-26-cash-carry-hl.md
- CLAUDE.md: riga nella sintesi di ricerca

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 18:46:14 +00:00
Adriano Dal Pastro cf72e395d3 research(options): gamma scalping (long-vol) — SCARTATO
"Scalping BTC/ETH con copertura in opzioni" = gamma scalping, lo specchio
esatto del VRP01 (long straddle ATM + delta-hedge -> incassa RV-IV).

Esito: perde ogni anno / ogni variante / ogni frequenza (Sharpe -3 a -6).
Diagnostica strutturale: a 1d IV>=RV (paghi il VRP); a 1h RV>IV gross ma il
rehedge orario paga 24x la fee di hedge -> variante peggiore. Marginale vs TP01
= DILUTES, non e' nemmeno un hedge. Muro eseguibilita': opzione BTC min $5968 >> $600.

Schiacciato tra due muri: rehedge lento = premio, veloce = fee -> nessuna
frequenza vince. Il VRP01 (lato short, gated) resta l'unico edge opzioni.

- scripts/research/options_gamma_scalp.py (harness: naked/cheap/rich, 1d+1h, diagnostica RV-IV)
- tests/test_gamma_scalp.py (lock della conclusione)
- docs/diary/2026-06-26-gamma-scalp-options.md
- CLAUDE.md: riga nella sintesi di ricerca

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 18:36:48 +00:00
Adriano Dal Pastro db738bce3b feat(live): arma il BOOK DERIBIT (TP01+SKH01 nettati in software)
Estende l'esecuzione live da TP01-only al book Deribit-only completo. TP01 e SKH01
tradano lo STESSO strumento (una sola posizione netta per conto su Deribit) -> netting
in software: un solo ordine/asset verso il target netto.

- src/live/book.py: target NETTO per asset = clamp(0.5*E*(0.75*tp_frac + 0.25*skh_sign), ±cap).
  Riusa current_target (TP01, causale) + _skyhook_positions (segno L/S, book 230m) + conto reale.
- src/live/execution.py: rebalance_signed() — reconcile CON SEGNO (long/short, flip via close+open,
  reduce reduce_only). La close resta sempre permessa (si esce da qualunque posizione).
- src/live/livefeed.py: fresh_5m() — feed 5m certificato + coda recente EFFIMERA da Deribit pubblico
  (stesso simbolo inverse, in-memory, NON scrive su disco -> dati certificati intatti; fallback al
  certificato su errore). Solo SKH01 ne ha bisogno (e' a 230m); TP01 e' giornaliero.
- scripts/live/book_execute.py: executor doppio-gate (config + --execute), disaster-SL on-book sulla
  posizione netta, log in data/live/book_executions.jsonl. Feed SKH fresco (live_feed=True).
- scripts/cron_book.sh + crontab ORARIO: book idempotente ogni ora (riconcilia al netto corrente);
  rimossa la riga live_execute.py (TP01-only) dal cron daily per non far collidere i due.
- config/live.json: ARMATO (execution_enabled=true). cap/asset $300 split 75/25, disaster-SL -30%.
  Tutto flat all'arming -> nessun ordine finche' un segnale non arma.
- tests/test_book_live.py: 20 test (sizing 75/25, cap, flip/close/reduce, parita' pesi backtest,
  gate-safety, reconcile con trader fittizio, merge/dedup feed + fallback, loader onorato). 76/76 pass.

CAVEAT: exit SKH SOFTWARE (latenza fino a fine barra 230m; solo disaster-SL on-book); TP01 scende a
peso 0.75 (max $225/asset); SKH01 resta research-grade (equity daily-step, margine DD ETH sottile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 21:43:27 +00:00
Adriano Dal Pastro 25a22fc7c1 feat(dashboard): riordino LIVE→trades→storico + trade/anno contati
- dashboard riorganizzata in 3 sezioni: ① LIVE (mainnet sola lettura) in
  alto, ② TRADES ESEGUITI (reali) + frequenza operativa al centro,
  ③ STORICO (backtest/forward simulato) in fondo (COMBO/BOOK/FORWARD come ③·a/b/c).
- book_trade_frequency() in sleeves.py: trade/anno CONTATI sui dati certificati
  (cache di modulo, una volta per processo). SKH01 round-trip BTC ~37 / ETH ~43
  -> ~75/anno combinato; TP01 turnover ~7x/anno. Card "trade/anno" + blocco freq.
- fix: collisione var `pos` nel ramo shadow-online (-> shpos) che avrebbe rotto
  la tabella posizioni se il conto fosse leggibile dal container.
- fix: turnover TP01 nan (disallineamento groupby) -> groupby posizionale, 7.2x/anno.
- 56 test pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 21:18:52 +00:00
Adriano Dal Pastro eeac97dde4 feat(dashboard): Deribit-only book panel (TP01+SKH01) + accumulation forecast
New section showing the executable Deribit-only book (TP01 75% + SKH01 25%): combined
FULL/HOLD Sharpe+DD, plus the reinvest-winnings accumulation projection (historical &
conservative CAGR, €5k→5y/10y, conservative €/day run-rate). Reuses the already-computed
sleeve daily series (no extra heavy compute). Honest caveats (bull sample, no leverage,
SKH01 not live, ~€177k for €50/day).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:43:47 +00:00
Adriano Dal Pastro c8a390d6b7 feat(portfolio): reproducible accumulation forecast for the Deribit book
scripts/portfolio/forecast_deribit_book.py — projects the Deribit-only book (TP01+SKH01)
forward by pure compounding (reinvest winnings), monthly-aligned, NO external contributions
(not a PAC). Deterministic @historical & @conservative CAGR + Monte-Carlo block-bootstrap
(median/p10/p90), plus €/day run-rate @conservative. Parametric (--capital/--years/--cons-frac).
Honest caveats baked in (bull-crypto sample, no leverage, SKH01 not live, conditional projection).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:42:14 +00:00
Adriano Dal Pastro 384b9cb0af feat(skyhook): pos_fn introspection for SKH01 sleeve (current open trade / flat)
_skyhook_positions(): replays the non-overlap entry+exit logic (TP/SL/max_bars) to the last
closed 230m bar and reports, per asset, the current OPEN trade (dir/entry/sl/tp/bars_in) or
'flat'. Wired into skyhook_sleeve(pos_fn=...) so the Deribit book report & web dashboard show
Skyhook's live position. Causal (closed bars only). +1 test. Currently flat/flat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:32:14 +00:00
Adriano Dal Pastro 160ad300be feat(portfolio): Deribit-only executable book (TP01+SKH01) + periodic rebalancing
- deribit_book_sleeves(): TP01 75% + SKH01 25% — the two directional BTC/ETH legs on
  ONE venue (Deribit), both since 2019. Excludes XS01 (Hyperliquid/stat-mode) & VRP01
  (modeled options). FULL Sharpe 1.78 / HOLD 1.17 / DD 9.4% (research).
- rebalance_sim(): realistic PERIODIC rebalancing (drift between dates, turnover cost at
  Deribit-taker ~5bps/side) vs the idealized continuous rebalance of combined_daily.
  period=1 + cost=0 reduces to continuous (tested).
- run_deribit_book.py: report — continuous vs weekly/biweekly/monthly rebal, per-year,
  accumulation €2k & $600-real, min-order $5 note. Finding: turnover is LOW (0.2-0.4x/yr),
  so monthly rebal (€7,919) ~= continuous (€7,938) — cost is negligible; daily would be
  sub-min-order fiction at $600 -> use >= weekly.
- +2 tests (rebalance_sim continuity & cost). Full suite green.

TP01 is the only live-armed leg; SKH01 is the candidate 2nd leg (validate execution code first).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:26:53 +00:00
Adriano Dal Pastro 50e2adf837 merge(skyhook): SKH01-V2-DD strategy + 4-sleeve portfolio + dashboard
Brings the Skyhook line into main:
- SKH01 dual-TF regime+breakout engine (BTC/ETH, causal, honest harness)
- 2 multi-agent research waves -> SKH01-V2-DD (asymmetric %-exits, standalone
  maxDD <30%, minHold +1.26, marginal ADDS vs TP01)
- wired as 4th portfolio sleeve @25% effective: FULL Sharpe 1.68->2.13, DD 14->8%
- dashboard shows the 4-sleeve view; tests 25 pass

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:42:15 +00:00
Adriano Dal Pastro 7eb0f67956 feat(dashboard): show SKH01 sleeve in 4-sleeve portfolio view
active_sleeves() already feeds the per-sleeve table & combined metrics, so SKH01
appears automatically. Manual touch-ups: title/docstring -> +SKH01; position label
is now sleeve-aware (the None fallback used to mislabel every pos-fn-less sleeve as
XS01's "book 19 gambe" — now XS01/SKH01/VRP01 get correct labels); footer note adds
SKH01 (quasi-orthogonal @25%, FULL Sharpe 1.68->2.13, DD 14->8%, research/forward-monitor).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:41:52 +00:00
Adriano Dal Pastro 8d1fe173f7 feat(portfolio): wire SKH01-V2-DD sleeve @25% effective -> 4-sleeve book
Add Skyhook (SKH01_V2_DD) as a portfolio sleeve. Effective weight 25%: the three
existing sleeves scaled into the remaining 0.75 keeping their 55:25:20 ratio
(TP01 41.25% / XS01 18.75% / VRP01 15% / SKH01 25%).

_skyhook_returns(): 50/50 BTC+ETH daily series of the dual-TF regime+breakout engine
(causal, net 0.10% RT), same convention as the marginal lens.

Portfolio impact (run_portfolio.py), 3-sleeve -> 4-sleeve:
  FULL Sharpe 1.68 -> 2.13 (+0.45), FULL maxDD 14.3% -> 7.8% (halved)
  HOLD-OUT Sharpe 1.63 -> 2.30 (+0.67), HOLD-OUT maxDD ~3.5% (flat)
  Positive every year 2019-26 (annual DD <=7.8%) vs buy&hold 50/50 FULL Sh 0.93 / DD 76%.

Skyhook is quasi-orthogonal (corr ~0.09 to TP01) so it lifts Sharpe AND cuts DD.
Research portfolio (fixed weights, no real rebalancing cost at $600; Skyhook daily
Sharpe is the step-marked lens convention) -> forward-monitor, not deploy.
Tests: 25 pass (skyhook 8 + portfolio 7 + vrp 4 + trend 6). Diary + CLAUDE.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:22:15 +00:00
Adriano Dal Pastro de72e3ce1f feat(skyhook): SKH01-V2-DD — asymmetric %-exits cut standalone DD <30% (2-wave agent research)
Second agent wave (skyhook-improve-v2, 14 DD-reduction families, each adversarially
verified by 2 skeptics) beats the prior winner on the only unmet goal (DD<30%).

Winner = ASYM_LS -> promoted to engine as SKH01_V2_DD:
  same signal (ptn_n=45, vola[35,95], vol_lo=0, exit-bars 24/16) but exits switched
  from ATR to FIXED-PCT ASYMMETRIC — long sl4%/tp10%, short sl2%(tighter)/tp8%.
  The tight short %-SL caps the per-trade loss that forms the maxDD in vol spikes.

Verified (sk.study, independent re-run): standalone maxDD BTC 21.4% / ETH 27.4% (<30%),
minFull +0.99, minHold +1.26, causality 0/400 both assets, fee-surviving to 0.40%RT,
marginal vs TP01 ADDS (corr 0.09, in-sample edge, robust_oos, multicut, clean-year +0.57),
blend 0.75*TP01+0.25*SKH uplift_hold +0.87; blend 50/50 full 1.84/hold 1.59/DD 10.7%.
Plateau (not knife-edge); both skeptics holds_up=high, killer=null.

Engine: per-direction short exit overrides (exit_mode_short/sl_*_short/tp_*_short),
backward-compatible (None -> symmetric, V1/intermediate-winner unchanged). +3 tests (8/8 pass).

Lessons: DD is cut by changing the exit MECHANISM (%-SL, L/S asymmetry, ensembles), NOT by
entry-only kill-switch / vol-target / cadence. PATTERN_CONF killed as overfit (knife-edge).
PCTL_DD unverified (rate-limit) and ENS_PARAM/TPSL_DD recency/hedge-loaded -> forward-monitor.
NOT yet wired to live sleeves: re-verify blend@0.25 + causality on execution code before deploy.

Includes both waves' research scripts (runs/SKH_* wave 1, runs/SKH2_* wave 2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:10:38 +00:00
Adriano Dal Pastro 8e46a62e67 docs(skyhook): diario porting SKH01 + V1 (sintesi onda agenti in aggiornamento)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:47:41 +00:00
Adriano Dal Pastro c7c07f4c35 test(skyhook): demo anchors + dual-TF alignment + causality + V1 robustness (5 pass)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:46:47 +00:00
Adriano Dal Pastro 2d8faf3896 research(skyhook): inline lever-scout -> shorts essential, regime gate matters, ptn_n=55/vol_lo=40/wider-stops lift hold-out
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:35:35 +00:00
Adriano Dal Pastro 64d98a070d feat(skyhook): SKH01 dual-TF regime+breakout engine + honest eval harness
Porting onesto del sistema ES Skyhook su BTC/ETH certificati:
- src/strategies/skyhook.py: 690m(segnale)+230m(exec) da 5m; BuzVola/BuzVolume
  Chande 0-100 (ancore demo verificate); Donchian breakout HTF; regime gate;
  composer; entries asimmetrici (uscitalong/short + stop/profit ATR) per backtest_signals.
- scripts/research/skyhook/skyhooklib.py: study (FULL/HOLD/fee-sweep/per-anno BTC&ETH),
  causality guard (0 mismatch), marginal-vs-TP01.
Baseline: BTC FULL Sh +0.91/+581%, ETH +0.64/+255%, fee-surviving, ma HOLD-OUT debole -> da migliorare.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:33:54 +00:00
Adriano Dal Pastro 237ca8da13 research(report): resoconto PROTETTO (soft-guard DD -4%) anno-per-anno -> combo + TP01 + GTAA singoli
Report che mette combo (TP01+GTAA 50/50), TP01 e GTAA sulla stessa griglia giorni-di-borsa
(esposizione 1x, come dentro al combo), applica la guardia-DD -4% a ciascuna serie e tira fuori
per anno: NL (net liquidation da $2000), DD intra-anno, rendimento, Sharpe + riga TOT con CAGR.
Combo protetto: CAGR +9.1% / DD 5.8% / Sh 1.38 (2022 -1.8%); baseline +11.3% / 8.4% / 1.48.
Aggiunto data/paper_combo/ al .gitignore (stato paper runtime, come gli altri paper dir).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 14:16:59 +00:00
Adriano Dal Pastro 856a02fcc5 research(stops): SL classici vs soft-guard -> il soft-guard vince (lo SL duro whippa nel grind)
Goal 'prova anche SL'. Test equo (trigger/re-entry sul NAV mercato). soft-guard -4% Sh 1.38/DD 5.8%
resta il migliore; trail-stop -6% valido ma inferiore (1.34/6.6%); -4% whipsaw (1.07, inMkt 42%);
stop mensile/vol inutili. Per un DD da grind, de-risk parziale > uscita totale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 13:09:43 +00:00
Adriano Dal Pastro 010d1f0733 feat(combo): paper combo NUDO vs PROTETTO (guardia-DD -4%) affiancati + dashboard
paper_combo traccia forward entrambe le versioni; dashboard mostra nudo + protetto. Guardia-DD:
de-risk 0.4x a DD>-4%, ri-rischia a -1.6% (backtest MaxDD 8.4->5.8%, 2022 -4.4->-1.8%). Opzioni
escluse (non aiutano il grind). Container ricostruito.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:59:07 +00:00
Adriano Dal Pastro 1c15c3c1be research(tail-hedge): protezione DD combo (incl. opzioni) -> vince la guardia-drawdown
Goal: sleeve/overlay protettivo per il combo (TP01+GTAA), anni tipo 2022, valutare opzioni.
Diagnosi: DD combo 8.4% e' grind-lento (2022 -4.4%), non crash -> il doppio trend gia' taglia i crash.

Test (tail_hedge_lab.py): guardia-DD -4% -> MaxDD 8.4->5.8%, 2022 -4.4->-1.8%, Sharpe 1.48->1.38,
CAGR 9.2%. Vol-target NON aiuta (2022 non e' vol-spike). OPZIONI (put/put-spread LONG su BTC/ETH,
premio BS su DVOL): sempre-on ~50%/anno -> con budget 3%/y effetto ~nullo, e nel grind 2022 sanguinano;
pagano solo nei crash secchi (stress -30%: put +25% netto). -> black-swan insurance cara, fuori
bersaglio per il 2022. A leva: guard rende il 2x sopportabile (2022 -10.9%), il 3x resta margin-call.

RACCOMANDAZIONE: aggiungere guardia-drawdown di portafoglio (no premio); opzioni solo eventuale
micro-hedge black-swan. Costo onesto del guard: -2.1pp CAGR per dimezzare il MaxDD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:55:14 +00:00
Adriano Dal Pastro 3a3bdd5c7b research(report): sim leva 1x/2x/3x combo vs TP01 (DD reale + margin-call), da 2k/5k
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:44:54 +00:00
Adriano Dal Pastro f983cc2447 research(report): resoconto anno-per-anno combo/TP01/GTAA da $2k (PnL/MaxDD/NumTrades)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:37:23 +00:00
Adriano Dal Pastro 389573e517 feat(dashboard): pannello COMBO cross-venue (TP01 Deribit + GTAA IB)
Aggiunge alla dashboard la sezione "COMBO DEPLOYABLE — cross-venue (paper)": equity paper forward
del blend 50/50 TP01+GTAA (da data/paper_combo/state.json) + posizioni azionabili IB correnti
(gtaa_weights: peso ETF + cash, asof). Nota onesta: paper rischio-zero, Sharpe ~1.5 ottimistico, il
robusto e' la diversificazione (corr 0.21, DD dimezzato); XS01/VRP01 esclusi (STAT-MODE).
Container ricostruito (codice baked nell'immagine).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:32:19 +00:00
Adriano Dal Pastro 3b552a92da feat(combo): paper-trade cross-venue TP01 (Deribit) + GTAA (IB), forward-only
L'unica cosa vera/deployabile della ricerca: diversificazione TP01+GTAA (corr 0.21, blend Sharpe ~1.5,
DD dimezzato). Si va in PAPER cross-venue.

- src/portfolio/gtaa.py: GTAA sleeve di prima classe (trend difensivo TSMOM vol-target 12% su
  SPY/QQQ/IWM/TLT/GLD/HYG). gtaa_returns() Sharpe 0.64; gtaa_weights() = pesi ETF correnti azionabili.
- scripts/live/paper_combo.py: tracker forward-only blend 50/50 TP01+GTAA (crypto compoundato su grid
  giorni-di-borsa), mostra posizioni azionabili su entrambi i venue. Solo gambe eseguibili.
- fetch_ib_equities.py --only: refresh mirato dei 6 ETF GTAA per il cron.
- cron_daily.sh: up gateway IB + refresh ETF GTAA + avanza paper_combo (dipendenza cross-venue gestita).

Init 2026-06-23: TP01 flat (risk-off), GTAA SPY13/QQQ8/IWM9/TLT17/GLD2/HYG17/cash34. Catena
gateway->refresh->paper testata end-to-end. PAPER (rischio zero), valida l'operativita' cross-venue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:26:51 +00:00
Adriano Dal Pastro 09c8bb7de8 research(cross-market): oltre SP500 (bond/commodity/indici esteri) -> niente, artefatto di confine UTC
Esteso il test crypto-lead a ZN(bond), ESTX50/DAX(Europa), NKD(Nikkei) via futures orari IB
(commodity GC/CL/HG bloccate da subscription). Test non-sovrapposto crypto[T-8h->T]->future[T->T+6h].

ES/NQ/RTY niente (gia'); ZN negativo; NKD debole (~overnight drift). ESTX50/DAX SEMBRANO fortissimi
(t_crypto 7.8, Sharpe 2.5, 3/3 anni) MA e' artefatto di confine UTC: picco a coltello a T=00:00,
morto a T=1h; GAP di 1h uccide l'effetto (Sharpe 2.45->-0.52); tutto l'edge nella singola barra
00:00->01:00 (Sh +2.93) vs ora dopo (-1.02). Firma esatta di day_boundary_robust (CLAUDE.md).

VERDETTO: nessuna anticipazione crypto->mercato sfruttabile, ne' SP500 ne' altro. Sempre co-movimento
contemporaneo (risk-beta) o artefatto di confine. Resta valido solo il diversificatore TP01+GTAA.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:12:16 +00:00
Adriano Dal Pastro c4bc336a53 research(cross-market): futures overnight non-sovrapposto -> edge ~0 su SP500, soffio su small-cap
Test ONESTO dell'idea "monitor Deribit/trade IB": entra mid-notte sul future indice, cattura il moto
SUCCESSIVO (finestre non sovrapposte, no look-ahead). Dati: ES/NQ/RTY orari da IB (fut_*_1h, ~3y).

RISULTATO: ES (S&P500) nessun edge (Sharpe ~0/neg, t_crypto 0-1.5); NQ momentum del future non crypto;
RTY (small-cap) unico con t_crypto incrementale 2.0-2.7 e crypto che aggiunge oltre il moto proprio del
future, ma Sharpe 0.4-0.5, 24 config (multiple-testing), 2.3y, per-anno incoerente (2026 negativo).

VERDETTO: l'idea NON da' edge tradabile, men che meno su SP500. Il forte crypto<->equity e' co-movimento
contemporaneo (risk-beta), non anticipazione: imposta una finestra causale non-sovrapposta e svanisce.
Il "Sharpe 5" del gap era look-ahead. RTY -> forward-monitor al piu'. Coerente col soffitto del progetto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:51:15 +00:00
Adriano Dal Pastro 55c337144e research(cross-market): "monitor Deribit/trade IB" gap = LOOK-AHEAD, edge tradabile ~0
L'idea (segnale crypto overnight -> trade indice IB) sembrava Sharpe 3.6-5.9 ma e' look-ahead:
la finestra segnale crypto [P21:00->D13:00] e il gap equity [Pclose->Dopen] coprono le stesse ore.
All'entrata (D13:00, pre-open) il gap e' gia' avvenuto -> non catturabile con l'ETF.
Decomposizione (net 2bps, sqrt252): OVERLAP gap Sh ~3.6-4.0 (artefatto) vs TRADABILE intraday
Sh -0.03..0.25 (reale, ~0, muore a costi). Conferma/rafforza "non deployabile" del workflow.
Resta possibile solo la versione futures mid-overnight (finestre non sovrapposte) -> serve dato
intraday ES/NQ, non in cache.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 11:23:18 +00:00
Adriano Dal Pastro d916520f2c research(cross-market): sweep 65-agenti crypto->mercati IB -> fenomeno gap robustissimo ma NON edge
Goal: >=50 agenti, migliore soluzione, diversi mercati e timing, su piu' anni.
Setup: 26 ETF certificati (IB) + BTC/ETH 1h; harness parametrizzato (lead overnight crypto ->
gap/intraday equity, t-incrementale, Sharpe IS/OOS, hit per-anno); workflow 416 config = 52 sweep +
12 verifica avversariale + 1 sintesi = 65 agenti.

RISULTATO: cluster fortissimo crypto-overnight -> GAP apertura equity (tutti i target risk-on).
Migliori: ETH->IWM/QQQ/XLK gap (Sh OOS 2.4-2.5, t 17), BTC->QQQ gap (Sh OOS 2.31, t 15, 9/9 ANNI).
Regge stress 10bps e OOS recente. MA due killer (verificatori concordi):
  1. NON tradabile via ETF (gap gia' all'open) -> serve future overnight (MNQ/MES), fuori dal
     capitale $0.5-2k (margin/liquidazione);
  2. e' RISK-BETA non alpha: finestra-lead ~contemporanea al gap (stesso shock macro), forza solo
     negli anni alta-vol (2022), beta implicito ~37%.
Unico ETF-tradabile (ETH->XLE intraday) crolla a 10bps (0.48->0.15), t 2.38 sotto Bonferroni/416.

VERDETTO: nessun edge proprietario deployabile a basso capitale. Migliore FENOMENO da forward-monitor
= BTC->QQQ gap overnight (9/9 anni). Coerente col soffitto del progetto. Valore: aver classificato il
fenomeno (risk-beta overnight) invece di scambiarlo per alpha.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 22:32:28 +00:00
Adriano Dal Pastro d2d535cf6a research(cross-market): crypto x mercati IB -> trovata ANTICIPAZIONE weekend-crypto -> lunedi' equity
Goal: cercare correlazioni/anticipazioni crypto<->IB. Dati cache (BTC/ETH Deribit 1h->1d; ETF eq_*).

(1) Correlazione contemporanea: crypto = risk-on (BTC ~0.32 SPY/QQQ/IWM, 0.25 HYG, 0.13 GLD, ~0 TLT).
(2) Lead-lag GIORNALIERO: NIENTE (picco k=0, rumore a |k|>=1) -> nessuno anticipa l'altro al daily.
(3) EFFETTO WEEKEND (anticipazione pulita): crypto Sab+Dom (equity chiuso) anticipa il lunedi'.
    GAP lunedi' corr +0.22/0.24 (SPY/QQQ/IWM/HYG), hit 59-62%, si RAFFORZA OOS22+ (+0.30/0.36).

Validazione avversariale:
  (A) INCREMENTALE vs venerdi': beta weekend-crypto significativo (QQQ gap t=+4.7, intr +2.9; SPY
      +4.4/+2.0; IWM +4.7/+2.7), friday_eq NON signif. -> info crypto-specifica, non momentum equity.
  (B) TRADABILE (entro Mon open, esco close, net 4bps): QQQ hit 60%, Sharpe 1.46 (OOS 1.33), long-flat
      OOS 1.91 ~+9%/yr; SPY/IWM piu' deboli ma OOS positivi.

VERDETTO: prima anticipazione cross-mercato reale. Crypto = proxy 24/7 risk-sentiment; lunedi' equity
recupera la direzione del weekend. Caveat: capacita' bassa (~52 lun/anno), tattico non cornerstone;
gap catturabile via futures IB (MNQ domenica sera) da validare. Coerente su 3 ETF (no cherry-pick).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:55:01 +00:00
Adriano Dal Pastro 67850b0dd8 research(equities): valida combo DEPLOYABLE TP01+GTAA (le due gambe eseguibili)
Combo onesto/eseguibile a basso capitale: TP01 (Deribit, gia' armato) + GTAA vt12 (IB), senza
XS01/VRP01 STAT-MODE. Finestra 2019-2026, TP01 compoundato sui giorni di borsa.

RISULTATO: corr TP01<->GTAA +0.21; blend 50/50 Sharpe 1.48 (40/60 e risk-parity 1.52) > best solo
1.25, maxDD 14%->8%. DIVERSIFICA anche da deployable.
CAVEAT: 2022 negativo (-2.64, trend whipsaw su entrambe), anni boom gonfiano l'assoluto (recenti
~0.95) -> il dato robusto e' il +0.27 di diversificazione, non il livello. Costo deployability:
crypto-pieno+GTAA 1.81 vs 1.48 (i ~0.33 persi = XS01/VRP01 non eseguibili). Cross-venue Deribit+IB.

Migliore config rischio-aggiustata EFFETTIVAMENTE eseguibile trovata post-reset. Non risolve EUR50/g
(capitale). Prossimo: paper-trade GTAA su IB (forward-only) per validare l'esecuzione cross-venue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:48:35 +00:00
Adriano Dal Pastro 437cf11199 research(equities): EQ-GTAA01 trend multi-asset + COMBO cross-mercato (diversifica il crypto)
(1) GTAA: trend difensivo long-flat su SPY/QQQ/IWM/TLT/GLD/HYG (EW sugli asset disponibili).
  GTAA lf vt12%: Sharpe 0.64 (OOS 0.89), maxDD 15% (8% sui 6-asset 2016+), corr SPY 0.64.
  Migliore sleeve equity: rischio-aggiustato > mono-SPY, DD bassissimo, diversificatore migliore.
  Difensiva (CAGR basso). Bear DD: GFC 14% vs 55%, COVID 10% vs 34%.

(2) COMBO cross-mercato: crypto (TP01+XS01+VRP01) x equity (GTAA vt12), finestra 2019-2026.
  corr crypto<->equity = +0.17 (bassissima). blend 50/50 Sharpe 1.81 > crypto solo 1.60 >
  equity 1.12; maxDD dimezzato 14%->7%. DIVERSIFICA: primo miglioramento STRUTTURALE del
  rischio-aggiustato complessivo della ricerca post-reset (diversificazione vera, non alpha).

CAVEAT: finestra crypto corta/favorevole (Sharpe assoluti ottimistici), cross-venue Deribit+IB,
XS01/VRP01 STAT-MODE -> il combo deployable reale e' ~TP01+GTAA. Non risolve EUR50/g (capitale).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:42:42 +00:00
Adriano Dal Pastro c9b89739c1 research(equities): EQ-TREND01 trend difensivo su SPY = edge difensivo REALE (analogo TP01)
Il cross-section e' morto (EQ-MOM01), ma il trend DIFENSIVO time-series su SPY regge — stesso
tipo di TP01 nel crypto. TSMOM multi-orizzonte / SMA-200 long-flat, causale, netto fee, OOS 2015+.

RISULTATO: Sharpe 0.54->0.62/0.65, maxDD DIMEZZATO (55%->~27%; nei bear lenti piu': GFC 19% vs
55%, dot-com 26% vs 49%, COVID 17% vs 34%). Plateau robusto (0.56-0.65), fee-robusto (0.48 a
0.10%/lato), basso turnover, eseguibile a $0.5-2k (switch mensile SPY/cash). SMA-200 = piu'
semplice E migliore.

CAVEAT: e' risk-management non alpha (CAGR -2/3pp); i tagli grossi sono in-sample (OOS 2015-26
quasi tutto toro -> ha seguito SPY a beta minore, ma COVID dimezzato). long-bonds TLT non convince.

Lezione cross-mercato confermata: il valore robusto e' ridurre il rischio (trend long-flat), non
battere il buy&hold. Prossimo: trend multi-asset/GTAA + diversifica la sleeve crypto?

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:37:37 +00:00
Adriano Dal Pastro 03267b8fc3 research(equities): EQ-MOM01 momentum settoriale -> NON batte SPY
Primo backtest del fronte equity. Momentum cross-sectional settoriale (9 SPDR, 1998-2026),
causale, netto fee, OOS 2015+, giudicato marginale vs SPY buy&hold (il baseline equity).

VERDETTO: nessun edge. Long-short Sharpe -0.08 (alpha cross-sectional MORTO su 27y,
decadimento post-2000 noto). Long-only ~= SPY (corr 0.85, uplift marginale ~0.00) = SPY a
beta piu' basso. Plateau stabile ~0.50 vs SPY 0.51; sugli 11 settori (2018+) peggio (0.69
vs 0.82). L'unico beneficio (maxDD 55->39%) e' del vol-target, non del momentum.

Coerente col progetto: il relative-value momentum e' morto anche in equity (come ortho wave
nel crypto). Prossimo angolo: TS-trend difensivo su SPY (analogo equity di TP01) per tagliare
il drawdown, non per battere il CAGR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:33:38 +00:00
Adriano Dal Pastro 1c0b5f1869 research(equities): apre il fronte azioni/ETF via IB — dati certificati + cache su disco
Branch dedicato. Disciplina v2.0.0: prima il dato certificato, poi la strategia.
IB paper (gnzsnz/ib-gateway) da' storia daily ADJUSTED_LAST (div+split) profonda.

- ib_equities_probe.py: sonda fattibilita' dati (profondita', adjusted, subscription).
- fetch_ib_equities.py: FETCH+CERTIFY universo -> data/raw/eq_<sym>_1d.parquet (ms epoch,
  namespace dedicato). RIPARTIBILE (salta i parquet gia' scritti) -> niente refetch da IB.
  Certifica: integrita', gap lunghi, sanita' ritorni, sanita' adjustment.
- eqlib.py: harness ricerca equity. Legge la CACHE su disco (lru_cache) MAI da IB; universi
  (11 settori SPDR + 9 classici 1998+ + broad), panel allineato, riusa lo scorer indurito altlib.

UNIVERSO CERTIFICATO (17, data/raw/eq_* gitignored = cache locale):
  9 settori classici dal 1998-12-22 (27.5y) + XLRE(2015)/XLC(2018) + SPY(1996,30y)/QQQ/IWM/
  GLD(2004)/HYG(2007)/TLT(2016). Tutti integri (monotoni, no dup, no spike>50%, gap-lunghi 0).
  Start comune: 9 classici 1998, 11 settori 2018.

Prossimo passo: prima ricerca = momentum cross-sectional settoriale, gauntlet onesto.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 21:29:11 +00:00
Adriano Dal Pastro 61180637eb research(funding-carry): FC01 cross-sectional su HL -> fragile, NON regge + infra IB paper
Onda "nuova ricerca mirata". Unico meccanismo non coperto dalle 2 ondate: carry da
funding (cashflow perp, delta-neutral). Scan dati: price-clock gia' FAIL (intraday),
Deribit ccxt 0 righe, Cerbero solo candele -> fonte = API pubblica Hyperliquid.

- fetch_hl_funding.py: 19 major, funding orario reale dal 2023-05, certificato
  (0 gap, cov 98-100%, ann +1.0% APT .. +21.6% NEAR). backoff anti-429.
- funding_carry_hl.py: book dollar-neutral short-alto-funding/long-basso, causale come
  XS01, vol-target 20%, fee 0.05%/lato. Giudizio: marginal_vs_tp01 indurito + overlap XS01.

VERDETTO: il premio esiste (carry >> anti) ma il book NON regge il gauntlet.
  FULL -0.12, HOLD -0.50, DILUTES vs TP01, in-sample edge <0.5, no multicut.
  Jackknife universo: FULL oscilla [-0.39,+0.30] togliendo UN asset -> FRAGILE/overfit.
  (preview a 17 asset era +0.62 ADDS: fortuna, mancavano NEAR/AAVE). corr XS01 -0.19
  (ortogonale, non re-skin). Meccanismo: carry-vs-momentum, gli alto-funding pompano.
  -> NON entra in portafoglio, fetcher NON in cron. Diario completo.

Infra IB (thread parallelo): gateway paper gnzsnz/ib-gateway (127.0.0.1:4002, READ_ONLY)
in docker-compose + ib_probe.py. Esito dati basis CME micro: backtest NON fattibile
(ContFuture back-adjusted, scaduti=1 barra). IB ok per esecuzione/forward, non ricerca.
.env.ibgw gitignored (credenziali paper), template in .env.ibgw.example.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 20:56:18 +00:00
Adriano Dal Pastro 745ba7d066 research(portfolio): simula PREVDAY come overlay tail-hedge su TP01+XS01+VRP01 (NON deploy)
Simulazione d'impatto (registry di produzione invariato): riscala i 3 sleeve attivi a (1-W) e
aggiunge PREVDAY a peso W; sweep W {0,5,10,15,20%}. A 10%:
 - FULL Sharpe 1.68->1.88 (+0.20), maxDD 14.3%->9.9% (-31%): la gamba short ammortizza i crash storici.
 - HOLD-OUT Sharpe 1.66->1.97 (+0.31), ret +16.7->+19.0% (DD gia' bassissimo 3.4%).
 - 10% ~ ottimo di DD: oltre, lo Sharpe sale ma il maxDD smette di scendere (solo piu' rischio short).
 - per-anno: migliora/pareggia quasi ovunque; costa solo nel toro 2021 (premio hedge), paga nel bear 2022.

Caveat: tutto IN-SAMPLE (i guadagni assumono che l'edge persista -> e' cio' che il forward-monitor
verifica); outer-join gonfia il peso effettivo 2019-20 -> l'hold-out e' il read pulito a 10%. PREVDAY
resta FORWARD-MONITOR. Lo script e' il riferimento per ri-valutare l'overlay a forward maturo.

Diario: 2026-06-21-prevday-overlay-portfolio.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 20:01:20 +00:00
Adriano Dal Pastro 043f141bf1 research(intraday): PREVDAY block-bootstrap -> coda-fortuna vs persistente (blocker #2/#3)
Chiarimento: il "top-5 giorni = 76-83%" del diario era sulle gambe REVERT scartate, non su PREVDAY
(breakout). Test su PREVDAY stesso + gamba short (= tutto il valore). Block bootstrap circolare 20g B=3000.

[A] Concentrazione: PREVDAY-full NON e' piu' coda-fortuna di TP01 (top5 22% vs 19%; 14.3% dei giorni
per il 50% del gain vs 8.0% -> piu' distribuito). MA la gamba short e' tail-dipendente (top5=130% del
netto: togliendo i 5 giorni migliori va in perdita; sono i giorni-crash).

[B] Bootstrap: full robustissimo (uplift mediana +0.28, 99% dei resample >0); hold-out regge con coda
piu' larga (uplift mediana +0.53, 93% >0, 5deg pctl appena negativo per hold-out corto + short
tail-dipendente).

Verdetto: #3 tail-luck DECLASSATO per PREVDAY-full, CONFERMATO per la gamba short (payoff grumoso, su
<10 giorni-crash/anno); #2 null-corr-zero RIDIMENSIONATO (uplift genuinamente positivo, era efficienza
relativa). Sintesi trilogia: PREVDAY = tail-hedge legittimo e bootstrap-robusto, eseguibile a taglia
reale, payoff concentrato sui crash -> candidato overlay tail-hedge, non sleeve-alpha. Forward-monitor.

Diario: 2026-06-21-prevday-bootstrap.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 19:56:11 +00:00
Adriano Dal Pastro b388c462e8 research(intraday): PREVDAY turnover-reduction (no free lunch) + long-only probe (e' un HEDGE)
La fee (~2.6%/anno) viene dai ~70 flip/anno, non dal churn sub-dollaro (da fill_haircut). Sweep
delle leve che riducono i flip a livello di segnale (buffer k, anchor multi-giorno, min-hold):
 - allargare buffer/anchor taglia fee e turnover ma l'uplift hold-out del blend cala monotono
   (k0.30->0.50->0.75 = upl 0.56->0.40->0.00); anchor multi-giorno tutto peggio (conferma anchor=1).
 - min_hold=24h e' l'unico ritocco quasi-gratis (upl 0.56->0.60) ma peggiora il DD -27%->-32%.
 - la config congelata e' gia' sulla frontiera efficiente turnover<->edge -> nessun cambio.

Bonus blocker #1: long-only vs long-short. long-only ha Sharpe standalone PIU' ALTO (1.55 vs 1.23)
ma corr a TP01 +0.64 e blend uplift solo +0.09. TUTTO il valore di portafoglio e' la gamba SHORT
(decorrelazione 0.64->0.15, uplift 0.09->0.56). PREVDAY non e' alpha: e' un HEDGE di regime-down
(costa nel toro, paga nell'orso 2022/2025-26), additivo alla flat-stance di TP01. Restano i blocker
null-corr-zero e tail-luck. Forward-monitor invariato; eventuale ruolo = overlay di tail-hedge.

Diario: 2026-06-21-prevday-turnover-and-hedge.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 19:45:54 +00:00
Adriano Dal Pastro 8514c096ea research(intraday): fill-haircut PREVDAY a basso capitale -> blocker d'esecuzione BENIGNO
Stima SUBITO (invece di aspettare il forward-monitor) quanto il fill reale a $600 erode il lead
PREVDAY, replicando i due libri di paper_prevday.py su tutto il path 1h (2019-03 -> 2026-06):
 - MODELED (continuo) vs REAL-$C (skip ribilanciamenti < $5 min-order), sweep C {600,2k,20k}.
 - HAIRCUT $600 = +0.01 Sharpe (FULL e HOLD): saltare il 98.4% dei micro-ribilanciamenti del
   vol-target non costa nulla (trade infinitesimi: fee risparmiata e tracking-error entrambi
   trascurabili; fee-drag 2.49% -> 2.39%). L'uplift hold-out del blend 80/20 regge +0.56 -> +0.55.

Conseguenza: dei 4 blocker no-deploy, il #4 (fill a basso capitale) e' SMONTATO. Restano i 3
strutturali (hedge-shaped, fallisce il null a corr-zero, tail-luck). PREVDAY resta forward-monitor.
Lezione: eseguire eval_weights_smallcap PRIMA di scartare un lead per 'fill irreale'.

Diario: 2026-06-21-prevday-fill-haircut.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 19:41:20 +00:00
Adriano Dal Pastro b5db59bea9 feat(dashboard): mostra il forward-monitor PREVDAY (lead ortogonale a TP01)
Nuova sezione "FORWARD-MONITOR — lead paper (non deploy)" nel dashboard, tra PAPER e LIVE:
legge data/paper_prevday/state.json e mostra i due libri (modeled €2k nominale vs real-$600
con min-order $5), ret/maxDD di entrambi, il fill-haircut, le posizioni correnti BTC/ETH e
i giorni/flip forward. Nota esplicita: LEAD in osservazione, NON deployato.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 19:27:27 +00:00
Adriano Dal Pastro 5cce7acfe1 live(monitor): prevday-breakout in FORWARD-MONITOR (paper, non deploy)
Il lead ortogonale a TP01 sopravvissuto all'onda intraday entra in forward-monitor (stesso
trattamento di XS01 STAT-MODE / STA05), NON in esecuzione reale.

- src/strategies/prevday_breakout.py: segnale CONGELATO (params fissi anchor=1, k=0.30, simmetrico,
  vol-target 0.20/30/2.0), self-contained. Bit-identico all'agent di ricerca (max diff 0.0):
  BTC full Sh 1.18/hold 0.92, ETH 1.09/1.42; marginal ADDS, earns_slot, corr_hold -0.01, non-hedge.
- scripts/live/paper_prevday.py: forward-only paper, traccia DUE libri — MODELED ($2000 continuo)
  e REAL-$600 (salta i ribilanciamenti < min-order $5) -> il gap = haircut di fill reale che lo
  scettico aveva segnalato. Inizializzato forward-only da oggi.
- cron_daily.sh: avanza il monitor ogni giorno.
- test: param congelati + causale + bounded + long-short. Suite intera verde.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 15:37:41 +00:00
Adriano Dal Pastro d5dd6f4b72 harness(causality): guardia look-ahead + calendar-artifact self-policing nel lab intraday
- altlib.causality_ok(target_fn, tf): online-consistency guard (ricalcola il target su un
  prefisso, la coda deve combaciare col full). eval_weights shifta la posizione ma non vede
  una feature non-causale (finestra centrata/shift(-k)/stat full-sample) -> questa sì.
- intra_score integra DUE gate prima/dopo lo scoring: causality (leak -> LEAK, squalificato)
  e day_boundary_robust (ARTIFACT-RISK -> fuori dagli slot). Effetto sul leaderboard intraday:
  open_drive + weekly_seasonality + overnight -> CAL-ARTIFACT (da soli, niente skeptic);
  prevday_range_breakout resta (ROBUST). earns_slot 10 -> 8.
- +2 test (causal-ok / leak), suite intera verde.

Il lab intraday ora auto-becca leak e artefatti-calendario che ieri richiedevano 3 scettici.
Chiude la 3a lezione harness dell'onda intraday.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 15:22:58 +00:00
Adriano Dal Pastro 4ae3b42442 harness(realism): codifica le 2 lezioni dell'onda intraday (day-boundary + small-cap fills)
Due gate nuovi in altlib.py (test tests/test_harness_realism.py, suite intera verde):

1. day_boundary_robust(target_fn, tf): shifta il confine del giorno UTC e ri-misura l'uplift
   marginale. INVARIANT (segnale di prezzo, spread 0) / ROBUST (effetto calendario vero, resta
   positivo) / ARTIFACT-RISK (uplift si inverte = etichettatura). Riproduce da solo il verdetto
   degli scettici: open_drive +0.23@00:00 -> -0.33@+8h = ARTIFACT-RISK; prevday_breakout = ROBUST.
   Decoupling chiave: il segnale vede il clock shiftato, il backtest usa il calendario reale.

2. eval_weights_smallcap(df, target, capital=600, min_order=5): salta i ribilanciamenti di
   nozionale < min_order (la finzione del micro-trading sub-dollaro che eval_weights costa come
   fee proporzionale su un overlay vol-target), riporta lo Sharpe haircut reale vs modellato.
   Vale per ogni sleeve a $600, TP01 incluso.

CLAUDE.md aggiornato (sezione HARNESS REALISM). La pipeline di falsificazione ora becca da sola
artefatti-calendario e finzioni-fee, oltre a hedge/regime-luck/leakage gia' codificati.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 14:44:20 +00:00
Adriano Dal Pastro 24565974c0 research(intraday): asse intraday/microstruttura — lead più vicino al reale ma NON deployabile
16 agenti su segnali low-turnover intraday (sessione/funding, reversione post-evento, breakout
range del giorno prima) su feed certificati 1h/15m, giudice = marginal scorer indurito + fee-sweep.
Lab: intra_score.py (wrappa study_marginal a TF scelto + turnover/fee), meta_intra.py (corr-TP01 +
per-cut), verify_intra.py (walk-forward + in-sample-null + drop-one + fee-stress).

Esito: 10/16 "earns_slot" -> 5 genuinamente ortogonali (corr<0.4). Combo dei 5: Sharpe 1.80, corr
0.17, leak-free, passa walk-forward (+0.30/+0.37 dove l'ortho dava -0.07), pre-2025 uplift +0.28,
drop-one e fee-robusto. Sembrava IL lead.

3 scettici: (1) open_drive = ARTEFATTO etichettatura UTC (shift confine 4h -> uplift negativo);
prevday_range_breakout REGGE (unico onesto, eseguibile). (2) combo fallisce il null a corr-zero
(20-24° pctl: aggiunge meno del rumore), è HEDGE (corr -0.57..-0.80 a Sharpe-TP01) + tail-luck
(80% PnL in top-5 giorni delle gambe revert). (3) robust-plateau ma null-pctl 0.20 = diversificazione
di stream ortogonale, non timing-alpha; + finzione fee micro-ribilanciamento a $600.

Verdetto: niente in live, resta solo TP01. Lead forward-monitor: prevday_range_breakout. Lezioni
harness da codificare: test shift-confine-giorno (artefatti calendar), fee discretizzata a piccolo
capitale, causality guard nel lab intraday. Diario 2026-06-21-intraday-microstructure.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 14:20:19 +00:00
Adriano Dal Pastro 62d3b23cc6 harness(marginal): indurisci marginal_vs_tp01 con la lezione dell'onda ortho (17/18 -> 1)
Lo scorer fisso-HOLDOUT + jackknife-mese era ingannabile: 17/18 book relative-value "ADDS"
su una sola finestra 2025 (ETH-bleed dove TP01 è debole). Tre gate nuovi in
altlib.marginal_vs_tp01:
  1. persistenza multi-cut (uplift a più date di taglio, non solo 2025) -> robust_oos
  2. has_insample_edge: Sharpe standalone PRE-holdout >= 0.5 (la basket faceva 0.29).
     null_pctl_* (vs asset-rumore corr-zero) restano come CONTESTO (diversification math).
  3. is_hedge: low-corr che paga solo quando TP01 è debole = hedge, non alpha.
Verdetti nuovi HEDGE/NOISE; earns_slot = ADDS + robust_oos + has_insample_edge + not hedge.

Effetto: sull'onda ortho 17/18 "ADDS" -> 1 (dvol_spread, unico con edge in-sample reale 0.57);
gli altri 16 -> NOISE/HEDGE. Un sleeve sintetico Sharpe~1.3 scorrelato resta ADDS (non rigetta
i diversificatori veri). +5 test (noise/hedge/single-regime/high-Sharpe-uncorr/in-sample-edge);
suite 37 passed. CLAUDE.md aggiornato.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 12:50:26 +00:00
Adriano Dal Pastro 0adc69a357 research(ortho): caccia all'ortogonale a TP01 — relative-value BTC/ETH reale ma NON deployabile (hedge mono-regime)
18 agenti su book market-neutral a 2 gambe BTC/ETH (eseguibili a $600, a differenza di XS01),
giudicati sul MARGINALE vs TP01 (altlib.marginal_vs_tp01), non sullo Sharpe assoluto.

Lab: ortholib.py (eval_book leak-free a 2 gambe + causalità + eseguibilità@600), ortho_score.py
(giudice), meta_ortho.py (corr mutua + persistenza multi-cut), sleeve_rv.py (curated, SELECTION-
BIASED, non deployare).

Esito: 17/18 "ADDS" -> gonfiato dall'hold-out corto fisso-2025 (finestra ETH-bleed dove TP01 è
debole). Diagnosi orchestratore: collassano a 8 bet (corr 0.43); persistenza multi-cut e selezione
walk-forward smascherano i 2025-only (kalman/xs2). Scettico indipendente: basket selection-free ha
uplift pre-2025 +0.027 = 49° percentile di asset-rumore corr-zero (matematica di diversificazione,
non segnale); corr(Sharpe-TP01, uplift) -0.87 (è un HEDGE dei drawdown di TP01); muore a 0.30% RT.

Verdetto: NIENTE in live. Resta solo TP01. Lezione: lo scorer marginale va indurito (multi-cut +
null-asset-rumore + distinguere hedge da alpha). Diario 2026-06-21-ortho-tp01-relative-value.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 12:35:48 +00:00
Adriano Dal Pastro 1afb1014c9 research(blind): 52 agenti ciechi su curve anonime BTC/ETH — orchestratore valuta PnL/maxDD, niente di nuovo regge
Flotta di 52 subagenti "esperti di segnali" su storico BTC/ETH ANONIMIZZATO (Series A/B
rebased a 100, calendario sintetico, split 70/30) — non sanno cosa siano. Ognuno scrive un
signal(df)->position causale (script o ML), tunato solo sul train. Orchestratore valuta su
PnL e maxDD nel test held-out.

Harness cieco leak-free (riusabile):
- make_blind.py: export anonimo + overlay; blindlib.py: evaluator con shift della posizione +
  GUARDIA DI CAUSALITA' online (squalifica ogni look-ahead, ML incluso); blind_eval.py CLI;
  score_all.py giudice OOS; verify_top.py (corr-al-trend, fee-stress, jackknife).
- 52/52 passano la guardia (zero leak su tutta la flotta).

Esito OOS (benchmark buy&hold: -7% PnL, 68% DD):
- top = macd (+21%, DD 11%, Sh 0.84), accel, vol_of_vol, regime_switch, rf, obv — tutti
  trend/vol-regime. Sharpe OOS ~0.84 decade dal train ~1.4. Mean-rev e ML in fondo.
- 3 scettici indipendenti: REFUTED. regime-luck (top-5 bar = 67-102% del PnL); trend-redundancy
  (HAC alpha t=+0.9..+1.5, nessuno >1.96 — TSMOM travestito); overfit (accel/vov knife-edge).

Verdetto: ri-conferma CIECA e indipendente del soffitto direzionale ~1.3. macd = classe-TP01,
forward-monitor non deploy. Diario 2026-06-21-blind-signal-fleet.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 07:05:04 +00:00
Adriano Dal Pastro f5d30d88b9 docs(claude): aggiorna l'header allo stato LIVE armato di TP01 + capitale reale ~$600
L'header v2.0.0 RESET diceva ancora 'esecuzione DISABILITATA / nessun trading live'
(stato del 2026-06-19), superato dall'arming del 2026-06-20: TP01 e' ARMATO/LIVE su
Deribit mainnet (config/live.json execution_enabled=true + cron live_execute.py --execute),
cap $300/asset, disaster-SL -30%, alert Telegram, capitale reale ~$600. Stato corrente
flat (target risk-off). Solo TP01 eseguito; XS01/VRP01 restano paper/STAT-MODE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 21:43:17 +00:00
Adriano Dal Pastro 9612560479 research(xsec): sweep cross-sectional su Hyperliquid (43 script/257 config) + verifica avversariale
Nuova harness condivisa xslib.py (panel HL certificato, score per-asset causale, book
long-k/short-k vol-targeted leak-free) + 43 script in runs/ su 11 famiglie (MOM/REV/VOL/
DIST/LIQ/VAL/STRUCT/UNIV). Scoring = earns_slot (full>0 AND hold-out>0 AND marginal ADDS
al portafoglio live AND corr XS01<0.6, con jackknife drop-one-month).

Find: 42/257 config earns_slot=True, ma TUTTE con corr TP01 -0.2..-0.4 e PnL ~solo 2025.
Verify (verify_survivors.py, 3 scettici deterministici):
 - S1 redundancy: cluster low-vol = UNA scommessa (XV01=XU02=1.00, XV02/XV03 r 0.44-0.67);
   XM09/XL02/XS06b/XR02 distinti (corr media off-diag +0.20).
 - S2 short-beta: cluster low-vol carica 0.44-0.70 su short-market -> NON market-neutral,
   e' un tilt short-alt-beta di regime. XM09(0.08)/XR02(-0.21) NON short-beta.
 - S3 per-anno: cluster low-vol decade (XV01/XU02 2026 -0.09); XL02 morto (2025 -0.14,
   2026 -0.43); XM09 (0.82/0.50/0.74) e XR02 (0.84/0.40/2.68) positivi in tutti e 3 gli anni.

Esito: nessuna sleeve nuova. Cluster low-vol RIGETTATO (regime-bet), XL02 RIGETTATO (overfit).
2 LEAD genuini (XM09 trend-gated x-sec momentum, XR02 reversal vol-gated) -> forward-monitor,
non deployabili (panel 2.5y regime unico + STAT-MODE esecuzione). Portafoglio live invariato.

Incluso anche options_vrp_managed.py (A/B VRP01 hold-to-expiry vs gestione attiva del doc
credit-spread): la gestione attiva DISTRUGGE l'edge (combo FULL managed Sh -1.29 vs HtE +0.96,
il delta-exit taglia i vincenti) -> scartata, VRP01 resta hold-to-expiry.

Diari: 2026-06-20-xsec-strategies-sweep.md, 2026-06-20-vrp-active-management.md.
gitignore: data/paper_portfolio/ (stato runtime paper) + scripts/research/xsec/runs/out/ (output rigenerabile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 21:36:57 +00:00
Adriano Dal Pastro 5ac4e16af8 research(alt): sweep 104 strategie alternative su Deribit (153 agenti) + marginal scorer
Ondata di ricerca onesta a largo spettro su BTC/ETH+DVOL certificati: 104 ipotesi
distinte (11 famiglie), un agente-finder per ipotesi, verifica avversariale a 3
scettici sui promettenti, sintesi (153 agenti totali). Esito: NIENTE di nuovo regge
-> conferma del soffitto strutturale ~1.3 BTC/ETH-direzionale; lo stack
TP01+XS01+VRP01 resta imbattuto.

- altlib.py: harness condiviso vettoriale leak-free (eval_weights/study_weights,
  fee-sweep, both-asset + hold-out 2025+). Riproduce i numeri canonici di TP01.
- MARGINAL SCORER (study_marginal/marginal_vs_tp01): Sharpe INCREMENTALE vs baseline
  TP01 (corr, blend uplift OOS, alpha residua) + jackknife OOS (clean-year +
  drop-best-month). earns_slot = abs!=FAIL & ADDS & robust_oos. Smaschera gli overlay
  su TSMOM con PASS assoluti fasulli (CMB04, VOL11, ...) e il falso positivo KAMA
  (ADDS ma muore al jackknife).
- runs/*.py (104) script riproducibili per ipotesi; wf_altstrat.js workflow.
- Verdetto: 0 candidati deployabili; 2 LEAD fragili (VOL08, STA05_LS) da forward-monitor.
- test_marginal_scorer.py blocca baseline + invarianti. Suite: 32 verde.

Diario: docs/diary/2026-06-20-alt-strategies-100agent-sweep.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 19:50:39 +00:00
Adriano Dal Pastro bf84bc91e2 feat(live): alert Telegram su esecuzione ed errori
src/live/notifier.py (stdlib, no-op se non configurato): legge TELEGRAM_BOT_TOKEN/CHAT_ID da env o
.env(.mainnet) gitignored. live_execute.py invia alert su: ordine eseguito (), ordine non
verificato (⚠️), disaster-SL piazzato/fallito (🛡️/⚠️), conto offline, e qualsiasi eccezione (🛑).
Nessun alert nei giorni flat/HOLD (no rumore). Config gia' presente in .env -> alert attivi.

Test config: uv run python -m src.live.notifier "msg". Test 28/28.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 16:09:09 +00:00
Adriano Dal Pastro 3cba5bb9d0 feat(dashboard): mostra i disaster-SL attivi nella sezione LIVE
Lo shadow espone i bracket disaster-SL aperti (open_orders filtrati per label DISASTER_LABEL,
centralizzata in deribit.py): asset, stop price, size. La sezione LIVE li mostra
("disaster-SL attivi (-30%): ..." o "nessuno (flat)"). Test 28/28.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 16:05:18 +00:00
Adriano Dal Pastro e5e2d3ec9b feat(live): disaster-SL on-book con lifecycle completo (idempotente) nel loop di esecuzione
ensure_disaster_sl(): garantisce UN solo STOP_MARKET reduce_only a ~-30% coerente con la posizione,
ad ogni run del loop, per asset:
- flat  -> cancella i bracket orfani;
- long  -> assicura lo stop (size = posizione, prezzo al tick);
- gia' coerente (1 bracket, amount~=, stop entro 5%) -> lascia com'e' (niente churn ne' gap di
  protezione fra cancel e place).

- deribit.py: open_orders (merge type all+trigger_all), disaster_stop_price.
- execution.py: cancel_order + ensure_disaster_sl.
- live_execute.py: gestione bracket ogni run, gated come l'esecuzione. Validato armato: flat ->
  disaster-SL 'flat' (cleanup), zero ordini. Test 28/28.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:47:30 +00:00
Adriano Dal Pastro 4650aa71a2 feat(live): ARMA l'esecuzione di TP01 (execution_enabled=true) + cabla al cron giornaliero
execution_enabled=true: con --execute il loop invia ordini REALI. Aggiunto al cron_daily.sh (00:30
UTC, dopo il refresh dati) lo step live_execute.py --execute. Validato armato: TP01 flat -> HOLD,
zero ordini. Da qui TP01 opera da solo sul conto reale al prossimo ENTRY del segnale.

NB: il loop NON piazza ancora il disaster-SL on-book (metodo presente, lifecycle bracket da cablare
prima del primo ENTRY). Rischio posizione comunque limitato dal cap $300/asset (~1x, no leva).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:41:03 +00:00
Adriano Dal Pastro bc9e322d0d feat(live): loop di esecuzione GATED di TP01 (execution_enabled + --execute, default OFF)
scripts/live/live_execute.py porta il conto reale al target di TP01 (min(0.5*frazione*equity,
cap/asset)): apre/riduce/chiude via DeribitTrader.rebalance_to(). DOPPIO GATE: config/live.json
execution_enabled=true (master, default false) E flag --execute; senza entrambi e' dry-run.
Reconciliation post-ordine + log in data/live/executions.jsonl. TP01 flat -> 0 azioni.

- execution.py: rebalance_to() (open/reduce/close al target); MAX_AMOUNT alzato a tetto hard
  anti-fat-finger (~$630/$430 su conto ~$600), il sizing operativo lo decide config max_notional.
- config/live.json: master switch + cap/asset $300 + min ordine $5 + disaster_sl_pct.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:37:51 +00:00
Adriano Dal Pastro a3d6b97db6 fix(dashboard): sezioni PAPER/LIVE evidenti (barra colorata) + Cache-Control no-cache
Le sezioni erano testo grigio poco visibile e il browser cacheava la pagina ('non vedo differenza').
Ora: header PAPER con barra verde, LIVE con barra rossa + sfondo rosso-tenue (separazione netta);
risposta HTTP con Cache-Control no-cache/no-store -> niente pagina stantia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:36:21 +00:00
Adriano Dal Pastro cddea50c5a feat(live): conto USDC -> strumenti lineari; entrata/uscita da Old; dashboard LIVE separato da PAPER
Correzione post-micro-test (il conto e' USDC, non BTC/ETH):
- deribit.py: INSTRUMENT -> BTC/ETH_USDC-PERPETUAL (lineari, gli unici eseguibili sul conto USDC);
  notional_to_amount gestisce i lineari (amount in base-coin = notional/price); + quantize_price;
  trade_history (read-only) per i trade reali. build_rebalance_order passa il prezzo.
- shadow.py: sizing col prezzo; espone live_trades (trade reali eseguiti su Deribit).

Entrata/uscita verificate (logica presa da Old/src/live/execution.py):
- execution.py: open() market verificato (state=='filled' + trade, fill/fee reali, filled_amount
  autorevole), close() market reduce_only (le CHIUSURE si tentano SEMPRE, senza cap), disaster-SL
  STOP_MARKET reduce_only. Cap di size SOLO sulle aperture. Fill dataclass.
- microtest.py: usa open()/close(); safe-close se l'apertura non e' verificata.

Dashboard: sezione PAPER (backtest+forward) separata da sezione LIVE (conto reale Deribit: shadow
TP01 + Trades REALI eseguiti). Test 27/27.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:15:45 +00:00
Adriano Dal Pastro c00f6016df feat(live): micro-test esecuzione REALE su Deribit mainnet (USDC linear) — round-trip validato
Primo ordine reale post-reset, a rischio ~0 ($6 notional, leva 0.011x). Scoperto che il conto e'
USDC -> strumento eseguibile = perp LINEARE BTC_USDC-PERPETUAL (l'inverse BTC-PERPETUAL fallisce
'not_enough_funds'). Round-trip BUY/SELL reduce_only verificato: fill reali, fee reali (0.0064 USDC),
posizione tornata a FLAT, costo totale $0.0071.

- src/live/execution.py  : DeribitTrader (estende DeribitRead) con market order + verifica posizione,
  GUARDRAIL hard (solo BTC_USDC-PERPETUAL, amount <= 0.0002 BTC). Niente leva per-ordine (Deribit non
  la accetta: l'esposizione la decide la SIZE).
- scripts/live/microtest.py : runner round-trip, default DRY-RUN, --live per inviare. Pre-flight ABORT
  se posizione preesistente; chiusura reduce_only; verifica ritorno a FLAT.
- src/live/deribit.py    : aggiunti spec contratto LINEARI USDC (BTC/ETH_USDC-PERPETUAL).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 15:06:53 +00:00
Adriano Dal Pastro 715f197cf2 feat(dashboard): lista trades TP01 (entry/exit dal segnale causale)
Nuova sezione "Trades TP01" nella dashboard: eventi ENTRY long / EXIT flat dedotti da
target_series sui dati certificati (data, asset, transizione di posizione, prezzo). In
src/live/shadow.tp01_trades(): account-independent (gira anche offline nel container),
ricalcolata a ogni render -> storico + forward. Empty-state se TP01 non ha mai mosso.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 14:18:46 +00:00
Adriano Dal Pastro bec2fb2089 chore(dashboard): monta .env.mainnet read-only nel container per lo "Shadow live"
Il token mainnet (sola lettura) abilita conto/posizioni REALI nel box Shadow della dashboard.
Montato a runtime, NON nell'immagine (.env.mainnet resta dockerignored). Solo letture: nessun
endpoint di trading e' raggiungibile da src/live/deribit.py. Verificato: conto reale $598.07 letto
dal container, TP01 flat -> 0 ordini.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 14:02:26 +00:00
Adriano Dal Pastro 9c48cdd884 feat(live): SHADOW MODE TP01 su Deribit mainnet (sola lettura) + dashboard 3-way
Validazione esecuzione di TP01 a RISCHIO ZERO: gira il loop live contro dati/conto/posizioni REALI
del mainnet, costruisce gli ordini di ribilancio esatti e li STAMPA invece di inviarli. Niente
testnet (e' la causa del reset v2.0.0: feed farlocco) -> shadow su mainnet reale + micro-test a
size minima come unica via per il fill (passo successivo).

- src/live/deribit.py  : client Deribit mainnet SOLA LETTURA (ticker/conto/posizioni via Cerbero MCP)
  + costruttore ordini deterministico (notional->contratti, step BTC $10/ETH $1, quantizzazione,
  delta vs posizione). Nessun metodo di trading, by design.
- src/live/shadow.py   : shadow_report() condiviso CLI+dashboard (niente drift); degrada con grazia
  se il mainnet non risponde.
- scripts/live/live_trend.py : CLI shadow (--no-net offline, --equity override). Verificato su
  mainnet reale: conto $598.07, posizioni flat, TP01 flat -> 0 ordini, parita' col paper OK.
- src/live/dashboard.py : box "Shadow live" + titolo/note al 3-way (TP01+XS01+VRP01).
- tests/test_live_shadow.py : 9 test deterministici (quantizzazione, sizing 50/50, entry/exit/None,
  parita' live==backtest). Suite 26/26.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 14:01:12 +00:00
Adriano Dal Pastro 9ed2ea4b13 fix(fetch_hyperliquid): taglia il backfill sintetico di cerbero MCP (vol=0) — universo 52->51
Cerbero MCP padda il periodo pre-quotazione su HL con barre SINTETICHE (volume 0, prezzi
copiati da Binance -> matchano cross-venue e non sono flat): asset listati dopo lo START
(es. AXS 83%, ALGO/SAND 37%) passavano i gate flat+cross-venue ed erano certificati PULITO
pur non essendo negoziabili. E' il caso v2.0.0 (edge su un book che non c'era).

Fix: il VOLUME e' il rivelatore del backfill -> (1) taglio del run iniziale a volume 0
(serie nativa), (2) gate storia nativa >=365g reali (AXS scartato), (3) gate vol=0 interno,
(4) cross-venue/flat ricalcolati solo sulle barre reali, (5) parquet scartati rimossi.

Verificato direttamente su cerbero MCP mainnet. I 19 major di XS01 hanno 0 backfill ->
strategia live invariata. Diario 2026-06-20-cerbero-backfill-fix.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 11:53:55 +00:00
Adriano c6236ed5d9 feat: integra VRP01 come sleeve del portafoglio (put credit spread + gate IV-rank)
src/portfolio/sleeves.py: _vrp_combo_returns + vrp_sleeve, self-contained in src/
(pricing BS + gate causali inline, DVOL da data/raw). Settimanale->giornaliero col
lump sul giorno di scadenza (preserva lo Sharpe annualizzato, peso costante).

Registry: TP01 0.55 / XS01 0.25 / VRP01 0.20 (TP01 resta maggioranza; VRP e' un
lead modellato, non deploy pieno). TP01+VRP01 monotono: FULL 1.30->1.44, HOLD
0.31->0.40 a peso 20%. Scorrelato a TP01 (+0.01).

Test tests/test_vrp_sleeve.py (5 pass). CLAUDE.md + diario aggiornati.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 11:24:40 +02:00
Adriano 75e1aacd19 research: analisi strategie FinanceOld + VRP v2 (defined-risk spread + gate IV-rank)
Analisi 4 progetti FinanceOld. Solo il filone opzioni-VRP backtestabile sui dati
certificati (funding-arb senza dati storici; Polybot ticks corrotti/3gg/edge=latenza).

VRP v2 porta 3 idee di OptionsAgent nel framework, causale + fee-aware:
- put credit spread (rischio definito): worst-week -16.6%->-7.4%, DD 33%->21%
- gate IV-rank>0.30: ribalta HOLD-OUT da -0.25 a +0.28 (alpha = filtro regime)
- COMBO f=1.0: FULL Sh 1.10, HOLD 0.60, DD 12%, positiva/piatta ogni anno
- blend TP01 70/30 -> Sh 1.00, DD 7% (corr +0.07)

Lead quantificato, non deploy (premio modellato ATM, serve f di stress reale).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 11:16:59 +02:00
Adriano Dal Pastro 92a63feb9c chore(monitor): cron giornaliero (refresh dati + avanza paper) + cleanup crontab/orfano
scripts/cron_daily.sh: rebuild_history BTC/ETH + fetch_hyperliquid (52 alt) + fetch_dvol +
paper_portfolio, ogni giorno 00:30 UTC -> tiene fresco il dato che il dashboard legge e avanza
il paper forward. fetch_hyperliquid END ora DINAMICO (oggi) per il refresh.

Cleanup: rimosso container orfano pythagoras-portfolio (vecchio runner pre-reset, exited);
crontab ripulito dai 4 job rotti del micro-test mainnet (hourly_report/drift/reconcile/
ledger_vs_backtest -> script archiviati in Old/), backup in logs/crontab.pre-reset.bak.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 09:06:38 +00:00
Adriano Dal Pastro 26e977d338 feat(monitor): dashboard PAPER del portafoglio attivo (TP01+XS01) + paper forward loop
src/live/dashboard.py: web UI stdlib (:8787) che mostra metriche (FULL/HOLD Sharpe, DD, CAGR),
per-sleeve, posizioni correnti, equity (backtest + paper forward), ultimo dato. Solo MONITOR,
esecuzione REALE disabilitata. scripts/live/paper_portfolio.py: forward-only del portafoglio
(StrategyPortfolio su active_sleeves), stato persistente in data/paper_portfolio (gitignored).

Dockerfile + docker-compose.yml minimali (solo servizio dashboard; runner/esecuzione restano in
Old/). Container pythagoras-dashboard ricostruito col codice nuovo (il vecchio mostrava dati
pre-reset). Mount data/ read-only. .dockerignore esclude Old/data/.venv/.git/.env.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20 08:57:55 +00:00
Adriano Dal Pastro 0d9f483131 docs: aggiorna CLAUDE.md allo stato corrente (XS01 blend+gate, portafoglio FULL/HOLD 1.55)
XS01 ridescritta con affinamenti (blend lookback [30,90] + gate dispersione p30, standalone FULL
1.50). Portafoglio attivo TP01 70% + XS01 30% -> FULL Sh 1.55 / HOLD 1.55 / DD 4.4%. Aggiunte le
lezioni: espansione universo Hyperliquid NON aiuta XS (52/top-liq/trend-multiasset tutti peggiori,
i margini sono nel segnale); lead opzioni VRP quantificato (f reale ~1.0, non deploy). Struttura/
comandi aggiornati (scripts/research track A-I + options_vrp + fetch_dvol; scripts/portfolio xsec_*).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:29:24 +00:00
Adriano Dal Pastro 87dd56a9ce feat(XS01): + gate di dispersione (p30) — portafoglio FULL 1.48->1.55, HOLD 1.06->1.55
Momentum cross-sectional vive nella dispersione; gate: entra solo se la dispersione cross-section
del momentum supera il percentile ESPANDENTE causale (altrimenti flat). Plateau robusto p15-p35
(non knife-edge: il crollo a p40+ e' over-gating); scelto p30. XS01 standalone FULL 1.10->1.50,
HOLD 1.03->1.71, DD 14%->10.8%. Portafoglio TP01 70+XS 30: FULL 1.48->1.55, HOLD 1.06->1.55, DD
4.6%->4.4%. Il gate alza SIA FULL SIA hold-out (tiene XS attivo nei regimi dispersi, flat nei bull
compatti; causale). E' il concetto del vecchio XS01.

sleeves.XS_CFG disp_pct=30; engine _xsec_returns gatea su dispersione. 12 test ok.
Diario 2026-06-19-xsec-dispgate.md. Affinamenti del segnale (blend+gate) > espansione universo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:24:04 +00:00
Adriano Dal Pastro fd5a0bd3cf feat(XS01): affina con blend di lookback [30,90] — FULL 0.80->1.10, portafoglio 1.41->1.48
Come TP01 fonde gli orizzonti, XS01 ora fonde 30g+90g del momentum cross-sectional (z-score per
lookback, mediato). Sweep: [30,90] e' il sweet spot (fonde i due singoli robusti, anti-overfit):
XS01 standalone FULL 0.80->1.10, DD 21%->14%, corr a TP01 -0.06->-0.12, 100% anni+. Portafoglio
TP01 70 + XS01 30: FULL Sh 1.41->1.48, DD 5.2%->4.6%, ~€/g 1.65->1.78; hold-out 1.15->1.06 (calo
marginale dentro il rumore). Piu' robusto (due orizzonti) + diversifica meglio -> promosso.

sleeves.XS_CFG lookbacks=(30,90), engine _xsec_returns usa lo score blended. 12 test ok.
Diario 2026-06-19-xsec-blend.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 22:19:12 +00:00
Adriano Dal Pastro bf6ade51af research: strato trend multi-asset (52 alt) RIDONDANTE col trend TP01 -> non aggiunto
TSMOM CANONICAL applicato a ogni alt dei 52, equal-weight. Standalone FULL 0.66 ma HOLD-OUT -1.03
(long negli alt nel calo 2025-26), corr a TP01 +0.74 (stessa beta direzionale). Contributo al
portafoglio NEGATIVO (HOLD -0.16/-0.27). Broadenizzare il TREND non diversifica: e' la stessa
direzionalita' su asset piu' rumorosi. Solo il market-neutral (XS01) diversifica davvero.

Chiude il filone espansione-universo (XS-52, top-liquidita' dinamico, trend-52: tutti peggiori).
Configurazione validata invariata: TP01 70% + XS01 (19 major) 30%, FULL Sh 1.41 / HOLD 1.15.
I margini reali sono in un MECCANISMO diverso (opzioni VRP), non nell'universo crypto-direzionale.
Diario 2026-06-19-trend-multiasset.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 21:17:16 +00:00
Adriano Dal Pastro 182d4eeac2 research: universo top-liquidità DINAMICO per XS — anch'esso peggiore del fisso-19 (memecoin diluiscono)
xsec_dynuniverse.py: a ogni ribilancio top-N per dollar-volume 30g causale (ragged-aware), poi XS
momentum. Esito: best dinamico top12 FULL 0.65/OOS0.54 (un anno neg) vs fisso-19 FULL 0.80/OOS1.20
(100% anni+). Contributo TP01+DYN 1.10/0.60 vs TP01+XS19 1.25/1.15. La classifica per volume ammette
i MEMECOIN ad alto volume (WIF/ORDI/JUP) erratici -> diluiscono. Liquidità != qualità.

Conclusione: ne' 52-all ne' top-liquidità dinamico battono i 19 major curati. XS01 resta sui 19.
Portafoglio invariato TP01 70% + XS01 30% (FULL 1.41 / HOLD 1.15). 12 test ok. I 52 parquet restano
per ricerca futura. Diario 2026-06-19-xsec-universe-expansion.md aggiornato.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 21:09:48 +00:00
Adriano Dal Pastro 8426d05f12 research: espandere universo XS01 a 52 asset DILUISCE (negativo) -> XS01 blindato sui 19 major
Esteso fetch_hyperliquid a 52 alt certificati (cross-venue vs Binance, flat 0%, 2024+; +gate
delistato per MKR/FXS). Ma il cross-sectional momentum sui 52 e' NEGATIVO (FULL -0.1..-0.6, k grande
non aiuta) vs +0.67/OOS0.91 sui 19 major (stessa finestra): i ~33 small-cap (WIF/JUP/ORDI/PYTH/TAO..)
sono idiosincratici/mean-reverting e rovesciano il momentum relativo. "Piu' asset = piu' robusto"
e' FALSO per l'XS momentum: la breadth utile e' quella dei major liquidi.

Fix: lo sleeve _xsec_returns usa XS_UNIVERSE esplicito (19 major), non glob-all (aggiungere parquet
certificati non lo rompe piu'). I 52 parquet restano su disco per ricerca futura, non per XS01.
Portafoglio ripristinato e invariato: TP01 70% + XS01 30%, FULL Sh 1.41 / HOLD 1.15. 12 test ok.
Diario 2026-06-19-xsec-universe-expansion.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 21:00:00 +00:00
Adriano Dal Pastro 53d0134cb1 research: calibra VRP su quote REALI cerbero-bite — f≈1.0 (non 1.29), lead DEBOLE confermato non-deploy
cerbero-bite GIA' accumula la catena reale mainnet (option_chain_snapshots, 2026-05->oggi) -> uso
quella (niente nuovo snapshotter). options_vrp_calibrate.py misura il fattore f reale su 223
snapshot/asset (put weekly delta-0.28, BID): BTC f median 1.03, ETH 0.97, skew reale +1.5..1.9 pt.
Il f reale e' ~1.0 NON 1.29 (lo snapshot singolo del branch era outlier ad alto skew). -> VRP sleeve
= punto f≈1.0 = Sharpe ~0.71 (conservativo), DD 33%, hold-out piatto: diversificatore DEBOLE (corr
+0.07) sotto TP01, coda severa. Calibrazione su ~10g densi, 1 regime calmo; f di stress non misurato.

Verdetto: la decorrelazione modesta NON giustifica il rischio di coda short-vol senza dato reale
multi-regime (serve che cerbero-bite copra un crash). Confermato NON-deploy. Portafoglio invariato
TP01 70% + XS01 30%. Diario 2026-06-19-options-vrp-lab.md aggiornato.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:38:54 +00:00
Adriano Dal Pastro 8f9ce89039 research: imposta sleeve OPZIONI VRP — infrastruttura + prima validazione (LEAD reale, non deploy)
fetch_dvol.py: storia DVOL (IV Deribit) BTC/ETH 2021-2026 -> data/raw/dvol_*. options_vrp_lab.py:
backtest CSP settimanale, premio BS su DVOL reale + calibrazione f (skew/spread), payoff sul path
realizzato, causale; gauntlet (VRP, sweep f/delta, per-anno, worst-weeks, corr+contributo vs TP01).

Esiti (book 50/50 put delta-0.28): VRP reale (BTC IV>RV 78% del tempo). Sharpe DIPENDE da f:
0.71 conservativo (IV-ATM) -> 1.70 a f=1.29 (skew reale calm). CODA severa (DD 30-33%, settimane
-15..-26% su LUNA/FTX/crash; 2022 -9%, 2026-YTD -14%). Scorrelato a TP01 (+0.07) -> migliora il
portafoglio anche a premio conservativo (TP01 70%+OPT 30%: Sh settimanale 0.71->0.97).

VERDETTO: lead reale e diversificante, MA premio modellato (non catena reale) + calibrazione
ottimistica + coda short-vol non catturata nello stress. Regola: mai short-vol da modello in
deploy. NON aggiunto. Portafoglio invariato TP01 70% + XS01 30%. Prossimo: accumulo quote reali
multi-regime + stress crash + daily-MTM + paper testnet. Diario 2026-06-19-options-vrp-lab.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:30:08 +00:00
Adriano Dal Pastro 87af03955c research: porta artefatti da strategy-research-calendar (tracks F-I + eval crypto_backtest + lead OPZIONI/VRP)
Dal branch parallelo strategy-research-calendar (continuazione della linea TP01). Porta su main il
record di ricerca + la fondazione del lead opzioni (NIENTE blob dati, niente codice in conflitto):
- Tracks F/G/H/I (seasonality/calendar, prior-levels, volume-vol, momentum-reversal): tutti
  NEGATIVI/spurii -> confermano il soffitto Sharpe ~1.3 su BTC/ETH direzionale (calendar = buy&hold
  travestito; mean-reversion morta anche a fee 0). Diari + script.
- trackD_lookahead_audit.py: audit anti-look-ahead (stesso esito del nostro fix >=12h).
- eval-crypto-backtest-options.md: valutazione strategia esterna crypto_backtest. Cross-valida TP01
  (il loro sleeve spot 12h ~ TP01: due ricerche indipendenti, stessa conclusione). Identifica il
  LEAD: sleeve income OPZIONI (vendita put settimanali delta-0.28, VRP IV>RV), scorrelato ~0.22 al
  trend -> via per superare il soffitto ~1.3.
- options_real_quote_check.py + cerbero-bite-mainnet-verified.md: VERIFICATO su QUOTE REALI Deribit
  mainnet (cerbero-bite/MCP = mainnet, bit-identico a ccxt.deribit). Premio reale (BID, con skew) =
  1.29x il modellato -> il backtest SOTTOSTIMA il premio; il rischio vero e' la CODA (short-vol) +
  liquidita' di roll in stress, non la magnitudine.

NB: lo sleeve opzioni e' un LEAD, NON deployato: prezzato da modello (BS su DVOL) + 1 snapshot in
regime calmo. Serve validazione real-chain multi-regime + stress crash + paper su testnet prima di
aggiungerlo al portafoglio. Portafoglio attivo invariato: TP01 70% + XS01 30%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:24:16 +00:00
Adriano Dal Pastro 790caefd52 research: wave1 beat-TP01 (26 agenti BTC/ETH) — nessun 3o sleeve robusto, portafoglio invariato
26 agenti, 3 contender ri-verificati onesti: tsmom_12h scartato (corr +0.49 = TP01 veloce),
breakout_atr scartato (gonfia solo FULL storico, hold-out +0.05), highvol_rev in WATCHLIST
(scorrelato e migliora FULL+hold-out MA edge solo a REV_LB=1 = picco non-plateau, FULL mediocre
0.74, HOLD>>FULL = regime-luck alta-vol 2025-26, reversal+concept-flip). Stesso difetto del RV
bocciato -> non deployato. Portafoglio resta TP01 70% + XS01 30%. L'edge incrementale e' venuto
dall'espansione universo (Hyperliquid cross-sectional), non da altre trend-variant su 2 asset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:19:47 +00:00
Adriano Dal Pastro a5a61ac7e3 feat(portfolio): XS01 cross-sectional (Hyperliquid) BATTE il portafoglio -> TP01 70% + XS01 30%
Espansione universo (su input utente "storico da cerbero"): il Cerbero MCP col token MAINNET serve
Hyperliquid (230 perp REALI, storia nativa dal 2024). fetch_hyperliquid.py certifica 19 alt liquidi
a 1d (flat 0%, cross-venue 4-9 bps vs Binance) -> data/raw/hl_*_1d.parquet. Abilita le strategie
CROSS-SECTIONAL (impossibili a 2 asset).

XS01 = cross-sectional momentum market-neutral (long 5 forti / short 5 deboli su ret 30g, ogni 10g,
vol-target 20%). Validato onesto: plateau (config/k/subset), fee-robusto (0.3% RT), scorrelato a TP01
(-0.06), positivo OGNI anno 2024-26, meccanismo complementare (lavora nella dispersione quando TP01
e' in cash). Diverso dal regime-luck RV bocciato (19 asset, plateau, ogni anno+).

Contributo al portafoglio (outer-join + pesi rinormalizzati per sleeve a date diverse):
  TP01-solo FULL 1.30 / HOLD 0.31  ->  TP01 70% + XS01 30%: FULL 1.41 / HOLD 1.15, DD giu', ~ogni anno+.
-> XS01 BATTE il portafoglio esistente: inserito in active_sleeves.

Caveat (documentati): storia XS ~2.5 anni; STAT-MODE (book 19 gambe non eseguibile a 2k -> ~20k),
sleeve diagnostico/forward-monitor. portfolio.combine ora outer-join+renorm. 12 test passano.
Diario 2026-06-19-hyperliquid-xsec.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 20:05:45 +00:00
Adriano Dal Pastro 18f22160b2 research: caccia al 2o sleeve — nessun diversificatore robusto, TP01-only resta
Tool second_sleeve_hunt.py: giudica i candidati per CONTRIBUTO al portafoglio (non Sharpe
standalone). RV mean-rev ETH/BTC morto (come sempre). RV relative-momentum (ratio_trend ==
xs_momentum) sembrava promosso (hold-out portafoglio 0.31->1.51) MA il per-anno + plateau lo
smascherano come REGIME-LUCK 2025: FULL Sh mediocre 0.56, 2 anni consecutivi negativi
(2023 -17%, 2024 -19%), guadagno concentrato nel 2025 (+62%), hold-out Sh non-plateau (0.25-1.92
al variare dei parametri). Beneficio FULL robusto solo +0.09 (diversificazione di uno sleeve
scorrelato debole). NON promosso: la disciplina che boccia i falsi positivi in-sample boccia
anche i falsi positivi nel hold-out. Criterio aggiornato: breadth per-anno + plateau, non solo
hold-out. Relative-momentum in WATCHLIST. Diario 2026-06-19-second-sleeve-hunt.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:28:51 +00:00
Adriano Dal Pastro ef52ad6a79 feat(portfolio): contenitore di strategie ESTENSIBILE — TP01 primo sleeve
src/portfolio/: Sleeve (serie rendimenti netti per-barra, causale/fee-aware) + StrategyPortfolio
(combina N sleeve per peso su griglia giornaliera comune, metriche FULL/HOLD-OUT/per-anno +
standalone per-sleeve, vs buy&hold). Registry sleeve attivi in sleeves.py: per ora SOLO TP01
(peso 100%); aggiungere = una riga (dopo validazione col gauntlet).

Report (run_portfolio.py): TP01 FULL Sh 1.30 / DD 14.3% / ~€1.52/g, HOLD-OUT 0.31 / +3.5%
(buy&hold -0.32 / -39%). Posizione corrente flat (difensivo). tests/test_portfolio.py (6 test).
CLAUDE.md aggiornato (struttura + comando + come aggiungere uno sleeve).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:17:18 +00:00
Adriano Dal Pastro 12754c4908 fix(TP01): bug look-ahead ffill mixed-TF -> deploy a >=12h (1d), strategia DIFENSIVA
Segnalato: ffill MIXED-TIMEFRAME su barre open-labeled (resample label="left") gonfiava il 4h
(~1.60 -> reale ~1.1). Ri-verifica per-SINGOLO-TF leak-free (guard prefix-recompute, leak=0 su
4h/6h/12h/1d): FULL Sh piatto ~1.3, hold-out 2025-26 MIGLIORE a 1d (Sh 0.31 / +3.5% vs buy&hold
-39%). Conclusione adottata: NON scendere sotto le 12h (sotto, costi+overfit dominano senza vantaggio).

- trend_portfolio.py: canonica PORT LF1d; resample_tf/resample_1d (resample_4h deprecato deploy);
  docstring con nota look-ahead + natura DIFENSIVA (taglia DD ~6x, non alpha).
- paper_trend.py: deploy a 1d (resample_1d, build_bars). 5 test passano.
- CLAUDE.md: TP01 ridescritta (>=12h/1d, gotcha ffill mixed-TF, difensiva).
- tp01_lowfreq.py + diario 2026-06-19-tp01-lookahead-fix-lf.md.
Gotcha: mai ffill/combine mixed-TF su timestamp open-labeled (close propagata indietro = leak).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 19:04:38 +00:00
Adriano Dal Pastro 756a2bdf04 research: stress-test TP01 — robusto come strategia DIFENSIVA (DD-cut), edge ritorno hold-out sottile
Stress sul modulo integrato: FULL regge fee 0.40% + lag + ampio plateau parametri (orizzonti
20/60/120 fa Sh 1.61, non cherry-pick); deflated-Sharpe DSR 0.999 a N=100 (no multiple-testing
artifact). MA il ritorno nel hold-out 2025-26 e' SOTTILE (+2.8%/Sh0.27 a 0.10%, ~flat a 0.40%/lag2):
TP01 PROTEGGE il drawdown (8% vs 60% buy&hold) piu' di quanto profitti. Proprieta' robusta e
deployabile = taglio DD; alpha = no. Da monitorare col paper trader prima di scalare.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:57:22 +00:00
Adriano Dal Pastro d152941360 integra(TP01): merge ricerca branch strategy-research-2026-06 (squash) — strategia vincente + harness + track A-E
Integra il lavoro della linea di ricerca parallela (AdrianoDev), verificato indipendentemente
col mio gauntlet onesto (regge il hold-out 2025-26 su entrambi gli asset, plateau 1h/4h/1d):
- src/strategies/trend_portfolio.py  TP01 (TSMOM 30/90/180 vol-target 20% lev2x long-flat, 50/50 BTC+ETH)
- src/backtest/harness.py            harness onesto (load + backtest_signals no-leakage + OOS)
- scripts/research/track{A,B,C,D,E}_*.py + trackD_timing.py  (le 5 track della ricerca)
- scripts/live/paper_trend.py        paper trader forward-only di TP01 (no esecuzione reale)
- tests/test_trend_portfolio.py (5 test, passano) + 6 diari trackA-E + synthesis
- CLAUDE.md aggiornato con l'esito ricerca (TP01 vincente, mean-rev morto, onesta su €50/g)

Squash (non merge) per NON portare in git i ~68MB di data/_feed_backup/*.bak che il branch
aveva committato per errore: esclusi + data/_feed_backup/ e data/paper_trend/ ora gitignorati.
Storia granulare del branch conservata sul ref origin/strategy-research-2026-06.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:55:04 +00:00
Adriano Dal Pastro 55c28e51b2 research: verify TP01 (branch parallelo) col gauntlet onesto — REGGE il hold-out 2025-26
TP01 (TSMOM 30/90/180 vol-target 20% lev2x long-flat, 50/50 BTC+ETH) passa dove il mio trend 1h
era caduto: hold-out 2025-26 +2.8%/DD8% vs buy&hold -39%/DD60%, positivo su ENTRAMBI gli asset,
plateau 1h/4h/1d. La chiave e' il vol-targeting (esposizione ~1/vol -> cash nei crash) che non
avevo combinato col trend. Edge DIFENSIVO reale (Sharpe full 1.36 vs B&H 0.92, ma CAGR 16.6% vs 48%).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:50:36 +00:00
Adriano Dal Pastro 38c8cdf25b research(v2.0.0): honest harness + fasi 0-3 + ricerca frattale 63 agenti — nessun edge robusto su BTC/ETH
Harness onesto research_lab.py (serie di posizione causale, fee-aware, null model a
rotazione circolare, hold-out 2025+ bloccato; self-test cheat/noise che valida il banco).
- Fase 1: triage superstiti (DIP, shape-ML) -> morti net-fee.
- Fase 2: esplorazione famiglie (reversal morta; solo trend long-only/MA-cross passa i gate base).
- Fase 3: conferma avversariale del trend -> regime-luck del toro, bocciato sul hold-out 2025-26.
- Ricerca frattale multi-agente (Workflow, 63 agenti, 52 ipotesi dai due documenti) con guard
  anti-look-ahead (eval_signal.py) + hold-out + test cross-asset -> 0 edge robusto (l'unico
  "confermato" su ETH fallisce su BTC con lo stesso codice).
- Analisi options: VRP reale +10/+14 vol pt ma finestra 6 sett. regime unico -> non validabile;
  ruolo solo overlay tail-cap, tenere cerbero-bite ad accumulare.

Quinta conferma indipendente: su BTC/ETH-solo-prezzo non c'e' un edge facile. Il processo
disciplinato ha evitato un falso "+49% vs -49%" che sul vecchio feed contaminato sarebbe
finito in produzione. Diari docs/diary/2026-06-19-research-phase0-1 / -phase2-options /
-phase3-confirm / -fractal-multiagent-search.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 18:37:05 +00:00
539 changed files with 80624 additions and 59 deletions
+11
View File
@@ -0,0 +1,11 @@
Old/
data/
.venv/
.git/
logs/
__pycache__/
**/__pycache__/
*.pyc
.env
.env.mainnet
docs/
+7
View File
@@ -0,0 +1,7 @@
# Credenziali IB Gateway PAPER per la ricerca dati (account paper, es. DUQ513966).
# COPIA questo file in .env.ibgw (gitignored) e riempi i valori REALI.
# cp .env.ibgw.example .env.ibgw && chmod 600 .env.ibgw && nano .env.ibgw
# NON committare mai .env.ibgw. Sono credenziali del CONTO PAPER (nessun denaro reale),
# l'API e' comunque READ_ONLY (solo dati storici, nessun ordine).
TWS_USERID=il_tuo_username_paper
TWS_PASSWORD=la_tua_password_paper
+22
View File
@@ -6,6 +6,8 @@ build/
.venv/
.env
!.env.example
.env.ibgw
!.env.ibgw.example
.vscode/
.idea/
.DS_Store
@@ -43,5 +45,25 @@ data/games/
# archived data (mirrors top-level data/ ignores, which are top-level-anchored)
Old/data/
Old/**/__pycache__/
# run logs (rigenerabili dagli script)
logs/
# cache della ricerca trackE (rigenerabile)
.cache_trackE_*.npy
# feed backup pre-rebuild (binari rigenerabili, NON in git) + stato paper trader (runtime)
data/_feed_backup/
data/paper_trend/
data/paper_portfolio/
# output grezzo dello sweep di ricerca xsec (rigenerabile dagli script in runs/)
scripts/research/xsec/runs/out/
# blind-signal derived data (regenerable via make_blind.py)
data/blind/
scripts/research/blind/leaderboard.json
# forward-monitor runtime state (regenerable, forward-only)
data/paper_prevday/
data/paper_combo/
data/paper_statarb/
+370 -22
View File
@@ -13,7 +13,13 @@ Cosa è cambiato:
**solo BTC/ETH** (tutti i TF). Gli alt sono esclusi (illiquidi/divergenti/non certificabili).
- Tutto il codice vecchio (strategie, stack live, ~100 script di ricerca/gate, dati non
certificati, 60+ diari) è **archiviato in `Old/`** (preservato in git, non cancellato).
- L'esecuzione è **DISABILITATA**, il conto mainnet è flat. **Non c'è trading live attivo.**
- ~~L'esecuzione è DISABILITATA, il conto mainnet è flat. Non c'è trading live attivo.~~
**AGGIORNATO 2026-06-20: l'esecuzione di TP01 è ARMATA e LIVE su Deribit mainnet**
`config/live.json` `execution_enabled=true` + cron giornaliero `live_execute.py --execute`
(cablato in `scripts/cron_daily.sh`). Guardrail: cap **$300 notional/asset**, min order $5,
**disaster-SL on-book 30%**, alert Telegram su esecuzione/errori. **Capitale reale ≈ $600**
(NON i €2000 nominali del paper trader). Stato corrente: **flat** (target TSMOM risk-off →
BTC/ETH 0.0x, nessun ordine). Solo TP01 è eseguito; XS01/VRP01 restano paper/STAT-MODE.
- Si riparte dalla ricerca di strategie NUOVE, su dati certi, con la metodologia qui sotto.
### Ricerca post-reset (2026-06-19) — esito
@@ -21,19 +27,343 @@ Cosa è cambiato:
Prima ondata di ricerca onesta su BTC/ETH certificati (5 track, harness condiviso
`src/backtest/harness.py`). Sintesi in `docs/diary/2026-06-19-research-synthesis.md`.
- **VINCITRICE (l'unica robusta e profittevole): TP01 Trend Portfolio** —
`src/strategies/trend_portfolio.py`. TSMOM multi-orizzonte (1-3-6 mesi) vol-targeted,
50/50 BTC+ETH. Config canonica **PORT LF4h** (4h, long-flat, vol-target 20%, leva cap 2x):
**CAGR ~16.6%, Sharpe ~1.32-1.36, maxDD ~12-14%, positiva ogni anno 2019-2026**.
Robusta su tutti i TF (15m-1d), regge fee fino a 0.40% RT, su entrambi gli asset.
Paper trader: `scripts/live/paper_trend.py`. Test: `tests/test_trend_portfolio.py`.
- **Edge deboli ma reali** (NON standalone, NON migliorano il portafoglio): ML walk-forward
su BTC (Sharpe ~0.57), trend 1h long-short (Sharpe ~1.0), relative-value market-neutral
ETH/BTC (scorrelato ~0.05 ma Sharpe solo 0.27 → troppo debole per alzare lo Sharpe).
- **MORTO/confermato artefatto:** mean-reversion / fade (negativo anche a fee zero su dati
certi — la vecchia libreria +201%/+1238% era pura contaminazione); trend 5m/15m (fee).
- **Soffitto strutturale:** con i soli BTC/ETH lo Sharpe di portafoglio si ferma a **~1.3**.
Combinare TF o aggiungere la RV non aiuta (ridondanza/edge troppo debole).
- **TP01 Trend Portfolio — strategia DIFENSIVA robusta (non alpha)** —
`src/strategies/trend_portfolio.py`. TSMOM multi-orizzonte (1-3-6 mesi) vol-targeted, long-flat,
50/50 BTC+ETH. Config canonica **PORT LF1d** (**>=12h, 1d raccomandato**, vol-target 20%, leva cap 2x):
**FULL Sharpe ~1.30, maxDD ~14%; HOLD-OUT 2025-26 Sharpe ~0.31 / +3.5%** mentre il buy&hold 50/50
faceva 39%/DD60%. Verificata indipendentemente col gauntlet onesto (hold-out + cross-asset +
plateau + deflated-Sharpe 0.999): **regge**. **Valore = taglio del drawdown ~6× vs buy&hold**, NON
generazione di ritorno (CAGR ~16% vs ~48% del buy&hold sul toro).
⚠️ **LOOK-AHEAD (2026-06-19):** un ffill MIXED-TIMEFRAME su barre open-labeled gonfiava il 4h
(~1.60 → reale ~1.1). Il calcolo per-singolo-TF è leak-free, ma **NON scendere sotto le 12h**:
costi+overfitting dominano senza vantaggio (FULL Sh piatto ~1.3 da 12h a 4h; hold-out migliore a 1d).
Deploy/paper a **1d**. Diari `2026-06-19-tp01-verification.md` / `-tp01-lookahead-fix-lf.md`.
Paper trader: `scripts/live/paper_trend.py` (1d). Test: `tests/test_trend_portfolio.py`.
Ri-verifica: `scripts/analysis/{verify_tp01,stress_tp01,tp01_lowfreq}.py`.
⚠️ **ANCHOR TIMING-LUCK (2026-07-02, confermato da scettico):** l'hold-out ~0.31 è calcolato
sull'ancora daily 00:00 UTC, che è la **migliore delle 24 possibili** (mediana ancore 0.04, banda
[0.13,+0.30]; P~0.86 che una qualsiasi ancora mostri uno spike così per puro caso) → l'hold-out
2025-26 NON risolve l'edge di ritorno di TP01; ciò che regge a OGNI ancora è il **taglio del DD**
(7-10% vs ~60% B&H). FULL/plateau/deflated-Sharpe/gate INVARIATI (h=0 al 31° pctl su FULL).
Regola: i futuri numeri hold-out di strategie a ribilanciamento ancorato si citano con la banda
d'ancora. Diario `2026-07-02-timing-crt-wave.md`; script `scripts/research/r0702_tp01_offset.py`
+ `r0702_skeptic_offset.py`.
- **XS01 Cross-Sectional Momentum (Hyperliquid) — DIVERSIFICATORE che migliora il portafoglio** —
`src/portfolio/sleeves.py:_xsec_returns`. Market-neutral su **19 alt liquidi major** Hyperliquid (1d,
dal 2024): ogni 10g long i 5 più forti / short i 5 più deboli, vol-target 20%. **Scorrelato a TP01
(~0.12).** Affinato (2026-06-19): **(a) blend di lookback [30,90]** (z-score cross-sectional mediato,
come il multi-orizzonte di TP01); **(b) gate di dispersione p30** (entra solo se la dispersione
cross-section del momentum supera il percentile espandente causale, altrimenti flat — XS è rumore in
regime compatto). Standalone FULL Sh **1.50** / HOLD 1.71 / DD 11%, plateau robusto (lookback, gate
p15-35). **Caveat:** storia ~2.5 anni; STAT-MODE (book a 19 gambe non eseguibile a 2k, serve ~20k) →
monitor forward. NB il gate concentra XS nei regimi dispersi (2025-26 = hold-out alta-dispersione).
⚠️ **PHASE TIMING-LUCK (2026-07-02):** i numeri headline sono sulla fase 0 del ciclo H=10, che è
al **15° pctl di DD** (10.8% vs ~15.5% fase tipica, 29% peggiore) e 85° di FULL fra le 10 fasi
(HOLD solo 65°, non estremo); P(spike per caso)≈0.91-0.94. Lens onesta = **ensemble di fase:
FULL 1.25 / HOLD 1.31 / DD 10.9%**; a fase mediana FULL 1.08/HOLD 1.10/DD 21%. La decisione di
ammissione @15% regge (0 fasi negative, 8/10 FULL≥1.0), i numeri 1.50/1.71/11% no → citarli con
banda di fase. Ora-del-giorno NON testabile (solo 1d HL). Script `scripts/research/r0702_anchor_xs01.py`;
diario `2026-07-02-anchor-audit-xs01-skh01.md`.
Ricerca `scripts/portfolio/{xsec_research,xsec_blend,xsec_dispgate}.py`. Diari `2026-06-19-hyperliquid-xsec`
/ `-xsec-blend` / `-xsec-dispgate` / `-xsec-universe-expansion` / `-trend-multiasset`.
- **PORTAFOGLIO ATTIVO = TP01 (33%) + XS01 (15%) + VRP01 (12%) + SKH01 (20%) + GTAA01 (20%)**
(`src/portfolio/sleeves.active_sleeves`): TP01+XS01 combinato **FULL Sharpe 1.55, HOLD-OUT 1.55,
DD 4.4%**. Aggiunto **VRP01** (options short-vol, sotto): TP01+VRP01 da solo fa FULL Sh 1.30→1.44 /
HOLD 0.31→0.40 a peso 20%. **Aggiunto SKH01-V2-DD @25% effettivo (2026-06-23, sotto)**: 4-sleeve
**FULL Sharpe 1.68→2.13, HOLD-OUT 1.63→2.30, DD full 14.3%→7.8%** (Skyhook quasi-ortogonale,
corr ~0.09). **Aggiunto GTAA01 @20% effettivo (2026-07-01, i 4 preesistenti scalati ×0.80):**
trend difensivo equity 6-ETF su IB (`src/portfolio/gtaa.py`, ~30 anni storia, validato 2026-06-22
su OOS equity 2015+ INDIPENDENTE dall'hold-out crypto, corr al book ~+0.10) → 5-sleeve
**FULL Sharpe 2.12→2.24, HOLD-OUT 2.21→2.46, DD full 7.8%→6.2%** (costo dichiarato: CAGR full
23.3→18.8%; 2022 unico anno con dSh). Uplift positivo in-sample E su tutte le finestre disgiunte
(vs EW-STR refutato lo stesso giorno). Convenzioni: weekend/festivi equity = 0.0 (capitale IB
fermo, non riciclato); attivazione nel book all'era crypto 2019-03; **il book live Deribit
(`deribit_book_sleeves` TP01+SKH01 75/25) NON lo include** (GTAA in paper_combo dal 2026-06-23).
Test `tests/test_gtaa_sleeve.py`; diario `2026-07-01-strategy-wave-6threads.md` (addendum GTAA).
Report `scripts/portfolio/run_portfolio.py`. Sleeve a date d'inizio diverse → outer-join con pesi
rinormalizzati (TP01/SKH01/GTAA dal 2019*, VRP dal 2021, XS dal 2024; *GTAA troncato all'era book).
⚠️ **ANCHOR-LUCK del book (2026-07-02):** l'HOLD 2.46 è calcolato con TUTTI gli sleeve ancorati
alla loro ancora canonica, che per TP01/XS01/SKH01 è al top della rispettiva banda (eredità di
fortuna ~+0.10/+0.17/+0.5 HOLD). **Stima de-luckata onesta: HOLD ~1.9-2.1, FULL ~2.0-2.2, DD ~6%
invariato** — il book resta positivo e diversificato a ogni ancora testata, ma 2.46 è un massimo
di configurazioni d'ancora, non la stima centrale. Diario `2026-07-02-anchor-audit-xs01-skh01.md`.
- **SKH01-V2-DD "Skyhook" — DIVERSIFICATORE quasi-ortogonale (research)** — `src/strategies/skyhook.SKH01_V2_DD`,
sleeve `src/portfolio/sleeves._skyhook_returns`. Sistema dual-TF (segnale 690m / exec 230m) regime
(BuzVola/BuzVolume tipo-Chande) AND pattern (Donchian breakout), NON trend-follower, L/S. Vincitrice
di 2 onde multi-agente (la 2ª = DD-reduction): exit a **percentuale fissa ASIMMETRICA** (long sl4%/tp10%,
short sl2%/tp8% più stretto) → standalone **maxDD BTC 21% / ETH 27% (<30%)**, minFull +0.99, minHold
+1.26, causale (0/400), fee-surviving 0.40%RT. Marginal vs TP01 **ADDS** (corr 0.09, has_insample_edge,
robust_oos multicut 7/7, is_hedge=False); blend 0.75·TP01+0.25·SKH **hold-out 0.31→1.17**. Verificato
leak-free + 2 scettici. **CAVEAT:** equity daily-step (Sharpe lens), ETH DD margine sottile, book 230m
(costi ribilanciamento da verificare a deploy) → research win, forward-monitor. Diario `2026-06-23-skyhook.md`.
⚠️ **GRID TIMING-LUCK (2026-07-02, più forte di TP01):** i numeri headline sono sull'offset 0 della
griglia 230m/690m, al **93-98° pctl dei 23 offset a priori** — minHold +1.26, blend 1.17 e book
HOLD 2.44 sono il MASSIMO dei 23 (mediane: minHold +0.39, blend 0.72, book 1.96); spike, non
plateau (±30m crolla); P(spike)≈0.70. **Il gate DD<30% (criterio di selezione di V2-DD) fallisce
in 15/23 offset** (mediana ETH 29.2%). Regge de-luckato: uplift blend positivo a TUTTE le 23 fasi
(min +0.18, med +0.42) + corr 0.05-0.11 → ADDS sopravvive ridimensionato. **LIVE (SKH=25% del book
Deribit):** path reale cron orario + exit software → book 50/50 FULL 1.46→1.19 / HOLD 1.64→1.15 /
DD 18→25%; nei crash gap-through-stop reale (sl2% modellato → 11/23% realizzato). Pesi/book
INVARIATI (ogni cambio passa weights_tilt_null); follow-up: cadenza 230m, peso live da rivedere.
Script `scripts/research/r0702_anchor_skh01.py`; diario `2026-07-02-anchor-audit-xs01-skh01.md`.
- **VRP01 Options Short-Vol — DIVERSIFICATORE da FinanceOld/OptionsAgent** — `src/portfolio/sleeves._vrp_combo_returns`.
Put credit spread settimanale (vendi put -0.28, compra put -0.10) gated su IV-rank. Idee portate da
`../FinanceOld/OptionsAgent` (Bear Call Spread + gate d'ingresso). Migliora il lead VRP nudo
(options_vrp_lab): **(a) defined-risk** taglia la coda (worst-week -16.6%→-7.4%, DD 33%→14%);
**(b) gate IV-rank>0.30** = vendi vol solo ricca → ribalta HOLD-OUT da -0.25 a +0.28 (l'alpha è il
filtro di regime). Standalone **FULL Sh 1.10, HOLD 0.60, DD 12%**, positivo/piatto ogni anno (2022
crash incluso). Scorrelato a TP01 (~+0.01-0.07). **CAVEAT:** premio MODELLATO su DVOL ATM (skew non
esplicito), book a 1d, f di stress reale non catturato → LEAD robusto, non deploy pieno. Ricerca
`scripts/research/options_vrp_v2.py` (vs baseline `options_vrp_lab.py`). Test `tests/test_vrp_sleeve.py`.
⚠️ **ANCHOR-AUDIT CHIUSO + ondata "migliora e proteggi" (2026-07-03, 7 filoni + 2 lenti + scettico):
VRP01 NON è migliorabile e la protezione DD si compra SOLO con la size.** (a) **Anchor-luck (ciclo
settimanale, 7 fasi): PRIMO sleeve SENZA firma di luck** — la fase canonica è la PEGGIORE delle 7 su
FULL (1.09 = 7° pctl) e su DD (11.8% = 93° pctl), mediana su HOLD (0.59); spike bootstrap NEGATIVO →
i numeri di ammissione FULL 1.10/HOLD 0.60/DD 12% sono CONSERVATIVI, non gonfiati. Da ora si citano
con banda: ShFULL [1.09,1.83], ShHOLD [0.03,1.11], DD [5.7,11.8%]; edge OOS f-dipendente (f=0.8 →
HOLD~0). **Con questo l'audit anchor è completo su 4/4 sleeve ancorati.** (b) Griglia 288 strutture:
nessuna batte VRP01 (DSR 0.000; metà griglia = 3ª occorrenza "0-perdite/Sharpe implausibile" dopo
CC01/ALB-A → gate `implausible_sharpe` alzato di priorità). (c) 4 overlay DD (exit-spike/SL-MTM/
ala-coda/cooldown): 4/4 REFUTED dal null de-levering — la protezione crash vive già nel gate
d'ingresso IV-rank. (d) Gate nuovi: 4° fallimento su 4 (l'alpha è il binario IV-rank>0.30). (e)
Sizing: 12% deploy ≈ 0.27 Kelly onesto (anti-rovina); ⚠️ NON confondere col 12% di PESO del book
(~0.014 Kelly, fattore 19x). (f) Gate term-structure VIX/VXV su SPX (ΔSh +0.90, DSR 0.992) =
**confound di modello al 100%** (la var del gate coincide con l'errore BS-flat vs term-structure) →
nuova regola: riprezzare term-structure-consistent prima di credere a un gate vol su strutture
BS-flat. Book/pesi INVARIATI. Diario `2026-07-03-vrp-improve-dd.md`; script `scripts/research/r0703_vrpimp_*.py` (7 file).
Diario `2026-06-20-financeold-analysis-vrp-v2.md`.
- **Universo Hyperliquid: ESPANDERLO NON aiuta XS01** (provato): 52-asset / top-liquidità dinamico /
trend-multi-asset → tutti peggiori (small-cap/memecoin diluiscono il momentum relativo; il trend
multi-asset è ridondante con TP01, corr 0.74). I margini su XS sono nella STRUTTURA DEL SEGNALE
(blend + gate), non nel numero di asset. I **51** parquet certificati restano per ricerca futura.
⚠️ Il test "52-asset = negativo" era in parte inquinato dal backfill sintetico (AXS 83%, ALGO/SAND
37% di barre vol=0) poi rimosso — vedi correzione estrazione 2026-06-20 sotto; resta comunque vero
che il long-tail diluisce XS01, ma il numero netto post-fix è 51.
- **Lead OPZIONI VRP (income short-vol) — quantificato, NON deploy** — `scripts/research/options_vrp_*.py`.
Vendita put settimanali che incassa il volatility risk premium (IV>RV), scorrelato al trend (~0.07).
Premio prezzato BS su DVOL reale (`fetch_dvol.py`) + calibrato su quote REALI cerbero-bite mainnet
(`options_vrp_calibrate.py`): **f reale ≈ 1.0** (non 1.29) → Sharpe ~0.71, DD 33%, coda severa
(settimane 15..26% su LUNA/FTX). Diversificatore DEBOLE a premio reale, e short-vol da modello.
**Regola: niente short-vol da modello in deploy.** Rivalutare quando cerbero-bite cattura un crash
(per il f di stress reale). Diari `2026-06-19-options-vrp-lab` / `-eval-crypto-backtest-options`.
- **Edge deboli/scartati:** ML walk-forward BTC (Sh ~0.57), trend 1h L/S (~1.0), RV ETH/BTC (Sh 0.27,
regime-luck), calendar/seasonality (buy&hold travestito), volume/vol e momentum-reversal (negativi).
- **MORTO/confermato artefatto:** mean-reversion / fade (negativo anche a fee zero — la vecchia
libreria +201%/+1238% era contaminazione); trend 5m/15m (fee).
- **GAMMA SCALPING (long-vol) "scalping BTC/ETH con copertura in opzioni" — SCARTATO (2026-06-26)** —
`scripts/research/options_gamma_scalp.py`, test `tests/test_gamma_scalp.py`. È lo **specchio
esatto del VRP01** (long straddle ATM + delta-hedge: incassa **RVIV**, dove VRP01 incassa IVRV).
Perde **ogni anno, ogni variante, ogni frequenza** (Sharpe 3 a 6; nudo/cheap-gated/rich-skip;
rehedge 1d e 1h). Diagnostica strutturale: a 1d IV≈o>RV (BTC +4.9pp) → paghi il VRP; a 1h RV>IV
gross ma (a) gonfiata da microstruttura, (b) il rehedge orario paga **24× la fee di hedge**
variante *peggiore* (6). Marginale vs TP01 = **DILUTES**, non è nemmeno hedge (perde sia TP01-up
sia TP01-down). Muro eseguibilità: opzione BTC min $5.968 ≫ $600. Schiacciato tra due muri:
rehedge lento = premio, veloce = fee → **nessuna frequenza vince.** Regola gemella del VRP:
*niente long-vol scalp da modello in deploy*. Il VRP01 (lato short, gated) resta l'unico edge
opzioni — funziona perché sta sul lato *giusto* dello stesso premio. Diario `2026-06-26-gamma-scalp-options.md`.
- **CASH-AND-CARRY (basis trade) "CC01" — premio REALE, Sharpe ARTEFATTO, NON deployabile (2026-06-26)** —
`scripts/research/cash_carry_hl.py`, test `tests/test_cash_carry.py`. Diverso da FC01 (funding
cross-sectional, già scartato): qui delta-neutral long-spot/short-perp sullo *stesso* asset →
ritorno ≈ **+funding** (zero esposizione prezzo). Il premio di funding è **reale** (~+8-14%/anno
aggregato, positivo ogni anno in-sample, ortogonale a TP01 corr ~0.05). MA lo **Sharpe modellato
11-13 (DD 0.3%) è un ARTEFATTO**: il modello cattura solo il cashflow liscio del funding e i
rischi di coda sono **strutturalmente fuori dal dataset** — (1) storico funding dal 2023-05 →
**manca il 2022** (deleveraging, funding , basis blow-out); (2) **procyclico** (carry +23% toro
2024 → +1.7% bear 2026, si comprime quando servirebbe); (3) liquidazione short/slippage non
modellati. Il mark-to-market della base (`premium` col → r=funding−Δpremium) sgonfia lo Sharpe
solo 13→11 → il basis-from-data NON è il rischio vero. Sharpe reale di un basis-trade ~1-3 con
code brusche. **NON eseguibile a $600** (spot+perp = 4-38 gambe, funding HL non Deribit) → STAT-MODE.
**LEAD da rivedere a scala (~20k+ e venue con funding eseguibile), non uno sleeve.** Sottoprodotto:
CC01 passa OGNI gate del marginal scorer → **punto cieco** (manca un gate "Sharpe implausibile →
rischio nascosto"; prossima indurita raccomandata). Diario `2026-06-26-cash-carry-hl.md`.
- **TP01 × DVOL vol-targeting — NON migliora (2026-06-26)** — `scripts/research/tp01_dvol_overlay.py`,
test `tests/test_tp01_dvol_overlay.py`. Angolo ESEGUIBILE (tocca il book live, non STAT-MODE):
usare il DVOL (vol implicita forward-looking) come denominatore del vol-target di TP01 invece
della vol realizzata. Su finestra comune 2021-2026: le varianti DVOL abbassano il DD (12.3%→9.2%)
ma anche Sharpe FULL (0.75→0.70) e CAGR (8%→6%). **Controllo decisivo:** il realized a target_vol
RIDOTTO (15%) eguaglia quel DD (9.4%) a Sharpe **più alto** (0.75) → il taglio di DD del DVOL è
solo **de-levering**, replicabile meglio con un semplice target_vol più basso. L'unico residuo
(hold-out +0.06) è single-window (storia DVOL <5 anni) → sotto la soglia multi-cut. Il gate
DVOL-spike de-risk è **ridondante col trend** (TP01 già flat nei crash, Δ 0.00). **Lezione: per meno
DD sul live la leva è `target_vol`, non un overlay DVOL** (20% resta canonico). Diario `2026-06-26-tp01-dvol-overlay.md`.
- **Filoni 2026-06-29 (1ª ondata) — tutti scartati/forward.** (A) **DVOL-DIREZIONALE** standalone BTC/ETH
(buy-the-fear / IV-RV come segnale di livello): l'unico edge è un **HEDGE** (is_hedge=True, paga solo
quando TP01 è debole), non alpha → earns_slot=False, forward-monitor come DD-dampener (diario
`2026-06-29-dvol-directional.md`). (B) **INTRADAY ERM** (efficiency-ratio regime momentum sub-daily):
**falso positivo da selezione-sull'hold-out** → SCARTATO (vedi gate SELECTION-ON-HOLDOUT;
`2026-06-29-intraday-regime.md`). (C) **XSEC-V2 NON-MOMENTUM** su HL (reversal/idio-reversal/low-vol/BAB):
solo LOWVOL 19-major regge standalone (FULL/HOLD 1.07) ma deflated-Sharpe 0.13 + storia 2.5a → **DEBOLE/
forward STAT-MODE** (`2026-06-29-xsec-v2-nonmom.md`). (D) **MACRO regime-gate** (equity/credito/oro/tassi →
de-risk crypto): **RIDONDANTE col trend** (corr→TP01 0.989; il gate lavora solo nel 2-3% dei giorni, TP01
già flat nei crash) → SCARTATO (`2026-06-29-macro-regime-gate.md`).
- **Sweep strategie a 5 thread (2026-06-29) — 0 nuovi sleeve, 1 LEAD che rompe 2 muri su 3.** Ricerca
parallela onesta su aree inesplorate (harness `altlib`+`xsec_v2_nonmom`, tutti i gate incl. il nuovo
`study_family_honest`): (1) low-risk cross-sectional, (2) momentum-structure vs XS01, (3) meta-allocazione
dinamica, (4) segnali ortogonali ETH/BTC, (5) 1-gamba a segnale. Esito: soffitto ~1.3 riconfermato; ogni
candidato ucciso dal gate giusto (deflated-Sharpe, is_hedge, selection-on-holdout, sostituzione-XS01,
multi-cut). Niente batte/diversifica XS01 (varianti = REDUNDANT); meta-allocazione < pesi fissi (i 4
sleeve già quasi-risk-parity); 1-gamba a segnale = TP01 travestito (trend) o hedge a DSR<0.95.
**LEAD forward-monitor:** **STATARB-RESID** (relative-MOMENTUM del residuo ETH−β·BTC, β OLS rolling, 2 gambe,
cella vincente **sgn=+1**: le dislocazioni ETH-vs-BTC CONTINUANO a 1d, la MR pura sgn=1 perde) — primo
stream **insieme ortogonale (corr→book 0.027, β-mkt 0.013) ED eseguibile a $600** (haircut ~0, NON
STAT-MODE come XS01/opzioni): marginal ADDS, robust_oos, fee-survive 0.30%/gamba; resta sotto soglia solo
sull'**edge** (Sharpe 0.84, DSR 0.929 same-sign <0.95). **CABLATO in forward-monitor PAPER:**
`scripts/live/paper_statarb.py` (W=45/sgn=+1 congelati, doppio libro MODELED/REAL-$600), nel cron
giornaliero accanto a `paper_prevday`; test `tests/test_paper_statarb.py`. Se la finestra forward conferma
l'edge è *deployabile* (2 gambe BTC/ETH perp). Altri LEAD: IVOL (idio-vol XS, STAT-MODE), DVOLSPREAD
(storia DVOL corta). Diario `2026-06-29-strategy-search-5threads.md`. Script
`scripts/research/{xsec_v3_lowrisk,xsec_v3_momstruct,meta_allocation,orthogonal_signals,signal_inout_1leg}.py`.
- **Ondata 2026-07-01 (6 filoni multi-agente + scettico) — 0 edge nuovi dai filoni, 1 gate nuovo,
e 1 sleeve promosso DALL'ARCHIVIO (GTAA01, sotto nel bullet portafoglio).** Filoni su angoli non coperti dalle ondate precedenti: (1) **funding time-series**
BTC/ETH (posizionamento) = SCARTATO — FOLLOW è trend-beta ritardato, FADE shorta il toro, il gate è
TP01 travestito (DSR 0.215); **il filone funding è chiuso su 3 lati** (FC01 carry, price-clock, TS).
(2) **breadth/internals alt** (51 HL) = SCARTATO ma unico NON-ridondante col trend (corr→TP01 0.40);
muore su jackknife (uplift su 1 mese) + DSR 0.433 con ~8 mesi IS → **rivisitabile tra 1-2 anni di
storia HL nativa**. (3) **residual momentum XS** (β-hedged, 19 major) = REDUNDANT — cross-section la
residualizzazione è un no-op (lo z-score di XS01 rimuove già il mercato); l'edge resta solo nella
coppia ETH/BTC (STATARB-RESID). (4) **ri-ottimizzazione pesi + guardia-DD**: il candidato EW-STR
(TP30/XS25/VRP15/SKH30, HOLD 2.21→2.35) **refutato dallo scettico come selezione-sull'hold-out di 2°
ORDINE** — SKH01/XS01 furono ammessi/affinati *perché* forti su quell'hold-out; pre-2025 ΔSh 0.05,
finestre disgiunte 0.12/+0.06/+0.14, percentile 94-100° fra 500 tilt casuali ≈ firma best-of-15.
Guardia-DD 5%/0.5: inerte OOS (la diversificazione fa già il lavoro; solo circuit-breaker d'emergenza).
(5) **affinamento VRP01** = NON MIGLIORA (l'alpha è tutto nel gate binario IV-rank; gate TP01 =
trappola in-sample; **3° fallimento → filone "VRP dentro il modello" esaurito** fino a f di stress
reale). (6) **stagionalità cross-sectional HL** = morta allo step statistico (null permutato).
**GATE nuovo codificato: `weights_tilt_null`** in `src/portfolio/portfolio.py` (+ `combine_outer`
riusabile): ogni proposta di CAMBIO PESI si giudica vs il null dei tilt casuali cap-respecting —
gate_pass solo se delta_insample≥0 E percentile < firma best-of-k (necessario, non sufficiente);
test `tests/test_weights_tilt_null.py`. ⚠️ Lezione tecnica: `DatetimeIndex.view("int64")` su indici
tz-aware non-ns (pandas 2.x) → scala sbagliata → `merge_asof` broadcasta = **look-ahead che
`causality_ok` non vede**; usare epoca esplicita in ms (altlib verificato pulito). Diario di sintesi
`2026-07-01-strategy-wave-6threads.md` + 6 diari di filone; script `scripts/research/r0701_*.py`.
- **Ondata 2026-07-02 (TIMING + CRT, 8 filoni multi-agente + scettico) — 0 nuovi sleeve, 1 finding
strutturale (anchor timing-luck di TP01, vedi ⚠️ nel bullet TP01).** Goal: "strategie con timing
differenti". (1) **Event-clock bars** (volume/vol/range da 5m, TSMOM/Donchian/EWMA in tempo-informazione):
batte il wall-clock a pari segnale/frequenza solo in 4/45 coppie; cella best IS 1.45 → HOLD 0.46,
NEUTRAL (corr 0.74 = trend travestito) → SCARTATO: il clock non è dove vive l'edge. (2) **Calendario
scadenze Deribit** (expiry weekly/monthly/quarterly ven 08:00 UTC): 0/24 celle a Bonferroni; il drift
post-expiry monthly fallisce placebo-weekday e permutation e si INVERTE sul quarterly (dove l'OI massimo
dovrebbe amplificarlo); unico pattern robusto = gio→ven negativo, ma è day-of-week (SEA morta) a Sharpe
netto ~0 → SCARTATO. (3) **Anchor timing-luck TP01 + tranching**: finding confermato (dettagli nel
bullet TP01); tranching K=2/4 = sola riduzione della varianza della STIMA (ΔSharpe n.s., ΔDD ~0.5pt),
NO deploy a $600 (il min-order lo degenera in K=1; serve feed intraday fuori path certificato) —
rivalutare a ≥5-10k. **Audit d'ancora ESEGUITO su XS01 e SKH01 (stesso giorno): il finding si
replica su 3/3 sleeve ancorati** — vedi ⚠️ nei rispettivi bullet e la stima de-luckata del book
nel bullet portafoglio; diario `2026-07-02-anchor-audit-xs01-skh01.md`.
(4) **Clock lenti (2-7g) + bande isteresi**: fee drag di TP01 = ~0.4%/anno = tetto di ogni risparmio;
il lag costa più del risparmio (HOLD ensemble 0.34→0.11 da N=2 a 7); a $600 **il min-order $5 è GIÀ la
banda ottimale** (ordini 74% a costo ~0) → nessun cambio al book. (5) **Velocità trend
regime-condizionata** (pesi tra orizzonti 30/90/180g vs percentile vol RV/DVOL): pctl 0.71 vs null
pesi-statici-casuali = tilt-30d statico travestito (trappola EW-STR); pesi canonici 1/3 confermati →
SCARTATO. (6-8) **CRT "Candle Range Theory"** (sweep-and-reclaim 3 candele, mai coperto da MRV/MIC):
base 864 trial DSR 0.000 + anchor-flip + short "smart-money" negativo perfino in-sample; multi-TF
(4h→15m, 1h→5m, ~10k trade) expectancy negativa ovunque anche a fee zero, e **il ritest è informazione
negativa** (pattern con-ritest 40bps vs senza +52bps: aspettarlo seleziona i peggiori); contesto
(FVG/equal-highs/sessioni, 22 trial) non salva il fade, cella "Asia" = artefatto anchor-flip →
SCARTATO 3/3. Sottoprodotto: sugli stessi livelli prior-day **FOLLOW > FADE ogni anno 2019-26**
(conferma indipendente del lead prevday in forward-monitor). Lezione: il timing-luck d'ancora è
multiple-testing che il deflated-Sharpe NON conta (candidato gate futuro `anchor_luck_band`).
Diario `2026-07-02-timing-crt-wave.md`; script `scripts/research/r0702_*.py` (9 file).
- **Ondata 2026-07-02-bis ("video claims": Elliott 3 filoni + Albimarini 2 + capital scaling) — 0 nuovi
sleeve, 0 forward-monitor, 1 azione config pendente sul deposito.** Meccanizzazione onesta di claim da
video didattici: (1) **Elliott range-cycle** (onda1 compressa→onda3 ampia): rumore, 0/24 celle a
Bonferroni, nessuna cella weekly regge a tutte le 7 ancore → SCARTATO. (2) **Confluenza Fibonacci**:
vs null ingenui sembra buona (pctl 0.82-1.00), vs null **location-matched** (Fib±jitter: "0.618 vs
0.58?") crolla a 0.39-0.68 = l'apparente edge è la POSIZIONE dei livelli, non i numeri; confluenza
FAIL 4/4 → SCARTATO (il null location-matched è IL test per ogni claim su livelli "speciali").
(3) **Tecnica del canale Elliott**: Donchian travestito — non batte il Donchian a pari geometria
(corr 0.43-0.53), DSR 0.685, cella in-sample collassa in hold-out (1.40→−0.87), target 1.618 = caso
(5/6 celle), anchor-luck di nuovo (4h banda hold [0.35,1.54], 00:00 la migliore) → SCARTATO.
(4) **Albimarini double-diagonal** (short T + long T+1, deep OTM, via motore DVOL di VRP01): il
condor stessa-scadenza la batte a ogni f (la long T+1 = assicurazione di coda +12/33bps nel tail,
~1bps costo medio, non dominanza); senza gate IV-rank TUTTE le strutture perdono (3ª conferma:
l'alpha del VRP è il gate); su Deribit fee-negativa a QUALSIASI size (fee 8 gambe = 194-221% del
theta); celle deep-OTM 0-perdite/142 trade = 2° caso "Sharpe implausibile" dopo CC01 → gate
`implausible_sharpe` raccomandato con più forza. VRP01 resta superiore su tutta la banda skew →
nessun LEAD. (5) **Audit claims** (28 trade, 82% win, PF 5.16, "420%/anno"): consistente con ZERO
skill (P=20-45%; il 78.6% delle finestre 6-mesi 1996-2026 lo produce); replay con code reali =
rovina 1998/2002/2020 col sizing dichiarato; la diagonale lascia passare il 12-40% della perdita
naked. (6) **Capital scaling 600→2-5k** (`r0702_capital_scaling.py`): l'unico vincolo binding è
`max_notional_per_asset_usd=300` (a 5k il book live girerebbe al 49% del target) → **al deposito
alzare il cap a equity/2** ($1000/$1750/$2500 a 2k/3.5k/5k); min_order $5 da LASCIARE; tranching
K=2 non cablare (blocco feed intraday); opzioni ETH eseguibili da ~2.6k ma la regola no-short-vol-
da-modello non decade col capitale; XS01 ~20k confermata, CC01 fuori per struttura. Aspettativa
onesta col CAGR de-luckato (10-15%): 2k ≈ €0.6-0.8/g, 5k ≈ €1.4-2/g (€50/g resta ≈130k).
⚠️ Lezione pandas: `resample("7D", origin=...)` IGNORA origin (pandas 2.x, solo RuntimeWarning) →
bande d'ancora weekly finte; usare `"168h"`. Diario `2026-07-02-elliott-albimarini-capital.md`;
script `scripts/research/r0702_{ell_*,alb_*,capital_scaling}.py` (6 file).
- **Video-claim "CRT top-down multi-TF, 74% win rate" — SCARTATO (2026-07-07): il 74% è un KNOB, non
un edge.** `scripts/research/r0707_crt_topdown.py`. Metodo ICT/SMC top-down (H1 setup CRT → M15
struttura/FVG → M5 conferma → M1 entry) con uscita parziale-70/80%-a-1.5R + break-even + runner verso
prev-daily high/low. Il setup H1 CRT è **già triplo-refutato** (onda 2026-07-02: base DSR 0.000, MTF
expectancy neg. ovunque "il ritest è informazione negativa", contesto/FVG peggiora, fade<follow) →
qui testato l'UNICO angolo nuovo: la **gestione d'uscita** e il **claim 74%**. Su BTC/ETH certificati
(H1→5m/15m; M1 non nel feed): **WR reale 3037%** a RR 1.52 (SOTTO il null gambler's-ruin 40% =
P(+1.5R prima di 1R)=1/(1+1.5) → il ritest tocca il target MENO di una moneta), **expectancy R
negativa a ogni schema/fee/finestra/asset** (1.2…−3.3R netto). **Il 74% si fabbrica avvicinando il
target**: sweep rr1 0.5→2.0 mostra WR salire (51→32%) con expectancy R INVARIANTE (WR alto = target
vicino, non direzione). DSR 0.000 (48 trial); a **fee 0** expR 0.10/Sh 0.63 → **non è morte-per-fee,
l'edge lordo non c'è** (residuo = beta di trend dei time-exit); parziale+BE+runner = 3-4 ordini/trade,
alcuni sub-min-order a $600. **Regola candidata:** il win-rate di uno schema parziale+BE non è merito
(≈1/(1+rr1)); convertire ogni claim "WR X%" in **expectancy R netto fee** prima di crederci (helper
`winrate_is_a_knob()`). Diario `2026-07-07-crt-topdown-74winrate.md`. Book/pesi INVARIATI.
- **Soffitto strutturale BTC/ETH-direzionale ~1.3** superato SOLO espandendo a un meccanismo diverso:
cross-sectional su universo Hyperliquid certificato (XS01) → portafoglio Sharpe ~1.55.
- **Sweep "strategie alternative" (2026-06-20) — 104 ipotesi / 153 agenti / NIENTE di nuovo regge.**
Ricerca onesta a largo spettro su BTC/ETH+DVOL (harness condiviso vettoriale leak-free
`scripts/research/alt/altlib.py`, 104 script in `scripts/research/alt/runs/`): 11 famiglie
(breakout, trend non-TSMOM, mean-rev gated, DVOL/vol, cross-asset pairs, stagionalità, overlay
rischio, opzioni modellate, microstruttura, ML walk-forward, combo). 16 promettenti, **1 sola**
sopravvissuta alla verifica avversariale (3 scettici) e comunque NON deployabile. Conferma forte
del soffitto ~1.3: ogni PASS era hold-out-fitting o **TP01/TSMOM travestito** (trend-beta del
toro). Unico LEAD: **STA05** (EWMA-cross ensemble, **long-short**) — leak-free, plateau, corr
hold-out **0.53** a TP01, il blend 0.75·TP01+0.25·STA05 alza l'hold-out 0.31→0.59 (full 1.30→1.24,
DD 14→16%); MA hold-out corto (536g) → **forward-monitor, non sleeve.** Lezione harness: valutare
lo Sharpe **MARGINALE vs baseline TP01** (non assoluto) + esigere plateau e jackknife
drop-one-month sull'hold-out prima di PASS (hanno ucciso 13/14 falsi positivi). Diario
`2026-06-20-alt-strategies-100agent-sweep.md`.
- **MARGINAL SCORER (implementato 2026-06-20)** — la lezione "Sharpe marginale, non assoluto" è
ora codice in `scripts/research/alt/altlib.py`: `study_marginal(name, target_fn)` valuta un
candidato direzionale BTC/ETH **sia** in assoluto **sia** rispetto al baseline `tp01_baseline_daily()`
(corr, uplift del blend OOS, beta+alpha residua) e ritorna `earns_slot = (abs!=FAIL) AND
(marginal==ADDS)`. **Regola: una nuova strategia direzionale si giudica su `earns_slot`, non sullo
Sharpe assoluto** (gli overlay-su-TSMOM ereditano lo Sharpe di trend e prendono PASS fasulli —
es. CMB04 PASS assoluto → NEUTRAL marginale). Demo `marginal_demo.py`, test `tests/test_marginal_scorer.py`.
⚠️ **INDURITO 2026-06-21 (onda ortho):** la versione fisso-HOLDOUT + jackknife-mese era
ingannabile — 17/18 book relative-value "ADDS" su una sola finestra 2025 (ETH-bleed dove TP01 è
debole). Tre gate nuovi in `marginal_vs_tp01`: **(1) persistenza multi-cut** (uplift positivo a più
date di taglio, non solo 2025); **(2) edge in-sample** (`has_insample_edge`: lo Sharpe standalone
PRE-holdout dev'essere ≥0.5 — un low-corr a Sharpe ~0.3 "aggiunge" solo matematica di
diversificazione, riportata via `null_pctl_*` vs un asset-rumore a corr-zero); **(3) hedge vs
alpha** (`is_hedge`: un low-corr che paga SOLO quando TP01 è debole — `corr(Sharpe-TP01, uplift
annuo)` molto negativa — è un hedge, non alpha). Verdetti nuovi: HEDGE, NOISE. Sull'onda ortho lo
scorer indurito collassa 17/18 → **1** (`dvol_spread`, unico con edge in-sample reale; comunque
forward-monitor per multiple-testing/storia DVOL corta). Lezione: un nuovo sleeve si giudica su
edge-in-sample + persistenza multi-cut + non-hedge, non sull'uplift di una finestra fortunata.
- **HARNESS REALISM (codificato 2026-06-21, onda intraday)** — due gate nuovi in `altlib.py`,
test `tests/test_harness_realism.py`:
- **`day_boundary_robust(target_fn, tf)`** — un effetto ora/sessione/giorno il cui uplift
marginale **si inverte** spostando il confine del giorno UTC di poche ore è un **artefatto di
etichettatura calendario** (ha ucciso `open_drive`: +0.23 a 00:00 → 0.33 a +8h → ARTIFACT-RISK).
Un segnale di prezzo è INVARIANT (spread 0); un effetto calendario vero è ROBUST (resta positivo;
es. `prevday_range_breakout`). **Regola: ogni segnale calendar/session/hour passa questo test
prima di crederci.**
- **`eval_weights_smallcap(df, target, capital=600, min_order=5)`** — a ~$600 un ribilanciamento
di nozionale < min_order **non si esegue**; la fee proporzionale che `eval_weights` applica a
migliaia di micro-trade sub-dollaro (tipici di un overlay vol-target) è **finzione**. Salta i
sub-min_order e riporta lo **Sharpe haircut** reale vs modellato. **Vale per OGNI sleeve a questo
capitale, TP01 incluso** — lo Sharpe netto onesto a $600 è quello small-cap, non quello modellato.
- **SELECTION-ON-HOLDOUT gate (codificato 2026-06-29, filone B intraday ERM)** — terzo gate in
`altlib.py`, test `tests/test_harness_realism.py`. Il lead ERM faceva `earns_slot=True` MA lo script
di scoperta sceglieva la cella per **`min_hold` massimo** su 60+ celle = **selezione-sull'hold-out**:
scegliendola in-sample-only ne esce un'altra (trend-beta corr→TP01 0.53, NEUTRAL) e il deflated-Sharpe
crolla (DSR 0.0-0.24 su 122 trial). `study_marginal` da solo non lo vede (giudica UNO stream, non *come*
è scelto). Tre funzioni: **`deflated_sharpe()`** (Bailey & Lopez de Prado, PASS ≥0.95), **`select_cell_insample()`**
(cella scelta col solo Sharpe pre-HOLDOUT), e il gate combinato **`study_family_honest(name, factory, grid, tfs)`**
`earns_slot_honest = earns_slot[cella in-sample] AND deflated-Sharpe≥0.95`. **Regola: una strategia
direzionale grid-searched si giudica con `study_family_honest`, non chiamando `study_marginal` sulla
cella a max hold-out.** Chiude il punto cieco gemello di CC01 ("Sharpe implausibile"). Diario
`2026-06-29-intraday-regime.md` (analisi `scripts/research/intraday_regime_analysis.py`).
- **Onestà sul target €50/giorno:** NON raggiungibile su 2000 in 1-2 anni (servono ~130k di
capitale o un DD da rovina). La leva non è la scorciatoia; la via è target-vol + capitale +
tempo. La strategia che *guadagna* esiste, ma a ~+€1.5/giorno su 2000.
@@ -59,13 +389,17 @@ netto fee, out-of-sample, robusto su griglia, e su dati certificati + liquidi +
src/data/downloader.py → load_data(asset, tf): legge i parquet certificati da data/raw/
src/strategies/base.py → Strategy (ABC), Signal, BacktestResult, YearlyStats
src/strategies/indicators.py → indicatori condivisi (ema, atr, keltner, ...)
src/strategies/trend_portfolio.py → TP01: strategia VINCENTE (PORT LF4h), causale, deployabile
src/strategies/trend_portfolio.py → TP01: strategia DIFENSIVA robusta (PORT LF1d, >=12h), causale
src/portfolio/ → PORTAFOGLIO DI STRATEGIE estensibile (Sleeve + StrategyPortfolio)
portfolio.py → combina N sleeve per peso su griglia giornaliera; metriche FULL/hold-out/anno
sleeves.py → REGISTRY sleeve attivi: TP01 33 / XS01 15 / VRP01 12 / SKH01 20 / GTAA01 20. Aggiungere = una riga
src/fractal/ → indicatori frattali (patterns.py, indicators.py, similarity.py)
src/backtest/engine.py → engine di backtesting riusabile
src/backtest/harness.py → harness ONESTO (load BTC/ETH, backtest_signals no-leakage, OOS)
src/version.py → APP_VERSION (legge il file VERSION)
scripts/research/ → ricerca post-reset: track{A-E}_*.py (trend/ML/MR/portfolio/xsec)
scripts/live/paper_trend.py → paper trader forward-only di TP01 (no esecuzione reale)
scripts/research/ → ricerca: track{A-I}_*.py + options_vrp_*.py + fetch_dvol.py
scripts/portfolio/ → run_portfolio.py (report) + xsec_*.py (ricerca/affinamento XS01)
scripts/live/paper_trend.py → paper trader forward-only di TP01 (1d) (no esecuzione reale)
scripts/analysis/ → SOLO i tool dati certificati:
rebuild_history.py → (ri)costruisce lo storico da Deribit mainnet (base 5m + resample)
certify_feed.py → certifica il feed (integrità, coerenza resample, spike, cross-venue)
@@ -87,7 +421,10 @@ uv run python scripts/analysis/certify_feed.py # certifica i feed
uv run python scripts/analysis/certify_feed.py --local # solo check locali (veloce)
uv run python scripts/research/trackD_trendport.py # backtest strategia vincente (full report)
uv run python scripts/research/trackD_timing.py # vincitrice su 15m/1h/4h/1d + PnL/DD/trade per anno
uv run python scripts/live/paper_trend.py # avanza il paper trader TP01 (forward-only)
uv run python scripts/analysis/fetch_hyperliquid.py # fetch+certify universo Hyperliquid (Cerbero mainnet) -> data/raw/hl_*
uv run python scripts/portfolio/xsec_research.py # ricerca cross-sectional su Hyperliquid (XS01)
uv run python scripts/portfolio/run_portfolio.py # report del PORTAFOGLIO attivo (TP01+XS01)
uv run python scripts/live/paper_trend.py # avanza il paper trader TP01 (forward-only, 1d)
uv run pytest # test
```
@@ -111,10 +448,21 @@ df = load_data("BTC", "1h") # OK. load_data("SOL", ...) -> FileNotFoundError (
### Universo ricercabile certificato
- **BTC / ETH**: puliti (2-6 bps vs Coinbase USD su tutta la storia), liquidi (~0% barre flat a 1h),
storia lunga (2018/2019→oggi) → **ogni timeframe (5m/15m/1h)**. È l'unico dato in `data/raw`.
- **Alt (SOL/XRP/ADA/LTC/DOGE/BNB): FUORI.** Illiquidi (LTC 5m 82% barre flat O=H=L=C, run fino a
~3 giorni), divergenti (LTC/DOGE >1% su 10-21% delle barre 2022-23), o non certificabili
(XRP delistato da Coinbase per causa SEC; BNB non listato + storia da 2024-10). Sono archiviati in
`Old/data/raw`. Riammetterne uno richiede prima una ricertificazione che dimostri liquidità + accordo.
- **Alt Deribit (SOL/XRP/ADA/LTC/DOGE/BNB): FUORI.** Illiquidi (LTC 5m 82% barre flat, run ~3 giorni),
divergenti, o non certificabili. Archiviati in `Old/data/raw`.
- **Universo Hyperliquid (Cerbero MCP MAINNET): 19 alt liquidi a 1d, dal 2024** — BTC/ETH/SOL/BNB/XRP/
DOGE/AVAX/LINK/LTC/ADA/ARB/OP/SUI/APT/INJ/TIA/SEI/NEAR/AAVE. Certificati (`fetch_hyperliquid.py`):
flat 0%, cross-venue 4-9 bps vs Binance, >1% ≈0% → `data/raw/hl_*_1d.parquet`. **Caveat:** storia
nativa solo **~2.5 anni** (2024-2026; pre-2024 = backfill, vol 0). Abilita le strategie
CROSS-SECTIONAL (impossibili a 2 asset). NB: Cerbero col token TESTNET = farlocco; col token
**mainnet** (`.env.mainnet`) = reale, ma SEMPRE da certificare (cross-venue + liquidità).
⚠️ **CORREZIONE estrazione (2026-06-20):** il backfill NON è solo pre-2024 — cerbero MCP padda con
barre SINTETICHE (volume 0, prezzi copiati da Binance → matchano cross-venue e non sono flat) ogni
asset listato su HL **dopo** lo START. Il `flat`+cross-venue da soli non lo vedono: il rivelatore è
il **VOLUME**. `fetch_hyperliquid.py` ora (1) taglia il run iniziale a volume 0, (2) scarta chi resta
< 365g reali (es. **AXS 83% sintetico → fuori**), (3) gata i gap vol=0 interni. Universo certificato
= **51** (era 52). I **19 major di XS01 hanno 0 backfill → invariati** (strategia live non toccata).
Verificato direttamente su cerbero MCP. Diario `2026-06-20-cerbero-backfill-fix.md`.
## Metodologia obbligatoria per ogni nuova strategia
+11
View File
@@ -0,0 +1,11 @@
FROM python:3.11-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY src/ src/
COPY scripts/ scripts/
COPY VERSION ./
VOLUME /app/data
# Monitor PAPER del portafoglio attivo (TP01+XS01). Esecuzione REALE disabilitata.
CMD ["uv", "run", "python", "-m", "src.live.dashboard", "--port", "8787"]
+9
View File
@@ -0,0 +1,9 @@
{
"_nota": "Config esecuzione LIVE del BOOK DERIBIT (TP01+SKH01 nettati in software). execution_enabled=true + --execute -> ordini REALI. ARMATO 2026-06-23: esecutore scripts/live/book_execute.py via cron ORARIO scripts/cron_book.sh (SKH01 e' a 230m). disaster-SL on-book -30% sulla posizione netta. Tutto flat all'arming -> nessun ordine finche' un segnale non arma.",
"_nota_cap": "Cap notional per-asset DINAMICO (frontiera 2026-07-03): con max_notional_per_asset_frac=0.5 il cap = equity/2, cosi' cresce col capitale e un deposito non resta strozzato. A ~$600 equity/2=~$300 -> INERTE (identico al vecchio cap fisso). Il cap dinamico si usa solo con equity reale fidata; su fallback/offline si ripiega su max_notional_per_asset_usd (protezione downside). Per tornare al cap fisso: rimuovere max_notional_per_asset_frac.",
"execution_enabled": true,
"max_notional_per_asset_usd": 300,
"max_notional_per_asset_frac": 0.5,
"min_order_usd": 5,
"disaster_sl_pct": 0.30
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+32
View File
@@ -0,0 +1,32 @@
# Solo MONITOR (dashboard paper) del portafoglio attivo. Niente runner/esecuzione reale
# (archiviati in Old/). v2.0.0+.
services:
dashboard:
build: .
container_name: pythagoras-dashboard
restart: unless-stopped
command: ["uv", "run", "python", "-m", "src.live.dashboard", "--port", "8787"]
ports:
- "8787:8787"
volumes:
- ./data:/app/data:ro
# token mainnet (sola lettura) per lo "Shadow live": conto/posizioni reali sulla dashboard.
# Montato a runtime (NON nell'immagine: .env.mainnet e' dockerignored). Solo letture, nessun ordine.
- ./.env.mainnet:/app/.env.mainnet:ro
# IB Gateway (PAPER) per la RICERCA DATI Interactive Brokers — replica il setup provato di BuzWay
# (scout). IBC fa login automatico headless; nessuna GUI desktop. API READ-ONLY (solo dati storici,
# MAI ordini). Bind SOLO su 127.0.0.1 -> non esposto in rete. Credenziali in .env.ibgw (gitignored).
# host 4002 -> container 4004 (socat paper), esattamente come nel connect("127.0.0.1", 4002).
ib-gateway:
image: ghcr.io/gnzsnz/ib-gateway:stable
container_name: pythagoras-ibgw
restart: unless-stopped
env_file: .env.ibgw
environment:
TRADING_MODE: paper
READ_ONLY_API: "yes" # SOLO dati: nessun ordine possibile via API
TWOFA_TIMEOUT_ACTION: restart
TIME_ZONE: Europe/Rome
ports:
- "127.0.0.1:4002:4004" # gateway paper (socat) raggiungibile solo da localhost dell'host
+35
View File
@@ -0,0 +1,35 @@
# 2026-06-19 — Wave 1 "beat TP01" (26 agenti BTC/ETH): nessun 3º sleeve robusto
Goal "trova strategie che battano l'esistente e inseriscile": GIA' soddisfatto da XS01 (cross-
sectional Hyperliquid, integrato → portafoglio TP01 70% + XS01 30%, FULL Sh 1.41 / HOLD 1.15).
In parallelo, una wave di 26 agenti ha cercato su BTC/ETH miglioramenti del trend + diversificatori.
## Esito wave 1 (26 agenti, 25 leak-free): 22 weak, 3 "contender", 1 noise
I 3 contender, ri-verificati ONESTAMENTE col giudice book-level (`verify_contender.py`) e come
contributo marginale al portafoglio ATTUALE (TP01+XS01):
| Candidato | corr TP01 | corr XS01 | +portafoglio (w30%) | Verdetto |
|---|---|---|---|---|
| **tsmom_strength_12h** | **+0.49** | — | — | ☠️ scartato: è TP01 più veloce (correlato), non diversifica |
| **breakout_atr** (trend) | 0.04 | 0.04 | FULL +0.48 / **HOLD +0.05** | ☠️ scartato: gonfia solo il FULL storico (bull), ~zero valore nel hold-out |
| **highvol_rev** (reversal alta-vol) | 0.08 | 0.05 | FULL +0.20 / **HOLD +0.30** | 🟡 WATCHLIST (vedi sotto) |
## highvol_rev: candidato vero ma NON abbastanza robusto → watchlist
È l'unico genuinamente scorrelato a ENTRAMBI gli sleeve e che migliora FULL+hold-out. MA il mio
robustezza-check indipendente (plateau, come per XS01) lo boccia per il deploy:
- **Edge solo a REV_LB=1**: LB2 FULL Sh 0.33, LB3 ~0.05 → **picco a singola-barra, non plateau**.
- **FULL standalone mediocre** (0.74); la forza è nel hold-out (HOLD 0.97-1.39 vs FULL ~0.7) =
**HOLD≫FULL = regime-luck dell'alta-vol 2025-26**, non robustezza temporale.
- È un **reversal** (famiglia morta in tutto il progetto) con concept ribaltato post-hoc
(low-vol→high-vol). Regge fee fino ~0.3% ma con margine ridotto.
Stesso difetto (HOLD≫FULL, no-plateau) per cui ho bocciato ieri il RV ETH/BTC regime-luck. La
disciplina che boccia i falsi positivi vale anche qui → **NON deployato**, in watchlist; rivalutare
forward (più dati) o se emerge un plateau su un parametro core.
## Conclusione
Wave 1 NON aggiunge un 3º sleeve robusto. **Portafoglio invariato: TP01 (70%) + XS01 (30%).** Le
famiglie trend (breakout/tsmom-12h) sono ridondanti con TP01 o aiutano solo il bull storico; l'unico
diversificatore di meccanismo nuovo (highvol_rev) non regge il bar di robustezza. Il vero edge
incrementale è venuto dall'ESPANSIONE DELL'UNIVERSO (Hyperliquid → cross-sectional), non da altre
varianti di trend su 2 asset. Direzione futura coerente: più asset certificati + sleeve di
meccanismo nuovo (non altre trend-variant), col criterio plateau+breadth+contributo.
@@ -0,0 +1,62 @@
# 2026-06-19 — Ricerca frattale multi-agente (63 agenti) su BTC/ETH
Su richiesta: 50+ agenti in parallelo a cercare strategie NUOVE ispirate ai due documenti
frattali (`Libro_frattali` + `Pythagoras_Trading_Prediction`), timing/asset diversi, ognuna
validata sull'harness onesto. Eseguito come Workflow: **63 agenti, ~2h, 3.8M token.**
## Cosa è stato testato
16 concetti frattali estratti dai documenti (sotto la patina esoterica: coscienza, frequenze
Solfeggio, numeri sacri → idee testabili): alfabeto candle U/D/0 (3-6, LONG), Fourier/cicli,
ricorrenza di Poincaré (analoghi kNN), centro di inversione Evideon (mirror tempo+prezzo),
indicatore H-C (~588/25 ≈ 23.5 barre), numeri-universali come periodi, invarianza di forma,
entropia di Shannon ("coscienza") come gate, confluenza multi-TF, grammatica composizionale,
fase-ricorrenza. × BTC/ETH × {5m,15m,1h} = **52 ipotesi**.
Ogni segnale: scritto da un agente come funzione `signal()`, valutato da `eval_signal.py`
(stesso harness onesto) con **guard automatico anti-look-ahead** (ricalcolo su prefissi).
Superstiti → verifica avversariale con sblocco una-tantum del **hold-out 2025-26**.
## Esito
- **Verdetti**: 29 rumore, 12 "real" (netto-fee positivo ma non battono il buy&hold), 11 "edge"
(in-sample: battono B&H + null p<0.05 + leak=0).
- **Guard anti-look-ahead**: nessun leak passato (gli agenti hanno prodotto segnali causali; i
pochi tentativi con futuro sono stati auto-squalificati e corretti).
- **Hold-out (la prova del nove)**: dei **11 superstiti in-sample, 10 REFUTATI** — performance
catastrofica nel 2025-26 (hurst-DFA 0.49, hc-cycle 0.83, vol-accel 1.16, universal-periods
0.42…−1.04, spectral-entropy 0.38/+0.29, multitf 0.49, solfeggio-BTC 0.64). Stessa firma di
sempre: **regime-luck del toro 2018-2024, sparito out-of-sample.**
- **1 "confermato"** dalla verifica per-agente: `momentum_solfeggio_cycle` **ETH 1h** (holdout
Sharpe +1.19, ret +49% mentre il buy&hold ETH faceva 49%). Sembrava un trionfo.
## Ma il "vincitore" cade al test cross-asset (kill decisivo)
Il guard per-agente valuta un asset alla volta e non poteva vedere il quadro. Ho rieseguito **lo
stesso identico codice** sui due major:
| Signal (identico) | FULL Sharpe | HOLD-OUT Sharpe | HOLD-OUT ret |
|---|---|---|---|
| Solfeggio-cycle su **ETH** 1h | 1.54 | **+1.19** | +49% |
| Solfeggio-cycle su **BTC** 1h | 1.17 | **0.25** | 7.5% |
Un edge robusto non fallisce sull'altro major. La stessa logica (long-only ~20% esposta, filtro
SMA(588), timing su ciclo ~24) che ha "schivato" il crash ETH 2025 **perde su BTC nello stesso
hold-out**. È **fortuna di regime di un singolo asset**, non skill. Aggravanti: costanti
numerologiche ad-hoc (24/588/56, "odore" di overfit, già notato dal verificatore); e con 52 trial,
trovare 1 segnale che passa un singolo regime di hold-out è atteso per puro caso (1/11 ≈ chance).
## VERDETTO
**La ricerca frattale multi-agente (52 ipotesi, 63 agenti) NON ha trovato alcun edge robusto.**
I concetti frattali/esoterici si sono comportati esattamente come le famiglie convenzionali (Fasi
1-3): edge in-sample da regime-luck del toro, refutati dal hold-out; e l'unico che passava il
hold-out su un asset fallisce sull'altro. **Nessuna magia nei numeri Solfeggio/sacri.**
Il valore: il processo disciplinato (guard anti-look-ahead + hold-out bloccato + **test cross-asset**)
ha catturato un falso "trionfo" (+49% vs 49%!) che sul vecchio sistema contaminato sarebbe finito
dritto in produzione. È la quinta conferma indipendente che su BTC/ETH non c'è un edge facile.
## Stato della ricerca dopo tutte le fasi
Testato: mean-reversion, momentum/trend, vol, lead-lag, hurst, shape-ML, e 16 famiglie frattali ×
multi-TF/asset. **Niente di robusto, fee-surviving, OOS e cross-asset.** Le direzioni oneste
restano: (a) accettare il ceiling = long risk-managed (no alpha); (b) allargare l'universo dati
CERTIFICATO oltre BTC/ETH; (c) fonti di segnale ortogonali al prezzo (on-chain, basis multi-venue,
opzioni multi-regime) — tutte richiedono nuovi dati certificati. Artefatti: `eval_signal.py`,
workflow `fractal-strategy-search`, ~52 segnali in `/tmp/pyth_sig_*.py`.
+60
View File
@@ -0,0 +1,60 @@
# 2026-06-19 — Espansione universo (Hyperliquid via Cerbero mainnet) → XS01 batte il portafoglio
L'utente: "ci dovrebbe essere uno storico dati preso da cerbero". Aveva ragione, ed è la chiave per
superare il soffitto a 2 asset.
## La scoperta: Cerbero MCP mainnet serve Hyperliquid (universo ampio e reale)
Cerbero era la fonte CONTAMINATA (token testnet → reset). MA col token **mainnet** (`.env.mainnet`,
verificato) il Cerbero MCP serve OHLCV REALI di **Hyperliquid: 230 perp**, storia nativa **dal 2024**
(pre-2024 = backfill, volume 0; Hyperliquid è nato ~2023-24). Prezzi recenti plausibili.
## Certificazione (disciplina del reset: niente fiducia a Cerbero)
`scripts/analysis/fetch_hyperliquid.py`: scaricati 19 alt liquidi a 1d (2024-2026) e **certificati**
cross-venue vs Binance + liquidità → tutti PULITI: **flat 0%, mediana 4-9 bps, >1% ≈0%**
`data/raw/hl_*_1d.parquet` (namespace dedicato). Caveat onesto: **~2.5 anni** di storia nativa.
## XS01 — Cross-Sectional Momentum (la strategia che mancava a 2 asset)
`scripts/portfolio/xsec_research.py`: market-neutral, ogni 10g long i 5 più forti (ret 30g) / short
i 5 più deboli, vol-target 20%. Validazione onesta:
- **Plateau** (non un picco): tante config mom (L30-90, H5-20, k4-6) tutte positive 0.6-0.98.
- **Fee-robusto**: FULL Sh 0.79→0.68 da fee 0% a 0.3% RT.
- **Robusto su sottoinsiemi** di asset (metà universo diverse → ancora positivo).
- **Scorrelato a TP01 (~0.06)**, **positivo OGNI anno** (2024 +2%, 2025 +19%, 2026 +20%).
- **Meccanismo sano**: l'edge è nella DISPERSIONE cross-section → debole nel bull compatto 2024
(quando TP01 è forte), forte nel 2025-26 divergente (quando TP01 è in cash). **Complementare**.
Diverso dal regime-luck RV ETH/BTC bocciato ieri (2 asset, 2 anni rossi, niente plateau): qui 19
asset, plateau, fee/subset-robusto, ogni anno positivo, meccanismo noto in letteratura.
## Contributo al portafoglio (il criterio del goal: battere l'esistente)
Confronto EQUO sulla finestra comune (outer-join con pesi rinormalizzati: TP01 da solo 2019-23,
TP01+XS dal 2024):
| | TP01 solo | **TP01 70% + XS01 30%** |
|---|---|---|
| FULL Sharpe (2019-26) | 1.30 | **1.41** |
| **HOLD-OUT 2025-26 Sharpe** | 0.31 | **1.15** |
| HOLD-OUT ret / DD | +3.5% / 7.5% | **+15.1% / 5.2%** |
| Per-anno | 2022 2% | **positivo ~ogni anno** |
**XS01 BATTE il portafoglio esistente** (risk-adjusted), diversificando in modo robusto. Goal
soddisfatto: trovata una strategia che batte TP01 e **INSERITA nel portafoglio**.
## Integrazione
- `src/portfolio/portfolio.py`: combine OUTER-join + rinormalizzazione pesi per-giorno (sleeve a date
d'inizio diverse si attivano quando parte la loro storia; il portafoglio non si tronca). Test nuovo.
- `src/portfolio/sleeves.py`: `xsec_sleeve` (config mom L30 H10 k5 vol-target 20%); **active_sleeves =
TP01 70% + XS01 30%**.
- `fetch_hyperliquid.py`, `xsec_research.py`. 12 test passano.
## Caveat onesti (da non dimenticare)
- **Storia XS solo ~2.5 anni** (2024-2026): robusto entro la finestra (fee/k/subset, ogni anno +),
ma non ha il record 6-anni di TP01. Cross-sectional momentum è literature-robust → prior favorevole.
- **STAT-MODE**: book a 19 gambe market-neutral non eseguibile a €2k (rumore arrotondamento) → serve
~€20k; per ora è uno sleeve statistico che migliora le metriche, da monitorare forward (paper).
- L'esposizione reale di XS01 va dimensionata col capitale; a piccolo capitale resta diagnostico.
## Stato
Portafoglio attivo = **TP01 (70%) + XS01 (30%)**, FULL Sh 1.41 / HOLD 1.15. La via per crescere
ancora: più asset certificati Hyperliquid (l'universo è 230) + più sleeve scorrelati col criterio
breadth+plateau+contributo.
+81
View File
@@ -0,0 +1,81 @@
# 2026-06-19 — Options VRP sleeve: infrastruttura + prima validazione onesta
Impostata la ricerca dello sleeve income opzioni (vendita put settimanali, incassa il volatility
risk premium IV>RV). Lead identificato dalla valutazione di `crypto_backtest` come la via per
superare il soffitto Sharpe ~1.3 (fonte di rendimento DIVERSA, scorrelata al trend).
## Infrastruttura costruita
- `scripts/research/fetch_dvol.py`: storia DVOL (IV 30d Deribit) BTC/ETH **2021-03 → 2026-06**
(1914g) → `data/raw/dvol_*.parquet`. È l'input IV.
- `scripts/research/options_vrp_lab.py`: motore backtest CSP settimanale. Prezzo put BS su DVOL
reale + **calibrazione f** (skew/spread vs quote reali), strike a delta target, payoff sul path
realizzato dei prezzi certificati. Causale (decisione a sell-date, payoff a scadenza). Gauntlet:
VRP context, sweep f/delta, per-anno, worst-weeks (coda), correlazione + contributo vs TP01.
- `scripts/research/options_real_quote_check.py` (dal branch): verifica premio su quote reali.
## VRP reale (contesto)
BTC DVOL 61% vs RV 53% → **VRP +7.8 pt, positivo 78% del tempo**; ETH +3.7 pt, 67%. Il premio di
volatilità esiste ed è più ricco su BTC.
## Risultati (book 50/50 BTC+ETH, put settimanali delta -0.28)
**Tutto dipende dalla CALIBRAZIONE f del premio:**
| f | Sharpe | CAGR | maxDD | worst-week |
|---|---|---|---|---|
| 0.70 | 0.32 | 12% | 51% | 26% |
| 0.85 | 0.20 | +1% | 35% | 26% |
| **1.00 (conservativo, IV-ATM)** | **0.71** | +16% | 33% | 26% |
| 1.15 | 1.22 | +34% | 32% | 25% |
| **1.29 (reale calm, con skew)** | **1.70** | +52% | 31% | 25% |
- A f=1.0 (ignora il bonus skew): Sharpe **0.71** — SOTTO TP01. A f=1.29 (skew reale misurato in
regime calmo): **1.70**. La verità sta in mezzo E f varia col regime (skew più alto nello stress).
- **Delta**: più ATM = più premio + più rischio (0.15→Sh 0.25, 0.28→0.71, 0.40→0.95).
**La CODA è severa (è short-vol):** maxDD standalone **30-33%**, singole settimane **15..26%**
(2021-05 crash, 2022-05/06 LUNA, 2026-02/06). Per-anno (f=1.0): 2022 **9%**, 2026-YTD **14%** —
sanguina negli anni di crash. HOLD-OUT 2025-26: Sharpe **0.04** a f=1.0 (piatto), 0.94 a f=1.29.
**Diversificazione (reale):** corr settimanale a TP01 **+0.07** (scorrelato). Contributo (f=1.0):
TP01 70% + OPT 30% → Sharpe settimanale 0.71→**0.97**, DD basso (11%). Anche al premio conservativo
migliora il portafoglio per pura decorrelazione.
## Verdetto — LEAD reale, NON deploy-ready
- ✅ Il VRP è reale (IV>RV 78%), lo sleeve è **genuinamente scorrelato** al trend (+0.07) e
**migliora il portafoglio** anche a premio conservativo. È la fonte di rendimento DIVERSA che
cercavamo per superare il soffitto ~1.3.
- ⚠️ MA: (a) le metriche headline dipendono da una calibrazione **ottimistica** (f=1.29);
conservativo (f=1.0) → Sharpe 0.71 con **DD 33%**. (b) Premio **MODELLATO** (BS su DVOL), non un
backtest su catena reale; la verifica su quote reali è UN solo snapshot calmo. (c) Il **rischio di
coda** (roll/assignment/gap nello stress, skew che esplode) NON è pienamente catturato.
- Regola del progetto: **mai deployare uno short-vol prezzato da un modello.** → NON aggiunto al
portafoglio. Portafoglio attivo invariato: TP01 70% + XS01 30%.
## CALIBRAZIONE su quote REALI cerbero-bite (`options_vrp_calibrate.py`) — corregge l'ottimismo
cerbero-bite GIA' accumula la catena reale mainnet (option_chain_snapshots, BTC 224k / ETH 237k
righe, 2026-05→oggi). Usandola (non un nuovo snapshotter), misurato il fattore f reale su 223
snapshot/asset (put weekly ~delta -0.28, vendita al BID):
- **BTC: f mediano 1.03** (IQR 0.89-1.21), skew reale **+1.9 pt** (IV put 43.5% vs DVOL 41.6%).
- **ETH: f mediano 0.97** (IQR 0.88-1.11), skew **+1.5 pt**.
- **Il f reale e' ~1.0, NON 1.29.** Lo snapshot singolo del branch (skew +4.8 → f 1.29) era un
OUTLIER; sulla media lo skew e' modesto e il bid/ask lo compensa → premio reale ≈ modellato.
→ Il VRP sleeve sta sul punto **f≈1.0 dello sweep = Sharpe ~0.71** (caso CONSERVATIVO), DD 33%,
hold-out ~piatto (0.04). Non il 1.70 ottimistico. Resta un diversificatore modesto (corr +0.07,
migliora il portafoglio settimanale 0.71→0.97 a 30%), ma standalone SOTTO TP01 e con coda severa.
**CAVEAT:** la finestra di calibrazione reale e' ~10 giorni densi (06-09→06-19, cerbero-bite ruota
le scadenze → i weekly compaiono sparsi) e UN regime calmo. Il f di STRESS resta non misurato.
## Verdetto aggiornato
Al premio REALE (f≈1.0), il VRP sleeve e' un diversificatore DEBOLE (Sharpe ~0.71 < TP01, DD 33%,
hold-out piatto): la modesta decorrelazione NON giustifica il rischio di coda short-vol senza molto
piu' dato reale multi-regime. **Confermato NON-deploy.** Il valore vero arriva solo se cerbero-bite,
continuando ad accumulare, copre un CRASH: lì si misura il f reale di stress e si fa un backtest su
catena reale. Fino ad allora, lead quantificato ma in attesa. Portafoglio invariato TP01 70%+XS01 30%.
## Prossimi passi per graduare il lead a sleeve deployabile
1. **Accumulo forward di quote reali** (bid/ask + skew della put settimanale delta-0.28, ogni giorno,
su più regimi) → sostituire il premio modellato con quello reale e misurare f nello stress.
2. **Stress crash-week con spread reali** (rollabilità, assignment, gap inverso/coin-settled).
3. **Daily-MTM** dello short put per l'integrazione nel portafoglio giornaliero (ora è settimanale).
4. **Paper-trade su Deribit testnet** prima di qualsiasi capitale.
Solo dopo, se regge a premi reali multi-regime, aggiungerlo come 3º sleeve (scorrelato, income).
@@ -0,0 +1,58 @@
# 2026-06-19 — Ricerca v2.0.0: Fase 0 (harness) + Fase 1 (triage superstiti)
Primo log di ricerca post-reset. Universo certificato: BTC/ETH, 1h. Hold-out 2025+ BLOCCATO.
## Fase 0 — harness onesto (`scripts/analysis/research_lab.py`)
Banco di prova causale per costruzione (modello a SERIE DI POSIZIONE: `pos[i]` decisa entro
`close[i]`, guadagna `close[i]→close[i+1]`, fee sul turnover |Δpos|). Metriche
Sharpe/CAGR/DD/exposure/turnover, finestra OOS, **null model a rotazione circolare**
(p-value: il timing batte il caso?), baseline buy&hold, sweep fee.
**Self-test del banco (valida l'HARNESS, non una strategia):**
- buy&hold BTC: Sharpe 0.79 (sanity OK).
- CHEAT look-ahead (pos = segno del rendimento futuro): Sharpe **58**, p=0.005 → l'engine
VEDE un edge reale quando esiste.
- NOISE causale a basso turnover: Sharpe **0.14**, p=0.26 → l'engine NON inventa edge dal
nulla (niente leak, niente skill spuria).
Il banco è affidabile. → ogni numero qui sotto è netto fee e causale.
## Fase 1 — triage dei 2 superstiti (`scripts/analysis/phase1_survivors.py`)
Sul feed pulito solo SH01 (shape-ML) e frammenti HONEST mostravano segnale residuo. Delle
HONEST solo **DIP** è testabile su BTC/ETH (TR01/ROT02 richiedono alt esclusi). Re-implementati
come serie di posizione, passati ai gate onesti.
### DIP reversion (long-only) — ☠️ MORTO
Griglia 3×3 (n, k) **tutta negativa** su entrambi gli asset (nessun plateau). Config centrale
n50 k2.0: FULL Sharpe 0.17 (BTC) / 0.06 (ETH); a fee 0% appena +0.02/+0.09 (niente edge nemmeno
lordo). OOS-VAL marginale (+0.36/+0.16) ma **null p=0.84-0.89** (peggio del caso). Rumore.
### SH01 shape-ML (walk-forward LogReg) — ☠️ FEE-DEAD
Pattern coerente su BTC/ETH, long/short e long-only:
| Variante | Sh fee0% | Sh fee0.05% | Sh fee0.10% | trade/anno | null p |
|---|---|---|---|---|---|
| BTC L/S | +0.32 | 0.70 | 1.71 | 877 | 0.167 |
| BTC long-only | +0.73 | 0.06 | 0.84 | 555 | 0.072 |
| ETH L/S | +0.31 | 0.40 | 1.11 | 773 | 0.137 |
| ETH long-only | +0.46 | 0.04 | 0.53 | 485 | 0.142 |
C'è un **sussurro di segnale LORDO** (Sharpe 0.3-0.7 a fee zero) ma il turnover (485-877
trade/anno) lo divora: a fee reale tutte negative, e **nessuna batte il null** (p>0.05). Net-fee:
rumore.
## VERDETTO Fase 1
**Né DIP né shape-ML sopravvivono su BTC/ETH certificato net-fee.** Nessuno dà Sharpe netto >0,
nessuno batte il null (p<0.05), nessuno batte il **buy&hold** (Sharpe 0.79/0.84 — di fatto la
"strategia" più forte vista finora). Si conferma: i "superstiti" della vecchia libreria erano,
come il resto, non-edge. Chiusi.
## Lead onesto per la Fase 2
L'unico segnale non-nullo è il **gross shape-ML** (Sharpe 0.3-0.7 a fee zero), ucciso dal
turnover. Direzione: esprimere quel segnale a **turnover molto più basso** (orizzonte di holding
lungo, soglia forte, o come GATE di regime invece che flip per-barra) per vedere se il sussurro
lordo sopravvive alle fee. È un lead, NON un edge. Inoltre: la barra reale da battere è il
**buy&hold** (Sharpe ~0.8) — una strategia di timing deve fare meglio di "stai sempre long",
net-fee.
@@ -0,0 +1,69 @@
# 2026-06-19 — Ricerca v2.0.0: Fase 2 (famiglie) + analisi OPTIONS
Universo certificato BTC/ETH. Barra da battere = **buy&hold** (Sharpe 0.79 BTC / 0.84 ETH).
Tutto netto fee 0.10% RT, hold-out 2025+ BLOCCATO. Harness: `research_lab.py`.
## Fase 2 — esplorazione famiglie (`phase2_families.py`)
24 combinazioni famiglia×asset×TF, ognuna: scan griglia → config migliore → gate onesti
(FULL/OOS-VAL, vs buy&hold, null p-value a rotazione, sweep fee).
### Esiti per famiglia
- **REVERSAL (mean-reversion breve): ☠️ MORTA OVUNQUE.** FULL Sharpe da 1 a 5.6 (peggio a
15m: fee-death, 5.6 BTC / 4.6 ETH), gross ≈0, null p 0.45-0.82. **Smentisce definitivamente
la tesi storica del progetto ("l'edge è sempre mean-reversion")**: era artefatto del feed.
- **TSMOM / MA-cross / Donchian (trend, long-only): segnale REALE ma MODESTO.** Le versioni
long-only (basso turnover) battono o eguagliano il buy&hold:
- **MA-cross long-only**: ETH FULL **1.12** / OOS 0.89 / p **0.007**; BTC FULL **0.90** / OOS
1.99 / p **0.040**. Plateau sulla griglia (ETH 12/48 e 48/192 entrambi 1.1), coerente sui
DUE asset, basso turnover (53-106 trade/anno). **Unici 2 a passare: battono B&H + OOS>0 + p<0.05.**
- Donchian long-only: FULL 0.84-0.94, OOS ottimo (BTC 2.37) ma p 0.08-0.10 (pochi trade → null
rumoroso). TSMOM long-only: ETH 0.83 (≈B&H). Le L/S perdono (turnover + short su asset in trend).
- **VOL-TARGET overlay**: ≈ buy&hold (FULL 0.77-0.84), p alto → non distinguibile dal B&H, ma è
un riduttore di vol/DD (mantiene lo Sharpe scalando l'esposizione).
- **HURST-gate, LEAD-LAG BTC↔ETH**: niente. (Hurst-mom ETH p=0.043 ma sotto il B&H; lead-lag
fee-dead.)
### Verdetto Fase 2
L'unica cosa reale su BTC/ETH certificato è il **trend-following long-only** (MA-cross in testa):
un **long con gestione del rischio** che batte il buy&hold di poco (Sharpe ~0.9-1.1 vs 0.8)
evitando i drawdown peggiori. È un effetto noto in letteratura (time-series momentum), NON alpha
market-neutral. **Caveat multiple-testing**: 2 flag su ~24 test ≈ soglia del caso; ma la stessa
famiglia vince su ENTRAMBI gli asset con plateau → è un LEAD genuino, non confermato. La barra
vera resta il B&H, e l'OOS-VAL alto di BTC (1.99) puzza di "2024 anno di trend forte" → serve la
prova del hold-out 2025-26 + regimi bear + stress fee/slippage + deflated-Sharpe (Fase 3).
## Analisi OPTIONS (`options_analysis.py`)
Dati reali cerbero-bite mainnet, ma finestra **~2026-05-01→06-11 (~6 sett., REGIME UNICO calmo)**.
### Livelli misurati (reali)
- **VRP (IV RV) positivo il 100% del tempo**: BTC +10, ETH +14 punti di vol annua. Le opzioni
sono sistematicamente CARE in questa finestra → vendere vol/covered-call avrebbe incassato premio.
- **Skew put positivo**: BTC IV put-10%OTM 44% vs call 35% (skew +10 pt); ETH 54 vs 49 (+5). Il
crash è prezzato (assicurazione cara).
- **Costo put protettiva** (mensile, %-del-notional): ~10% OTM = **0.98% BTC / 1.36% ETH**; ATM
3.3%/5.0%; ~15% OTM 0.83%/0.71%. Liquidità: ATM spread ~3%, OTM 7-12%. Mensile ben popolato
(499-2043 strike), settimanale OTM sottile. Funding perp ≈ 0 (nessun carry).
### Verdetto OPTIONS
**Nessun edge su opzioni è validabile ora**: 6 settimane, regime unico calmo. Il segnale
VRP-positivo / sell-vol è ESATTAMENTE ciò che brilla in calma e salta in aria nei crash (è il
rischio che viene pagato) — non testabile senza un crash nel campione. Ruoli legittimi (entrambi
NON validabili ora, solo forward):
- **(a) Tail-cap / catastrofe**: put OTM standing su un book long (il candidato trend ha DD grossi).
Costa ~1-1.5%/mese a 10% OTM — gateabile coi premi reali misurati qui. Overlay per-trade 24h
INFATTIBILE (strike OTM corti inesistenti/illiquidi); standing settimanale/mensile FATTIBILE.
- **(b) Harvest del VRP** (covered call / put-spread): +10-14 pt ci sono ORA, ma è una scommessa
short-vol che richiede un crash nel campione per essere giudicata onestamente. Non l'abbiamo.
**Raccomandazione**: le opzioni NON sono un'avenue di ricerca a breve (manca storia multi-regime).
Mosse: (1) lasciare cerbero-bite ad accumulare (gratis, reale, costruisce in avanti il dataset
multi-regime); (2) rivalutare quando la finestra attraversa un crash/alta-vol; (3) intanto, l'unico
uso giustificato è come OVERLAY (tail-cap su una strategia spot), gateato sui premi reali qui sopra.
## Prossimo passo
Fase 3 sul solo candidato reale (trend-following long-only, MA-cross): sblocco UNA volta del
hold-out 2025-26, comportamento nei bear (2018/2022), stress fee×2 + slippage + lag, deflated-Sharpe
per il multiple-testing. Se regge → è la prima strategia onesta del progetto v2.0.0 (modesta:
migliora il buy&hold, non lo stravolge). Se non regge → anche il trend era sample-luck.
@@ -0,0 +1,62 @@
# 2026-06-19 — Ricerca v2.0.0: Fase 3, conferma avversariale del candidato trend
Candidato: **trend-following long-only (MA-cross)**, l'unico a passare i gate base in Fase 2.
Protocollo: selezione config solo pre-hold-out → sblocco una-tantum del hold-out 2025-26 →
breakdown bear → stress → deflated-Sharpe. Script `phase3_confirm.py`.
## Esito: ☠️ NON CONFERMATO — era regime-luck del mercato toro
### (1) Pre-hold-out (2018-2024): forte e robusto
Plateau pieno: BTC Sharpe 0.91-1.16, ETH 1.19-1.48 su tutte le config. **Deflated-Sharpe**
(N=60 trial): BTC DSR **0.990**, ETH **0.982** → l'effetto trend era REALE e robusto al
multiple-testing **sul 2018-2024**.
### (2) HOLD-OUT 2025-26 (sbloccato una volta) — FALLISCE
| | buy&hold | trend 24/96 | trend 96/288 (slow) |
|---|---|---|---|
| BTC Sharpe | 0.37 | **0.81** | 0.00 |
| BTC ret | 32.9% | 33.6% | 5.0% |
| ETH Sharpe | 0.32 | **0.95** | 0.01 |
| ETH ret | 49.3% | 52.0% | 11.3% |
Il 2025-26 è stato un periodo in DISCESA (buy&hold negativo). Il trend long-only — che "dovrebbe"
schivare i bear — si è fatto **frullare** (whipsaw): perde quanto o PIÙ del buy&hold, Sharpe negativo
su ogni config. Solo la MA lentissima (96/288) limita i danni a ~flat (5/11%), ma è cherry-pick
post-hoc e comunque NON positiva.
### (3) Per anno — il meccanismo
Il trend cattura ~70-80% degli anni TORO (2019-2024) e attutisce i bear IN-SAMPLE (2018 1% vs
39%; 2022 47% vs 65%). MA nel 2025 OUT-OF-SAMPLE ha fatto **peggio** del buy&hold (BTC 25% vs
7%; ETH 41% vs 11%): frullato in un mercato choppy/discendente. È il classico fallimento del
trend-following nei bear laterali. → l'edge 2018-24 era **beta del toro con risk-management**, non
alpha persistente.
### (4) Stress
FULL regge modestamente (Sharpe 0.65-0.91 anche a fee2x+lag), ma HOLD-OUT è negativo ovunque
(0.81 → 1.34) e peggiora sotto stress. Fragile.
### (5) Deflated-Sharpe
DSR>0.95 sul pre-hold-out → conferma che l'effetto era statisticamente reale **nel campione di
training**. Lezione chiave: **robustezza statistica in-sample ≠ persistenza out-of-sample.** Il
hold-out bloccato ha colto ciò che DSR da solo non poteva — il cambio di regime.
## VERDETTO FINALE (Fasi 0-3)
**Nessun edge validato, fee-surviving e out-of-sample esiste su BTC/ETH tra le famiglie testate.**
Il trend-following era il miglior candidato: reale 2018-24 (toro), ma **bocciato sul hold-out
2025-26** (whipsaw, sotto il buy&hold). La barra realistica resta il **buy&hold** (Sharpe ~0.8
sullo storico, ma 0.3/0.4 nel 2025-26: anche "stai long" è stato duro di recente).
Il processo disciplinato ha funzionato: **ha evitato di deployare un falso edge** (che, sul vecchio
sistema contaminato, sarebbe finito in produzione). Questo è il valore del reset.
## Implicazioni / direzioni
- **Non deployare** il trend come edge: è regime-dipendente, non batte il buy&hold OOS.
- Con **solo BTC/ETH prezzo**, il pozzo dei segnali è poco profondo: timing puro non ha edge robusto.
- Opzioni: nessun ruolo a breve (confermato). Tenere cerbero-bite ad accumulare per uno studio
multi-regime futuro.
- Scelte oneste per andare avanti: (a) accettare che il "ceiling" su BTC/ETH è un long risk-managed
(no alpha) e ottimizzare quello (vol-target per ridurre DD, non per battere il mercato); (b)
allargare l'universo dati CERTIFICATO (servono asset liquidi+puliti oltre BTC/ETH, che Deribit non
offre bene → valutare un secondo venue mainnet certificabile); (c) fonti di segnale ortogonali al
prezzo (on-chain, funding/basis multi-venue, opzioni multi-regime) — tutte richiedono nuovi dati
certificati prima di poterci credere.
@@ -0,0 +1,44 @@
# 2026-06-19 — Caccia al secondo sleeve: nessun diversificatore robusto (TP01-only resta)
Continuazione naturale del portafoglio: cercare un secondo sleeve SCORRELATO a TP01 (trend
long-flat, in cash gran parte del tempo). Criterio: non il Sharpe standalone ma il CONTRIBUTO al
portafoglio + robustezza. Tool: `scripts/portfolio/second_sleeve_hunt.py` (riusa le RV di trackE).
## Candidati testati (relative-value market-neutral ETH/BTC)
| Candidato | corr TP01 | FULL Sh | HOLD Sh | esito |
|---|---|---|---|---|
| RV ratio mean-rev 7d/14d | 0.09/0.05 | 1.36/1.03 | 0.62/0.76 | ☠️ morto (mean-rev dead, come sempre) |
| RV ratio_trend / xs_momentum 30d | +0.04 | **0.56** | **1.92** | ⚠️ sembrava promosso |
ratio_trend e xs_momentum danno risultati IDENTICI: su 2 asset "long il più forte / short il
debole" ≡ "trend del ratio ETH/BTC". È UN segnale (relative-momentum), non due.
## Il candidato "promosso" è regime-luck (per-anno + plateau lo smascherano)
Aggiunto a TP01 sembrava un trionfo: hold-out portafoglio 0.31 → 1.18 (w20%) / 1.51 (w30%),
corr +0.04. MA:
- **Hold-out (1.92) >> FULL (0.56)**: bandiera rossa (immagine speculare della trappola di Fase 3).
- **Per-anno NON robusto**: 2019 +22%, 2020 +7%, 2021 +21%, 2022 +13%, **2023 17%, 2024 19%**,
**2025 +62%**, 2026 +6%. Due anni consecutivi negativi; il "guadagno" è concentrato nel 2025
(ETH sottoperforma BTC in modo netto e sostenuto). FULL Sharpe mediocre 0.56, DD 41%.
- **Nessun plateau**: l'hold-out Sharpe oscilla 0.25→1.92 al variare di (N, hold) → picco
config+regime, non altopiano.
- Il beneficio FULL al portafoglio è solo **+0.09 Sharpe** (la legittima diversificazione di uno
sleeve scorrelato a Sharpe 0.56: √(1.30²+0.56²)≈1.42). Il resto del "miglioramento" è il 2025.
## Decisione: NON promosso — TP01-only resta il portafoglio deployato
La stessa disciplina che ha bocciato i falsi positivi in-sample (Fasi 1-3) e cross-asset (frattali)
deve bocciare questo falso positivo nel hold-out. Il relative-momentum BTC/ETH è un edge debole e
regime-dipendente (2 anni a 17/19%), il cui contributo robusto al portafoglio è marginale
(+0.09 FULL); il grosso del beneficio è la fortuna del 2025. Aggiungerlo significherebbe
scommettere sul ripetersi di quel regime.
**Lezione/criterio aggiornato per i futuri sleeve:** "migliora il hold-out" da solo NON basta (il
hold-out è UN regime). Un secondo sleeve va promosso solo se: causale, corr bassa, **positivo nella
maggioranza degli anni** (no 2 anni consecutivi rossi), **plateau** sui parametri, e migliora il
portafoglio su FULL E hold-out — non solo per via di un singolo anno fortunato.
## Stato
Portafoglio = **TP01-only** (difensivo, Sharpe FULL 1.30 / hold-out 0.31). `active_sleeves()`
invariato. `second_sleeve_hunt.py` resta come tool per valutare candidati futuri col criterio
corretto (contributo + breadth per-anno + plateau). Il relative-momentum BTC/ETH è in WATCHLIST,
non deployato.
@@ -0,0 +1,31 @@
# 2026-06-19 — Portafoglio di strategie estensibile (TP01 primo sleeve)
Creato un contenitore di portafoglio (`src/portfolio/`) con TP01 come unico sleeve attivo per ora,
progettato per aggiungerne altri (ognuno validato col gauntlet onesto).
## Design
- **Sleeve** = una strategia validata che produce una serie di rendimenti netti per-barra
(datetime-indexed, CAUSALE, netto fee). Opzionale `pos_fn` per le posizioni correnti (live).
- **StrategyPortfolio**: porta ogni sleeve su griglia GIORNALIERA comune (compounding intra-giorno
→ mixa TF diversi in modo coerente), combina per PESO rinormalizzato sui giorni comuni
(= equal-capital-by-weight ribilanciato di continuo). Metriche FULL + HOLD-OUT 2025-26 (bloccato)
+ per-anno + standalone per-sleeve, vs benchmark buy&hold 50/50.
- **Estensibilità**: aggiungere uno sleeve = una riga in `src/portfolio/sleeves.active_sleeves`
(dopo validazione: research_lab + hold-out + cross-asset + causality guard). Niente sleeve non validati.
## Stato attuale (1 sleeve = TP01, peso 100%)
`scripts/portfolio/run_portfolio.py`:
- **FULL** Sharpe 1.30 / ret +201% / DD 14.3% / ~€1.52/g su 2k (n=2655 giorni 2019-2026)
- **HOLD-OUT 2025-26** Sharpe 0.31 / +3.5% / DD 7.5% (buy&hold 50/50: Sharpe 0.32 / 39% / DD 59%)
- Per-anno positivo quasi ovunque (2022 2.1%, 2026-YTD 0.7%)
- Posizione corrente: **flat** (TP01 in cash nel regime attuale = difensivo)
## File
- `src/portfolio/{__init__,portfolio,sleeves}.py`, `scripts/portfolio/run_portfolio.py`,
`tests/test_portfolio.py` (6 test, passano). CLAUDE.md aggiornato.
## Prossimo
Il portafoglio è pronto per ospitare nuovi sleeve. Candidati naturali (da validare prima):
un secondo edge scorrelato a TP01 (TP01 è trend long-flat → serve qualcosa di diverso, es. una
strategia che lavori quando TP01 è flat). Finché non c'è un secondo edge che regge il gauntlet,
il portafoglio = TP01 difensivo. Quando arriverà, basta una riga in sleeves.py.
@@ -0,0 +1,43 @@
# 2026-06-19 — TP01: look-ahead ffill mixed-TF, ri-verifica e adozione bassa frequenza (>=12h)
Segnalazione utente/agente: un look-ahead **ffill MIXED-TIMEFRAME su barre open-labeled**
(`resample(label="left")`) gonfiava il 4h a Sharpe ~1.60; il risultato reale è ~1.1.
Conclusione: **NON scendere sotto le 12h** — costi e overfitting dominano.
## Cosa ho verificato (`scripts/analysis/tp01_lowfreq.py`)
Ricalcolo TP01 PULITO **per singolo TF** (barre discrete, posizione shiftata +1, NESSUN
ffill/combine mixed-TF), con un **guard di causalità esplicito** (ricalcolo `target_series` su
prefisso → `tgt[i]` invariato). Esito (fee 0.10% RT, hold-out 2025-26 bloccato):
| TF | leak | FULL Sh | FULL ret | HOLD Sh | HOLD ret | HOLD DD |
|---|---|---|---|---|---|---|
| 4h | **0** | 1.36 | +204% | 0.27 | +2.8% | 8.3% |
| 6h | **0** | 1.42 | +217% | 0.21 | +2.1% | 7.9% |
| 12h | **0** | 1.32 | +198% | 0.22 | +2.3% | 8.6% |
| **1d** | **0** | 1.30 | +201% | **0.31** | **+3.5%** | 7.5% |
| buy&hold 50/50 1d | — | 0.92 | +1671% | **0.32** | **39%** | 59% |
## Lettura
- **Il path single-TF che ho usato in verify/stress è LEAK-FREE** (guard=0 su ogni TF): il
gonfiaggio 1.60 stava nel path **mixed-TF ffill** (ensemble/combine, es. trackE), NON nel
portafoglio single-TF. Per questo il mio 4h era 1.36 (non 1.60).
- **La conclusione "≥12h" è comunque CORRETTA e la adotto**: il FULL Sharpe è PIATTO ~1.3 da 12h
a 4h → scendere sotto le 12h NON dà vantaggio reale, aggiunge solo costi/turnover e rischio
overfit/look-ahead (lo stress mostrava il margine hold-out del 4h fragile a lag/fee). **1d è il
migliore**: hold-out Sharpe 0.31 (il più alto), DD 7.5%, turnover/costi minimi, leak-free.
- Allinea anche col numero dell'agente: il "reale ~1.1" è del path mixed-TF corretto; il mio
single-TF pulito dà ~1.3 FULL. In ogni caso **edge difensivo modesto**, non alpha.
## Decisioni applicate
- **Canonica deploy → PORT LF1d** (era LF4h). `trend_portfolio.py`: docstring aggiornata + nota
look-ahead; aggiunti `resample_tf`/`resample_1d`, `resample_4h` marcato deprecato per il deploy.
- **Paper trader → 1d** (`paper_trend.py`: `resample_1d`, `build_bars`, etichette 1d; gira, 5 test ok).
- **CLAUDE.md**: TP01 ridescritta come DIFENSIVA, canonica ≥12h/1d, gotcha look-ahead documentato.
- **Gotcha riusabile:** mai ffill/combine MIXED-TIMEFRAME su timestamp open-labeled (`label="left"`):
la close del bar (nota solo a fine bar) verrebbe propagata indietro all'open-label → look-ahead.
Il calcolo per-singolo-TF a barre discrete (posizione +1) è sicuro; il guard prefix-recompute lo prova.
## Verdetto invariato
TP01 resta la prima strategia onesta del progetto: **difensiva** (taglia il DD ~6× vs buy&hold,
hold-out 2025-26 positivo su entrambi gli asset), modesta nel ritorno. Deploy a **1d**, forward-only
paper trader, prima di qualsiasi capitale reale.
@@ -0,0 +1,84 @@
# 2026-06-19 — Verifica TP01 (branch strategy-research-2026-06) col gauntlet onesto
Una ricerca PARALLELA (branch `strategy-research-2026-06`, AdrianoDev) dallo stesso baseline
v2.0.0 ha trovato TP01 come "unica vincitrice". La mia linea (Fasi 2-3) aveva bocciato il trend
sul hold-out 2025-26. Ho riprodotto TP01 VERBATIM (`scripts/analysis/verify_tp01.py`) e l'ho
passato al mio gauntlet. **TP01 REGGE — la mia conclusione precedente era incompleta.**
## TP01 = TSMOM 30/90/180g, **vol-target 20%**, leva cap 2x, **long-flat**, portafoglio 50/50 BTC+ETH (4h)
## Esiti del gauntlet
**(A) Multi-TF (4h cherry-picked?) — NO, plateau robusto:**
| TF | FULL Sharpe | HOLD-OUT Sharpe |
|---|---|---|
| 15m | 0.93 | 0.31 |
| 1h | 1.32 | +0.20 |
| **4h** | **1.36** | **+0.27** |
| 1d | 1.30 | +0.31 |
1h/4h/1d danno tutti FULL ~1.3 e hold-out positivo → non è un artefatto di un singolo TF (solo il 15m, fee-sensibile, fallisce).
**(C) HOLD-OUT 2025-26 (il test che ha ucciso il mio trend 1h) — TP01 PROTEGGE:**
| | Sharpe | ret | DD |
|---|---|---|---|
| **TP01 portfolio** | **+0.27** | **+2.8%** | **8.3%** |
| buy&hold 50/50 | 0.35 | **39.4%** | 59.8% |
**(D) Cross-asset nel hold-out — regge su ENTRAMBI** (BTC sleeve +2.9% Sh 0.24, ETH +2.4% Sh 0.24).
A differenza del "vincitore" frattale (+ETH/BTC), TP01 protegge coerentemente su BTC E ETH.
**(B) Per anno:** positiva quasi ogni anno 2019-2026 (eccezioni piccole: 2022 2.4%, 2026-YTD 0.9%),
DD annui 1-12%. Il claim "positiva ogni anno" è lievemente ottimistico ma sostanzialmente vero.
## Perché TP01 regge dove il MIO trend (Fase 3) è caduto
La differenza chiave è il **VOL-TARGETING** (che NON avevo combinato col trend): TP01 scala
l'esposizione ∝ 1/vol_realizzata → nel crollo 2025-26 la vol è esplosa e TP01 si è messo
quasi in cash, schivando il drawdown. Il mio MA-cross 1h aveva esposizione fissa ed è rimasto
long nel chop → frullato. Concorrono: TSMOM multi-orizzonte (più liscio del MA-cross), long-flat
(niente perdite short), diversificazione 50/50. **La mia "trend = regime-luck" era vera per il
trend NUDO; TP01 = trend + vol-target + portafoglio è un'altra cosa, e robusta.**
## Cosa È onestamente TP01 (no oversell)
- **Edge DIFENSIVO, non alpha**: FULL Sharpe 1.36 vs buy&hold 0.92 — MA CAGR +16.6% vs +48.1%.
Su tutto il toro il buy&hold ha reso ~8x di più. Il valore di TP01 è il **DD** (13.8% vs 77.5%
full; 8% vs 60% nel hold-out) e la **protezione dai crash**.
- Nel hold-out 2025-26 ha fatto solo +2.8% (Sharpe 0.27, basso): ha **protetto, non profittato**.
- Un solo regime di hold-out, ma il vol-targeting è meccanico (high vol → low expo) → generalizza
per costruzione meglio di un timing fittato.
- Config canonica (30/90/180, vol20%, lev2x) non iper-tunata; 4h non cherry-picked (plateau).
## VERDETTO
**TP01 è la PRIMA strategia onesta e robusta del progetto post-reset.** Supera il mio gauntlet
(hold-out positivo su entrambi gli asset, plateau multi-TF, causale, fee-aware). È modesta e
difensiva (Sharpe ~1.3, soffitto strutturale dichiarato corretto), ma è reale: migliora il
rischio/rendimento del buy&hold tagliando i drawdown e proteggendo nei crash. La ricerca parallela
ha fatto centro proprio sul pezzo che la mia linea non aveva combinato (vol-target sul trend).
**Raccomandazione:** integrare il branch su main (modulo `trend_portfolio.py` + paper trader),
trattare TP01 come baseline operativa difensiva. Aspettative oneste verso il target €50/g: a
Sharpe 1.3 / CAGR 16.6% servono molto capitale o leva (con più DD) — TP01 è un fondamento solido,
non una scorciatoia.
## STRESS-TEST (`scripts/analysis/stress_tp01.py`, integrato e rieseguito sul modulo vero)
| Dimensione | Esito |
|---|---|
| **Sweep fee** | FULL robusto fino a **0.40% RT** (Sh 1.44→1.36→1.28→1.13). HOLD-OUT SOTTILE: +2.8%/Sh0.27 a 0.10% → ~flat (Sh 0.03) a 0.40% |
| **Lag/slippage** | FULL robusto (1.29-1.43). HOLD-OUT si erode: lag1(4h)→Sh0.12, lag2→−0.02, lag1+fee0.20%→0.04 |
| **Plateau parametri** | OTTIMO — target_vol/leva/orizzonti/vol_win tutti reggono o migliorano (orizzonti 20/60/120 → Sh 1.61). **NON un picco cherry-picked** |
| **Deflated-Sharpe** | DSR **0.999** a N=10/40/100 trial → il Sharpe FULL non è artefatto di multiple-testing |
**Verdetto stress (onesto):**
- **Robustezza FULL-period: FORTE.** TP01 supera fee 0.40%, lag, ampio plateau di parametri, e
deflated-Sharpe. NON è overfit né cherry-picked — la proprietà robusta è il **taglio del
drawdown** (13.8% vs 77.5% full; 8% vs 60% hold-out), invariante a tutto lo stress.
- **Edge di RITORNO nel hold-out: REALE ma SOTTILE e sensibile alla frizione.** Nel 2025-26 ha
schivato il crash in modo affidabile (DD 8% vs 60%) ma ha **protetto più che profittato** (+2.8%,
Sh 0.27), e quel sottile positivo si assottiglia a zero sotto fee2x o lag 2 barre.
**Conclusione:** la proprietà **deployabile e robusta di TP01 è la PROTEZIONE del drawdown**, non
la generazione di alpha. È una strategia difensiva genuina (prima del progetto a superare gauntlet
+ stress), ma a basso ritorno: il valore è "Sharpe ~1.3 con DD ~6× più piccolo del buy&hold",
non "battere il mercato". Per il capitale reale: il vol-targeting + long-flat sono meccanici e
generalizzano; il rischio residuo è la frizione di esecuzione sul filo del sottile edge di ritorno
nei regimi avversi → da monitorare col paper trader forward-only prima di scalare.
+28
View File
@@ -0,0 +1,28 @@
# 2026-06-19 — Strato trend multi-asset sui 52 alt: RIDONDANTE col trend di TP01
Tentativo: aggiungere un terzo sleeve = TSMOM (stessa logica TP01 CANONICAL, long-flat vol-target)
applicato a OGNI alt dei 52 Hyperliquid certificati, equal-weight ragged. Idea: trend più
diversificato che diversifichi TP01 (BTC/ETH). `scripts/portfolio/trend_multiasset.py`.
## Esito: ridondante e peggiore
- **TREND-52 standalone**: FULL Sh 0.66, **HOLD-OUT 1.03** (negativo), anni+ 33%. Gli alt sono
stati long nel calo 2025-26 e hanno sanguinato — a differenza di TP01 (BTC/ETH) che il
vol-target+trend portò in cash. I trend degli alt sono più rumorosi/whippy.
- **corr a TP01 = +0.74** (stessa beta direzionale, come previsto) | corr a XS01 0.05.
- **Contributo al portafoglio (TP01 70 + XS 30):** +TREND-52 w20% → FULL 0.01, **HOLD 0.16**;
w30% → FULL 0.02, **HOLD 0.27**. PEGGIORA.
## Lezione
Broadenizzare il TREND su molti alt NON diversifica: è la **stessa direzionalità** (corr 0.74 con
TP01) su asset più rumorosi → aggiunge perdita/rumore, non edge. La dimensione trend è già catturata
in modo pulito da TP01 (BTC/ETH, vol-targeted). L'unica espansione che diversifica davvero resta
quella **market-neutral** (XS01 cross-sectional), perché è ortogonale alla beta direzionale.
## Conclusione (chiusura del filone "espansione universo")
Esplorate tutte le vie di espansione sui certificati Hyperliquid:
1. XS su 52-all → diluito (memecoin), negativo.
2. XS top-liquidità dinamico → peggiore del fisso-19 (liquidità ≠ qualità).
3. Trend multi-asset su 52 → ridondante (corr 0.74) + hold-out negativo.
Nessuna migliora il portafoglio. **Configurazione validata e invariata: TP01 70% + XS01 (19 major)
30% — FULL Sh 1.41 / HOLD 1.15.** I margini reali per crescere NON sono nell'universo crypto-
direzionale (saturo), ma in un MECCANISMO diverso (opzioni VRP, in attesa di dati di stress reali).
+35
View File
@@ -0,0 +1,35 @@
# 2026-06-19 — Affinamento XS01: blend di lookback [30,90]
Come TP01 fonde gli orizzonti 30/90/180, XS01 ora fonde piu' lookback del momentum cross-sectional
(z-score cross-sectional per lookback, mediato) invece del singolo L=30. `scripts/portfolio/xsec_blend.py`.
## Sweep lookback (19 major, 899g) — FULL/OOS/DD/anni+/corrTP
| lookbacks | FULL | OOS25 | DD% | anni+ | corrTP |
|---|---|---|---|---|---|
| [30] (prima) | 0.80 | 1.20 | 21 | 100% | 0.06 |
| [90] | 0.88 | 0.90 | 17 | 100% | 0.05 |
| **[30,90]** | **1.10** | **1.03** | **14** | **100%** | **0.12** |
| [20,40,90] | 0.51 | 0.67 | 25 | 100% | 0.12 |
| [30,60,120] | 0.68 | 0.74 | 16 | 100% | 0.13 |
**[30,90] e' il sweet spot**: fonde i DUE singoli robusti (30 e 90), FULL Sh 0.80→1.10, DD 21→14%,
corr a TP01 0.06→−0.12 (diversifica meglio), 100% anni+. Non e' un cell fortunato: e' la
combinazione dei due lookback gia' validati (anti-overfit, come il multi-orizzonte di TP01).
## Effetto sul portafoglio (TP01 70% + XS01 30%)
| | XS01 [30] | XS01 blend [30,90] |
|---|---|---|
| XS01 standalone FULL / DD | 0.80 / 21% | **1.10 / 14%** |
| Portafoglio FULL Sharpe | 1.41 | **1.48** |
| Portafoglio HOLD-OUT Sharpe | 1.15 | 1.06 |
| Portafoglio DD | 5.2% | **4.6%** |
| ~€/giorno (2k) | +1.65 | +1.78 |
Migliora FULL Sharpe + DD + robustezza (due orizzonti) al costo di un hold-out marginalmente piu'
basso (0.09, dentro il rumore di una singola finestra). Giudizio: il blend e' piu' robusto
(meno dipendente da un singolo lookback) e diversifica meglio -> PROMOSSO.
## Azione
`src/portfolio/sleeves.XS_CFG`: `L=30` -> `lookbacks=(30,90)`; engine `_xsec_returns` usa lo score
blended (media z-score cross-sectional per lookback). **Portafoglio attivo: TP01 70% + XS01 blend
30%, FULL Sh 1.48 / HOLD 1.06 / DD 4.6%.** 12 test ok. Sleeve sempre sui 19 major.
+44
View File
@@ -0,0 +1,44 @@
# 2026-06-19 — Affinamento XS01: gate di dispersione (p30)
Il momentum cross-sectional vive nella DISPERSIONE (winners/losers distanti). In regime compatto
(tutti gli asset insieme) e' rumore. Gate: entra solo se la dispersione cross-section del momentum
supera il percentile ESPANDENTE causale `disp_pct`; altrimenti flat. Sul blend [30,90] dei 19 major.
`scripts/portfolio/xsec_dispgate.py`. (È il concetto del vecchio XS01 pre-reset, disp_min=p50.)
## Sweep soglia (19 major, 899g) — XS01 standalone + contributo portafoglio
| soglia | XS FULL | XS OOS | PORT FULL | PORT HOLD | %flat |
|---|---|---|---|---|---|
| no gate | 1.10 | 1.03 | 1.50 | 1.06 | 0% |
| p15 | 1.32 | 1.39 | 1.64 | 1.36 | 28% |
| p20 | 1.46 | 1.63 | 1.72 | 1.52 | 31% |
| p25 | 1.46 | 1.63 | 1.72 | 1.52 | 31% |
| **p30** | **1.50** | **1.71** | **1.74** | **1.56** | 35% |
| p35 | 1.60 | 1.90 | 1.81 | 1.69 | 37% |
| p40-p50 | 1.0 | 0.8 | 1.36-1.38 | 0.77-0.93 | 42-49% |
**PLATEAU robusto p15-p35** (cinque punti, tutti molto > no-gate); il crollo a p40+ e' OVER-gating
(salta troppo). Scelto **p30** (centro sicuro del plateau, lontano dal cliff p40). Non un knife-edge.
## Effetto sul portafoglio (TP01 70% + XS01 30%)
| XS01 | PORT FULL | PORT HOLD | PORT DD |
|---|---|---|---|
| [30] originale | 1.41 | 1.15 | 5.2% |
| + blend [30,90] | 1.48 | 1.06 | 4.6% |
| + dispersion gate p30 | **1.55** | **1.55** | **4.4%** |
XS01 standalone: FULL 1.10→1.50, HOLD 1.03→1.71, DD 14%→10.8%, ~€/g 1.64→2.36. Il gate alza SIA
FULL SIA hold-out (a differenza del solo blend, che barattava un po' di hold-out).
## Meccanismo + caveat onesti
- **Causale**: soglia = percentile espandente della dispersione PASSATA; nessun look-ahead.
- **Perche' funziona**: tiene XS attivo nei regimi DISPERSI (2025-26, dove gli alt divergono) e flat
nei bull compatti (2024). L'hold-out 2025-26 e' ad alta dispersione -> il gate concentra
l'attivita' di XS proprio li' -> hold-out forte. E' il comportamento voluto, ma NB che il salto
del hold-out riflette anche che il 2025-26 e' stato un regime ad alta dispersione.
- Caveat XS01 invariati: storia ~2.5 anni; STAT-MODE (book 19 gambe non eseguibile a 2k).
## Azione
`src/portfolio/sleeves.XS_CFG`: aggiunto `disp_pct=30`; engine `_xsec_returns` gatea su dispersione.
**Portafoglio attivo: TP01 70% + XS01 (blend [30,90] + gate disp p30) 30% — FULL Sh 1.55 / HOLD 1.55
/ DD 4.4%.** 12 test ok. Affinamenti del SEGNALE (blend + gate) hanno funzionato dove l'espansione
universo no: i margini su XS sono nella struttura del segnale, non nel numero di asset.
@@ -0,0 +1,62 @@
# 2026-06-19 — Espandere l'universo XS01: PIÙ asset DILUISCONO (i 19 major sono il sweet spot)
Richiesta: aggiungere altri asset Hyperliquid certificati per rafforzare XS01 (cross-sectional
momentum). Fatto il lavoro, esito ONESTO: **non rafforza — diluisce.**
## Cosa ho fatto
- Esteso `fetch_hyperliquid.py` a ~54 candidati alt maggiori (mappa Binance auto SYM/USDT, k-prefissi
esclusi). **52 certificati** (cross-venue 4-11 bps vs Binance, flat 0%, storia 2024+): aggiunti
ATOM DYDX APE CRV LDO STX GMX SNX BCH COMP WLD UNI TRX FIL RUNE ENA ORDI JUP WIF PYTH FET AR ETC
ALGO GALA SAND AXS DOT BLUR JTO PENDLE ONDO TAO. Esclusi MKR (delistato HL 2025-09) e FXS
(migrazione Frax 2026-01) via nuovo gate "ultima barra recente".
## Il finding: il cross-section dei 52 è NEGATIVO; i 19 major sono positivi
Stessa finestra (2024-04 → 2026-06, 807g), mom L*/H10:
| Universo | k | FULL Sharpe (L30/L60/L90) |
|---|---|---|
| **52 asset** | 5 | 0.13 / 0.21 / 0.35 |
| **52 asset** | 8-12 | tutti negativi (k grande non aiuta) |
| **19 major** | 5 | +0.30 / +0.36 / **+0.67** (OOS 0.91) |
I ~33 small/new-cap aggiunti (WIF, JUP, ORDI, PYTH, TAO, GALA, AR, BLUR…) sono idiosincratici/
mean-reverting: il loro rumore **rovescia** il momentum relativo. Cross-sectional momentum su crypto
funziona fra i MAJOR liquidi, non sul long tail. Allargare l'universo NON è gratis.
## Azione
- **XS01 resta sui 19 major** (sweet spot già validato: plateau/fee/subset). Lo sleeve
`_xsec_returns` ora usa una **lista esplicita `XS_UNIVERSE` (19)**, non più glob-all (così
aggiungere parquet certificati non lo cambia/rompe — avevo inavvertitamente fatto vedere allo
sleeve 52 asset = negativo).
- I 52 parquet certificati restano su disco: dato valido per ricerca futura (uno strato diverso —
es. trend-following multi-asset, o un XS ristretto ai top-liquidità — potrebbe usarli), ma NON XS01.
- Portafoglio invariato e ripristinato: **TP01 70% + XS01 30%, FULL Sh 1.41 / HOLD 1.15.**
## Lezione
"Più asset = più robusto" è FALSO per il cross-sectional momentum: il long tail di alt piccoli
diluisce/inverte l'edge. La breadth utile è quella dei major liquidi (corr-strutturata), non il
numero grezzo.
## Tentativo 2: UNIVERSO TOP-LIQUIDITÀ DINAMICO (`xsec_dynuniverse.py`) — anch'esso PEGGIORE
Provato a selezionare a ogni ribilancio i top-N per dollar-volume 30g (causale) dai 52, poi XS
momentum fra quelli (adattivo, ragged-aware). Esito:
| Universo | FULL Sh | OOS25 | anni+ |
|---|---|---|---|
| top12 dinamico (L30H10k5) | 0.65 | 0.54 | 67% (2026 4%) |
| top15/20/25 dinamico | 0.14-0.38 | ≤0.30 | 33-67% |
| **fisso-19 major (L30H10k5)** | **0.80** | **1.20** | **100%** |
| fisso-19 major (L90H10k5) | 0.88 | 0.90 | 100% |
Contributo: TP01+DYN 70/30 = FULL 1.10 / HOLD 0.60 vs **TP01+XS19 = FULL 1.25 / HOLD 1.15**.
**Perché fallisce:** la classifica per dollar-volume ammette comunque i MEMECOIN ad alto volume
(WIF, ORDI, JUP, PEPE...) che hanno volumi enormi ma momentum erratico/mean-reverting →
diluiscono. **Liquidità ≠ qualità** nelle crypto. I 19 major *curati* (established, corr-strutturati,
non solo alto volume) restano il sweet spot.
## Conclusione
Né più nomi (52) né top-liquidità dinamico migliorano XS01. **XS01 resta sui 19 major curati**
(FULL 0.80 / OOS 1.20, 100% anni+). Portafoglio invariato: TP01 70% + XS01 30% (FULL 1.41/HOLD 1.15).
Per rafforzarlo davvero servirebbe una curatela di QUALITÀ (established majors), che è già ciò che i
19 sono. Coerente con la disciplina: nessuna espansione senza che migliori il gauntlet. I 52 parquet
certificati restano per ricerca futura (es. trend multi-asset, dove il long tail non diluisce).
@@ -0,0 +1,167 @@
# Sweep "strategie alternative su Deribit" — 104 ipotesi, 153 agenti (2026-06-20)
## Cosa
Ondata di ricerca onesta richiesta esplicitamente con >=100 agenti: **studiare strategie di
trading ALTERNATIVE** a TP01/XS01/VRP01 sull'universo certificato Deribit (**BTC/ETH** OHLCV +
**DVOL**). Catalogo di **104 ipotesi distinte** su 11 famiglie, **un agente-finder per ipotesi**,
poi **verifica avversariale a 3 scettici** per ogni finding promettente, poi sintesi. Totale
**153 agenti**, ~5.86M token, ~2h (workflow `scripts/research/alt/wf_altstrat.js`,
run `wf_0f3659fc-809`).
Famiglie: BRK (breakout/canali), TRD (trend non-TSMOM), MRV (mean-reversion gated), VOL (DVOL +
vol realizzata, Deribit-specific), XAS (cross-asset BTC/ETH: ratio/lead-lag/cointegrazione/RS),
SEA (stagionalità/ora-del-giorno), RSK (overlay difensivi), OPT (strutture opzioni modellate su
DVOL), MIC (microstruttura/candele), STA (ML walk-forward), CMB (combinazioni/filtri).
## Harness condiviso (nuovo, validato)
`scripts/research/alt/altlib.py` — libreria di valutazione ONESTA e **vettoriale** usata da tutti
gli agenti, così il no-look-ahead è strutturalmente impossibile:
- `eval_weights(df, target)`: posizione decisa con dati `<= close[i]`, **tenuta durante la barra
i+1** (lo shift lo fa la libreria), fee su turnover, **fee-sweep** 0.000.30% RT incorporato.
- `study_weights/study_signals`: ogni ipotesi girata su **entrambi gli asset** + **HOLD-OUT 2025+**
+ per-anno, con verdetto conservativo PASS/WEAK/FAIL (richiede min-asset full>=0.5 **e** hold>=0.2
**e** sopravvivenza fee).
- DVOL allineato **causalmente** (`merge_asof` backward), storia dal 2021-03.
- **Calibrazione:** la replica TSMOM riproduce i numeri noti leak-free di TP01 (BTC full 1.12 /
hold 0.31, DD 77%→23%); buy&hold correttamente FALLISCE l'hold-out (full 0.79, hold 0.37).
104 script riproducibili in `scripts/research/alt/runs/`.
## Esito — NIENTE di nuovo batte o diversifica lo stack esistente
Su 104 ipotesi: **16 promettenti**, **1 sola sopravvissuta** alla verifica avversariale (STA05),
e anch'essa **ridondante/non deployabile**. È il risultato pulito e atteso per un progetto al suo
**soffitto strutturale BTC/ETH-direzionale ~1.3** (già documentato). Lo stack
**TP01 (55%) + XS01 (25%) + VRP01 (20%) resta imbattuto** da questa ondata.
Il segnale ricorrente: decine di trend-follower prendono **FULL Sharpe alto (~1.01.3)** ma
**HOLD-OUT 2025 negativo** (Supertrend, ADX-EMA, Heikin-Ashi, Turtle, SMA200-regime,
Donchian+Chandelier, Kalman, OBV, body-ratio, ...): è **trend-beta del toro**, non alpha, e si
rompe nell'hold-out. I PASS apparenti erano quasi tutti **(a)** singola cella fortunata
sull'hold-out, oppure **(b)** TP01/TSMOM con un overlay attaccato sopra.
### L'unico sopravvissuto: STA05 — EWMA-cross ensemble vote (LEAD, non sleeve)
Voto d'insieme su 13 coppie EMA (fast {5,10,20,40} × slow {40,80,120,200}, fast<slow),
posizione = voto medio firmato, vol-target 20%/cap 2x, 1d. Verifica: **leak-free** (perturbazione
barre future = 0), **plateau** di parametri, **non** fortuna di un singolo anno (jackknife
drop-one-year 0.550.96), sopravvive fee a 0.30% RT. Ho rieseguito il **blend test** raccomandato
(50/50 BTC+ETH, mia stessa griglia di TP01, fee 0.10% RT):
| variante | FULL Sh | DD | HOLD Sh | corr→TP01 (full/hold) |
|---|---|---|---|---|
| TP01 (canonico, controllo) | **+1.30** | 14.3% | +0.31 | — |
| STA05 long-only | +1.24 | 16.3% | +0.21 | **0.93 / 0.94** → ridondante |
| STA05 **long-short** | +0.87 | 28.6% | **+0.86** | **0.71 / 0.53** |
Blend TP01+STA05_LS: `0.75·TP01 + 0.25·LS`**FULL 1.24, HOLD 0.31→0.59, DD 16.1%**;
`0.50/0.50` → FULL 1.13, **HOLD 0.75**, DD 18.8%.
**Lettura onesta (più precisa della sintesi del workflow, che lo aveva liquidato come "dominato
su ogni asse"):** la versione **long-only** è ridondante con TP01 (corr 0.94). La versione
**long-short** invece è solo moderatamente correlata (**0.53 nell'hold-out**) e **migliora
davvero l'hold-out del blend** (0.31→0.59 a peso 25%), al costo di un po' di FULL Sharpe
(1.30→1.24) e DD (14%→16%). MA: l'hold-out è **solo 536 giorni** (include lo stub 2026 corto) →
classica trappola "bello OOS ma OOS breve", e standalone ha DD 28.6%. **Verdetto: LEAD da
monitorare forward, NON deploy, NON sleeve confermato.** Da rivalutare quando l'hold-out cresce.
## Famiglie confermate MORTE / ridondanti (negativi onesti)
- **BRK** breakout (Donchian/Keltner/Bollinger/ORB/NR7/inside-bar): ogni variante rompe l'hold-out
BTC; l'unico PASS (BRK04) è cella singola overfit con maxDD 63%.
- **TRD** trend non-TSMOM: tutto trend-beta del toro ridondante con TP01; i 4 PASS (TRD02/07/08/10)
sono fortuna di singola cella sull'hold-out, dominati dal TSMOM.
- **MRV** mean-reversion: la crypto **tende, non torna**; molti negativi anche a fee zero, **0 PASS**
→ conferma su dati certi la lezione v2.0.0 ("il fade è artefatto").
- **VOL** gate/overlay DVOL su TSMOM: ogni overlay (VOL03/04/08/09/11) è **peso morto netto-negativo**;
la parte robusta è sempre TP01 nudo, la componente DVOL/EWMA aggiunge anti-valore.
- **XAS** spread BTC/ETH (ratio/lead-lag/cointegrazione/RS/dual-mom): gli spread **tendono non
revertono** (negativi a fee zero); le "rotazioni" PASS (XAS03/04/09) sono TP01 travestito con
selezione fortunata sull'hold-out.
- **SEA** stagionalità: fee-killed a 1h, artefatti di regime a 1d, nessun hold-out cross-asset.
- **RSK** overlay di rischio (circuit breaker/kill-switch/DD-scaling/inverse-vol RP): o seguono il
prezzo (buy&hold travestito) o aggiungono frizione senza proteggere dove serve.
- **MIC** micro-pattern candele: hold-out crolla cross-asset; l'unico "survivor" MIC05 è l'artefatto
di **un singolo evento** (short del crash 2026-01-29 su ~13 trade).
- **STA** ML su feature di prezzo (Ridge/Logistic/RF/Kalman/SGD/AR1/k-means): nessun potere
predittivo OOS; l'unico PASS (STA05) è l'ensemble di trend = TP01.
- **CMB** combinazioni: ogni combo è TP01 più un filtro che distrugge valore.
- **OPT** strutture opzioni (modellate su DVOL ATM, niente skew): code severe (ETH maxDD 96% su
iron condor), **lead-only** al meglio → conferma la regola VRP01 "niente short-vol da modello in
deploy". Numeri tipo OPT02/OPT04 hold-out 2.4/1.96 sono artefatto del premio modellato + asset
asimmetrico (ETH fallisce) → giustamente NON promettenti.
## Lezioni metodologiche (azionabili)
1. **L'harness deve premiare lo Sharpe MARGINALE vs un baseline TP01, non lo Sharpe ASSOLUTO.**
`study_weights` valuta lo Sharpe assoluto: così ogni overlay-su-TSMOM **eredita** lo Sharpe di
trend di TP01 e prende un PASS fasullo (VOL03/04/08/09/11, CMB04/06). Per la prossima ondata:
valutare il **contributo incrementale** rispetto a TP01 nudo, così gli overlay non possono
ereditare un PASS.
2. **Prima di gradare PASS, esigere (a) un PLATEAU di parametri (non una cella isolata) e (b) un
jackknife drop-one-month / drop-best-day sull'hold-out.** Questi due check da soli hanno ucciso
**13 dei 14** falsi positivi in verifica avversariale.
3. La verifica avversariale a 3 scettici con angoli diversi (leak / overfit-robustezza /
plausibilità-economica-vs-TP01) ha funzionato: ha distinto i 15 falsi positivi dall'1 robusto.
## Raccomandazione
**Non aggiungere nulla di questa ondata al portafoglio live.** Lo spazio
**BTC/ETH-direzionale single-asset è esaurito**: ogni PASS era hold-out-fitting o un overlay su TP01.
Redirigere il budget di ricerca verso **meccanismi davvero diversi** dove il soffitto non morde:
espandere/monitorare forward **XS01** (cross-sectional sui 51 alt Hyperliquid certificati — l'unico
che abbia mai battuto il soffitto) e **VRP01 reale** (quando cerbero-bite cattura skew live + uno
stress). Tenere **STA05_LS** in lista LEAD per il forward-monitor dell'hold-out.
Artefatti: `scripts/research/alt/altlib.py`, `scripts/research/alt/runs/*.py` (104),
`scripts/research/alt/wf_altstrat.js`, verifica blend `/tmp/verify_sta05.py`.
## Follow-up — MARGINAL SCORER implementato (non più solo raccomandazione)
La lezione #1 ("valutare lo Sharpe MARGINALE vs baseline TP01, non assoluto") è ora **codice**
in `altlib.py`:
- `tp01_baseline_daily()` — TP01 CANONICAL 50/50 BTC+ETH, rendimenti netti giornalieri (cache).
Riproduce il canonico (full 1.30 / hold 0.31) — bloccato da test.
- `marginal_vs_tp01(cand_daily)` — corr a TP01 (full/hold), **uplift del blend** (Sharpe di
TP01+w·cand meno TP01, full & hold-out, w∈{0.25,0.5}), **beta a TP01 + alpha residua** (parte
ortogonale al trend), e un **verdetto**: ADDS / REDUNDANT / DILUTES / NEUTRAL.
- `study_marginal(name, target_fn)` — valuta un candidato **sia** in assoluto (`study_weights`)
**sia** marginale; `earns_slot = (abs_grade != FAIL) AND (marginal_verdict == ADDS)`.
- Convenzione pulita `target_fn(df, asset)` (via `_call_target`) per le strategie DVOL/cross-asset
— niente più inferenza-asset hacky (il VOL03 dell'agente la sbagliava, usava DVOL BTC anche per ETH).
- Demo riproducibile `scripts/research/alt/marginal_demo.py` + test `tests/test_marginal_scorer.py`.
**Dimostrazione (la prova che il fix discrimina):**
| candidato | assoluto | marginale | earns_slot |
|---|---|---|---|
| TP01-itself (sanity) | WEAK | REDUNDANT (corr 1.0, uplift 0) | False |
| **STA05 long-short** (il lead) | PASS | **ADDS** (corr-hold 0.53, blend-hold +0.29) | **True** |
| STA05 long-only | WEAK | REDUNDANT (corr 0.93/0.94) | False |
| VOL03 DVOL-gated TSMOM (overlay) | WEAK | NEUTRAL (corr 0.93, uplift triviale) | False |
| **CMB04 momentum+low-vol (overlay)** | **PASS** | **NEUTRAL** (corr 0.94) | False |
Il punto chiave è l'ultima riga: **CMB04 prendeva un PASS assoluto col vecchio harness, ma il
marginal scorer lo declassa correttamente** — il suo "Sharpe 1.0" è trend di TP01 ereditato al 94%,
non alpha nuovo. Regola operativa d'ora in poi: una nuova strategia direzionale BTC/ETH si giudica su
`study_marginal` (earns_slot), non sullo Sharpe assoluto.
## "Resta qualche candidato?" — gate marginale + jackknife su TUTTI i contendenti forti
Passati i 7 promettenti più forti non-ancora-marginal-testati (`marginal_remaining.py`):
Vortex/Hull (FAIL nella ricostruzione pulita), VOL11 kill-switch (corr 0.94 → REDUNDANT), XAS03/09
rotazioni (NEUTRAL, anzi RS-rotation **diluisce** l'hold-out 0.20), **TRD07 KAMA** e **VOL08**
(entrambi marginale=ADDS). Ma il marginal-point-estimate **può essere ingannato da un singolo mese**:
ho aggiunto al gate il **jackknife OOS** (`robust_oos` = uplift positivo nell'anno OOS pulito 2025
**e** sopravvive al drop-best-month). Risultato:
| candidato | clean-2025 uplift | drop-best-month | robust_oos | earns_slot |
|---|---|---|---|---|
| TRD07 KAMA | +0.089 | **0.034** | False | **False** (era ADDS!) |
| VOL08 RV-term | +0.158 | +0.034 | True | **True** |
| STA05 long-short | +0.039 | +0.131 | True | True (ma 2025 ~0, il grosso è lo stub 2026) |
**KAMA è il falso-positivo istruttivo:** ingannava il marginal scorer (uplift +0.056) ma muore al
jackknife (0.034 togliendo il mese migliore) → il gate rinforzato (`earns_slot` ora esige
`robust_oos`) lo uccide correttamente. Codificata così la lezione #2 in `marginal_vs_tp01`.
### Verdetto finale: NESSUN candidato deployabile
Dopo il gate più severo (abs≠FAIL + marginale=ADDS + jackknife OOS), i 104 collassano a **2 LEAD
fragili**: **VOL08** (overlay term-structure di vol realizzata) e **STA05_LS** (ensemble EMA
long-short). Entrambi sono **famiglia-trend su BTC/ETH** (non un meccanismo nuovo), moderatamente
correlati a TP01 (0.530.61 hold-out), con uplift piccolo e concentrato su un OOS di ~1.5 anni →
**forward-monitor, NON sleeve.** E sono correlati tra loro (entrambi trend) → di fatto **un solo
tema**: "una costruzione di trend-timing alternativa, modestamente decorrelata a TP01 nel 2025-26".
La diversificazione vera resta fuori dallo spazio direzionale single-asset (→ XS01 / opzioni reali).
@@ -0,0 +1,86 @@
# 2026-06-20 — Correzione estrazione cerbero MCP: il backfill sintetico (vol=0) ingannava la certificazione
## Contesto
Richiesta: "analizza cerbero MCP correggendo l'estrazione dati storici secondo le analisi fatte".
Le analisi del progetto avevano già fissato un principio — *"storia nativa Hyperliquid solo dal 2024,
pre-2024 = backfill, volume 0"* — e `fetch_hyperliquid.py` lo gestiva con un floor `START=2024-01-01`.
**Il floor non basta.**
## Il difetto
`fetch_hl` chiedeva a cerbero MCP `get_historical` dal 2024-01-01 e certificava ogni asset con tre
gate: **flat-bar** (O==H==L==C), **cross-venue** (mediana |close Binance| < 60 bps), **recency**.
Nessuno guardava il **volume**. Risultato: gli asset listati su HL *dopo* lo START passavano come
PULITO pur essendo in gran parte **backfill sintetico**.
Ispezione del volume sui parquet (leading run di barre a volume 0):
| asset | barre | leading vol=0 | primo trade reale | % sintetico |
|---|---|---|---|---|
| **AXS** | 902 | **748** | 2026-01-18 | **82.9%** |
| ALGO | 902 | 338 | 2024-12-04 | 37.5% |
| SAND | 902 | 338 | 2024-12-04 | 37.5% |
| AR | 902 | 58 | 2024-02-28 | 6.4% |
| ETC | 902 | 11 | 2024-01-12 | 1.2% |
| BTC/ETH + 19 major | 902 | 0 | 2024-01-01 | 0% |
AXS era **certificato PULITO** (flat 0%, cross-venue 9.5 bps) pur avendo solo ~5 mesi di trading reale.
## Verifica diretta su cerbero MCP (token mainnet)
Interrogato l'endpoint `cerbero-mcp.tielogic.xyz/mcp/tools/get_historical` (bot-tag
`pythagoras-mainnet`):
- **BTC**: 902 barre, leading vol=0 = 0, volume reale dal 2024-01-01 (V=699, 2437, 5306…). Nativo. ✓
- **AXS**: 902 barre, **748 leading vol=0**, primo vol>0 = 2026-01-18. Le barre a volume 0 hanno
prezzi (O/H/L/C) che **coincidono con Binance**:
| data | cerbero close | binance close | Δ |
|---|---|---|---|
| 2024-01-01 | 9.262 | 9.26 | 2.2 bps |
| 2024-01-02 | 8.949 | 8.94 | 10.1 bps |
| 2024-01-03 | 7.937 | 7.95 | 16.4 bps |
**Diagnosi provata:** cerbero MCP riempie il periodo pre-quotazione con barre **sintetiche — volume 0,
prezzi copiati da un venue di riferimento (Binance)**. Per questo i vecchi gate venivano ingannati:
- cross-venue passa → i prezzi *sono* Binance (Δ 116 bps);
- flat passa → le barre non sono flat (hanno movimento di prezzo);
- ma **volume 0** → su HL quelle candele **non erano negoziabili**. È esattamente il caso v2.0.0
(edge su un book che non c'era).
## Correzione (`scripts/analysis/fetch_hyperliquid.py`)
1. **Il VOLUME è il rivelatore del backfill**`trim_backfill()` taglia il run iniziale di barre a
volume 0; si tiene solo la **serie nativa**.
2. **Gate storia nativa** `MIN_NATIVE_DAYS=365`: dopo il taglio serve ≥ 1 anno di vita reale →
scarta chi è troppo corto (AXS, 154 barre reali → fuori).
3. **Gate vol=0 interno** `INTERIOR_VOL0_MAX=5%`: gap di liquidità oltre il taglio iniziale.
4. **cross-venue/flat ricalcolati SOLO sulle barre reali** (non più sui sintetici).
5. **I parquet degli asset scartati vengono rimossi** (disco == set certificato; niente file
contaminati a riposo).
## Risultato
- Universo certificato: **52 → 51** (AXS scartato).
- ALGO/SAND (338 barre), AR (58), ETC (11) ripuliti dal backfill → ora start reale corretto.
- **I 19 major di XS01 hanno 0 backfill → invariati**: la strategia live (`XS_UNIVERSE` esplicito) NON
è toccata. Verificato: portafoglio 3-way (TP01+XS01+VRP01) gira identico, FULL Sh 1.68 / HOLD 1.67.
- Re-fetch end-to-end su cerbero reale: 51 PULITO, sweep su tutti i file → 0 backfill residuo.
## Nota su una conclusione precedente
Il diario `2026-06-19-xsec-universe-expansion.md` concludeva "cross-section dei 52 = negativo". Quella
finestra includeva i sintetici (AXS 83%, ALGO/SAND 37% di barre vol=0 con ritorni non eseguibili): la
magnitudine del risultato era **in parte un artefatto**. La conclusione qualitativa (il long-tail
diluisce XS01; i 19 major sono il sweet spot) resta valida, ma il numero netto è 51 e il test andrebbe
ri-girato sui dati puliti se si volesse riusare quell'universo.
## Lezione
`flat` + cross-venue **non bastano** a certificare un feed che fa backfill copiando un altro venue: il
backfill è plausibile sui prezzi proprio perché è copiato. Il **volume** (=liquidità reale) è il gate
che mancava. Coerente con la regola di prim'ordine v2.0.0: certificare il dato — anche il *volume*,
non solo il prezzo — prima della strategia.
File: `scripts/analysis/fetch_hyperliquid.py`. Universo: `data/raw/hl_*_1d.parquet` (51, serie native).
@@ -0,0 +1,93 @@
# 2026-06-20 — Analisi strategie FinanceOld + VRP v2 (defined-risk + gate IV-rank)
## Contesto
Richiesta: analizzare le strategie in `../FinanceOld`, provare a migliorarle, testarle su dati storici.
Quattro progetti esaminati. Verdetto di **backtestabilità onesta** sui dati certificati (BTC/ETH
Deribit mainnet + DVOL):
| Progetto | Strategia | Backtestabile sui dati certi? |
|---|---|---|
| **FundingRateArbitrage** | Spread funding cross-exchange (perp-perp, spot-hedge) | ❌ Nessun dato funding storico nel repo (solo `exchange_settings.json`). Edge = differenza cross-venue, non ricostruibile. |
| **Polybot** | Latency-arb Polymarket (BS digital-option) + sure-bet delta-neutral | ❌ `dataVPS/collector.db` (645MB) ha solo **~3 giorni** di `poly_books`+`funding`, e la tabella `ticks` (prezzi perp = cuore dell'edge) è **corrotta** ("database disk image is malformed"). L'edge è la latenza: non riproducibile su barre OHLC comunque. |
| **OptionSpalping** (→Cerbero) | LLM autonomo su opzioni Deribit + perp Hyperliquid | ⚠️ È un agente LLM, non una regola meccanica. Il *concetto* (income short-vol su Deribit) è testabile. |
| **OptionsAgent** | **Bear Call Spread + Long VIX hedge** su IWM, con 5 gate d'ingresso | ✅ Il *concetto* (vendi premio rischio-definito, incassa VRP, gate su IV-rank/regime) mappa direttamente sul nostro `options_vrp_lab.py`. |
→ Scelta operatore: **focus VRP opzioni**. L'unico filone con dati veri + metodologia onesta.
## Baseline (options_vrp_lab.py, ora con fee)
Vendita put NUDA settimanale delta -0.28, premio BS su DVOL reale. f = premio_reale/modellato.
- `f=1.0` (conservativo): **FULL Sh 0.78, DD 33%, worst-week -16.6%, HOLD-OUT Sh -0.25** → muore OOS.
- Il rischio è la **CODA**: worst-week su LUNA (2022-06), crash 2021-05. Anno 2022 = -9%.
## VRP v2 — 3 idee di OptionsAgent portate nel framework
Nuovo script `scripts/research/options_vrp_v2.py`. Tutto **causale** (strike/premio/gate da dati
≤ sell-date; payoff a scadenza sui prezzi certificati). Fee opzioni Deribit modellate (12.5% del
premio netto per round-trip = cap del fee reale). Capitale = strike corto (cash-secured) per
entrambe le strutture → DD/worst comparabili.
1. **Rischio definito (PUT CREDIT SPREAD)** — vendi put -0.28, COMPRI put -0.10. Il long wing
**cappa la coda per costruzione**: worst-week -16.6% → **-7.4%**, DD 33% → 21%, Sh 0.78 → 0.99.
2. **Gate IV-RANK > 0.30** (cond. d'ingresso di OptionsAgent) — vendi vol solo quando ricca
(percentile espandente causale di DVOL). Trada il **58%** delle settimane → **Sh 1.35** e
ribalta **HOLD-OUT da -0.25 a +0.28**. È l'alpha vero: il filtro di regime, non la struttura.
3. **Crash-skip IV-rank > 0.90** (NO-GO, come "VIX>35" di OptionsAgent) — marginale da solo.
4. **Gate VRP>0** (DVOL>RV30 causale) — marginale (il VRP è >0 il 78% del tempo, poco selettivo).
### Risultati chiave (book 50/50 BTC+ETH, f=1.0 conservativo)
| Config | FULL Sh | DD | worst-wk | HOLD-OUT Sh | attivo |
|---|---|---|---|---|---|
| naked (baseline) | 0.78 | 33% | -16.6% | **-0.25** | 100% |
| spread | 0.99 | 21% | -7.4% | -0.26 | 100% |
| spread + ivr30 | **1.35** | 14% | -7.4% | **+0.28** | 58% |
| **COMBO** (spread+vrp+ivr30+crashskip) | 1.10 | 12% | -7.4% | **+0.60** | 41% |
COMBO f=1.0 per-anno: 2021 +26%, 2022 **-6%**, 2023 +2%, 2024 +18%, 2025 -0%, 2026 +5%
(il 2022, anno-crash che dimezzava il nudo, è quasi piatto: la coda è tagliata).
A `f=1.29` (skew reale misurato in regime calmo) la COMBO fa FULL Sh 1.87 / HOLD 1.45 / DD 9%.
### Contributo al portafoglio (COMBO f=1.0 vs TP01)
- Corr settimanale **+0.07** (scorrelato, come il VRP nudo).
- TP01 70% + OPT 30% → Sh **1.00** (TP01 solo 0.73), DD **7%**.
- TP01 50% + OPT 50% → Sh **1.19**, DD 7%.
## Conclusione onesta
Le idee di OptionsAgent **migliorano davvero** lo sleeve VRP, in modo OOS-robusto:
- la **struttura defined-risk** taglia la coda (worst -16.6%→-7.4%, DD -19pt) → meno dipendenza dal
f di stress, che era il rischio non catturato del lead nudo;
- il **gate IV-rank** è l'alpha: ribalta l'HOLD-OUT da negativo a positivo vendendo solo vol ricca.
Resta un **lead, non un deploy**: premio MODELLATO su DVOL ATM (skew non esplicito), book a 1d, e
serve la catena reale (cerbero-bite) per il f di stress in un crash. Ma è un miglioramento netto,
quantificato e onesto, del miglior lead income che avevamo. Prossimo passo: rivalutare il f di stress
quando cerbero-bite cattura un crash, e validare lo skew reale sul long wing (-0.10).
Script: `scripts/research/options_vrp_v2.py`. Baseline: `scripts/research/options_vrp_lab.py`.
## Integrazione come sleeve (VRP01)
La COMBO è stata integrata nel portafoglio come **VRP01** (`src/portfolio/sleeves._vrp_combo_returns`,
`vrp_sleeve()`). Implementazione self-contained in `src/` (niente import da `scripts/`): pricing BS +
strike-from-delta + gate causali inline, DVOL da `data/raw/dvol_*.parquet`.
**Settimanale → giornaliero (onesto):** il rendimento settimanale è piazzato sul **giorno di
scadenza**, 0.0 sugli altri giorni dello span. Questo PRESERVA lo Sharpe annualizzato (niente
smoothing che gonfierebbe il daily Sharpe) e tiene lo sleeve presente ogni giorno → peso costante
nell'outer-join del portafoglio. Verificato: lo sleeve daily replica i numeri settimanali
(FULL Sh 1.09, HOLD 0.60, DD 12%), corr daily vs TP01 = +0.01.
**Pesi (per evidenza, engine reale):** TP01+VRP01 monotòno fino al 40% VRP (FULL 1.30→1.55,
HOLD 0.31→0.52, DD fermo 14%). Essendo VRP un lead MODELLATO (non deploy pieno), non lo sovrappeso:
registry = **TP01 0.55 / XS01 0.25 / VRP01 0.20** (TP01 resta maggioranza, l'unico deployable pieno).
La validazione 3-way completa richiede i dati Hyperliquid (XS01, gitignored, token Cerbero) → gira
locale con `scripts/portfolio/run_portfolio.py`.
Test: `tests/test_vrp_sleeve.py` (5 pass: monotonìa BS, ordering strike, determinismo+griglia
giornaliera, gate riducono l'attività, coda tagliata <-15%).
@@ -0,0 +1,43 @@
# VRP01 + gestione attiva intra-trade — A/B onesto (NEGATIVO)
**Data:** 2026-06-20
**Script:** `scripts/research/options_vrp_managed.py`
**Esito:** la gestione attiva del documento credit-spread **distrugge l'edge**. VRP01
**hold-to-expiry resta superiore.** → scartata.
## Cosa testava
Innesta sul put credit spread di VRP01 le regole intra-trade del doc `strategia-credit-spread-eth`:
profit-take 50% del credito, stop-loss 1.5× il credito, **VOL-STOP** (chiudi se DVOL sale ≥10 punti
dall'apertura — regola crypto-specifica nuova), **delta-exit** (chiudi se |delta| short put ≥0.30),
time-stop 7 DTE. A/B sugli **stessi ingressi gated** (VRP>0 + IV-rank>0.30) e dati certificati;
MTM giornaliero dello spread via BS sul path certificato + DVOL reale (causale).
BASE = hold-to-expiry (come VRP01) vs MANAGED = stesso trade gestito.
## Risultato (combo 50/50 BTC+ETH, sleeve-level)
| variante | Sharpe | DD | ret | HOLD Sh |
|----------|--------|------|------|---------|
| 14d hold-to-expiry (BASE) | **0.96** | 11.7% | +39% | +1.52 |
| 14d + solo vol-stop | 0.12 | 10.1% | +3% | +1.01 |
| 14d FULL managed | **1.29** | 14.8% | 15% | 1.17 |
Per-asset: la gestione FULL ribalta entrambi (ETH 0.33→−1.15, BTC 1.88→−0.89). Il **delta-exit**
domina le uscite (18-25 trade su ~33-45) e taglia i vincenti prima della decadenza theta; persino
il **vol-stop da solo** quasi azzera il ritorno (combo Sh 0.12). Win-rate crolla 80-94% → ~40%.
## Lettura
Per un venditore di premio short-vol l'edge È la decadenza theta tenuta fino a scadenza: ogni
uscita anticipata (delta, vol-stop, PT) **monetizza meno theta e/o realizza la coda** invece di
lasciarla riassorbire. Le regole di "difesa" del doc azionario/ETH non trasferiscono al VRP crypto
modellato: l'unica gestione che non danneggia è **non gestire** (hold-to-expiry, come VRP01 già fa).
**Caveat invariato:** premio MODELLATO su DVOL ATM (no skew) + nessun fill di stress reale → tutto
ciò resta a livello di LEAD, non deploy. Ma la conclusione relativa (BASE > MANAGED) è robusta
perché è un A/B sugli **stessi** trade e dati.
## Azione
Nessuna modifica a VRP01 (`sleeves._vrp_combo_returns`, hold-to-expiry). Script conservato come
riferimento dell'esperimento scartato.
@@ -0,0 +1,133 @@
# Sweep strategie cross-sectional su Hyperliquid (xsec) — 43 script / 257 config
**Data:** 2026-06-20
**Harness:** `scripts/research/xsec/xslib.py` (nuovo) + 43 script in `scripts/research/xsec/runs/`
**Verifica:** `scripts/research/xsec/verify_survivors.py` (3 scettici, deterministico)
**Esito in una riga:** niente di deployabile; il cluster vincente appariscente è **una sola
scommessa di regime (short alt-beta)**, ma **2 lead genuini** (XM09 trend-gated x-sec momentum,
XR02 reversal vol-gated) sopravvivono a tutti gli scettici → **forward-monitor, non sleeve.**
## Contesto e motivazione
Dopo che il sweep BTC/ETH a 104 ipotesi (`2026-06-20-alt-strategies-100agent-sweep.md`) ha
esaurito lo spazio direzionale single-asset confermando il soffitto ~1.3, la frontiera indicata era
**cross-sectional / multi-asset** sul panel Hyperliquid certificato, dove quel soffitto non vincola
e dove c'è spazio DISTINTO da XS01 (x-sec momentum semplice sui 19 major).
Nuova harness condivisa `xslib.py`: il panel è N asset × ~810 giorni (universo `all` = **49 alt**
con ≥700g dopo il fix backfill; `majors` = 19 di XS01). Una strategia = uno **score per-asset
causale** (dati ≤ close[i]); l'harness lo classifica cross-section ad ogni ribilanciamento, va long
i top-k / short i bottom-k (market-neutral) o long-only, vol-targeta al 20%, addebita fee sul
turnover, e — strutturalmente leak-free — il peso deciso a `i` incassa il return di `i+1` (stessa
convenzione di `src.portfolio` xs_book / `sleeves._xsec_returns`).
**Scoring onesto** (`study_xs`): un candidato guadagna `earns_slot=True` SOLO se
`full Sharpe>0 AND hold-out 2025+ Sharpe>0 AND marginal_vs(active)=="ADDS" AND corr(XS01)<0.6`.
`ADDS` a sua volta richiede `holdUplift_w20 ≥ 0.05 AND robust_oos` (uplift hold-out >0.02 **e**
jackknife drop-one-month tutti positivi). È il marginal scorer del sweep precedente, portato sul
cross-sectional: si giudica **l'apporto al portafoglio live** (TP01+XS01+VRP01), non lo Sharpe
assoluto.
**Caveat cotto dentro l'harness:** il panel è **~2.5 anni** (2024-26). Ogni risultato è
SUGGESTIVO, non robusto come i 6 anni di BTC/ETH. E l'hold-out (2025-26) è **un singolo regime**
(alt-bear/chop relativo a BTC).
## Find phase — 43 script, 257 sotto-config
11 famiglie cross-sectional: MOM (varianti momentum), REV (reversal), VOL/RISK (low-vol, low-beta,
BAB, semivarianza, vol-of-vol), DIST (skew/coskew lottery), LIQ (Amihud/turnover/volume),
VAL (distanza da MA, RSI), STRUCT (double-sort, ensemble z-vote, risk-parity, low-corr, trend-R²,
lead-lag BTC), UNIV (sweep di universo). **Esito: 42/257 config `earns_slot=True`.**
Sembra molto. Ma **due tell** accomunano quasi tutti gli slot-earner:
1. corr a TP01 **fortemente negativa** (0.2…−0.4) — è *per questo* che "aggiungono";
2. PnL **concentrato nel 2025** (ritorni +22%…+84% nel 2025).
Top per Sharpe/uplift (rappresentante per famiglia):
| id | meccanismo | univ | FULL Sh | HOLD Sh | upliftHold | jackknife | corr TP01 | corr XS01 |
|----|-----------|------|---------|---------|-----------|-----------|-----------|-----------|
| XR02-L3-p70-maj | reversal gated alta-vol | maj | 1.40 | **2.27** | 1.078 | 0.744 | 0.02 | 0.08 |
| XV02_majors_H10k5 | low **idio**-vol | maj | 1.32 | 1.95 | 1.196 | 0.792 | 0.20 | 0.06 |
| XL02-vz60r20-maj | vol-trend momentum | maj | **1.83** | 1.84 | 0.568 | 0.125 | 0.13 | 0.08 |
| XM09_all | trend-gated x-sec mom | all | 1.29 | 1.59 | 0.556 | 0.355 | 0.07 | 0.25 |
| XS01b-MAJ | double-sort mom×low-vol | maj | 1.36 | 1.23 | 0.427 | 0.16 | 0.29 | 0.38 |
| XU02/XV01 lowvol | low realized-vol | maj | 1.05 | 0.98 | 0.425 | 0.186 | 0.34 | 0.16 |
| XV03 lowbeta (BAB) | beta | all | 0.36 | 0.71 | 0.22 | 0.051 | 0.38 | 0.19 |
| XS06b lowcorr | corr(asset,market) | all | 0.74 | 1.00 | 0.286 | 0.092 | 0.19 | 0.18 |
## Verify phase — 3 scettici (`verify_survivors.py`)
Ipotesi sotto test: *"non sono N edge indipendenti, ma UNA scommessa di regime — short la
spazzatura high-beta nell'alt-bear 2024-26 — travestita da 30 maschere; il jackknife è robusto solo
DENTRO quel regime."* Ricostruito il book più forte per famiglia e:
**S1 — matrice di correlazione mutua (>0.6 = stessa scommessa).** Esito SFUMATO:
- Il cluster low-vol È una sola scommessa: **XV01 = XU02 = 1.00** (identici), XV01↔XV02 0.65,
XV01↔XV03 0.67, XV02↔XV03 0.44.
- MA **XM09, XL02, XS06b, XR02 sono distinti** dal cluster e tra loro (corr media off-diagonale
solo **+0.20**, solo 18% delle coppie |r|>0.6). L'ipotesi "tutto una scommessa" è **parzialmente
falsa**.
**S2 — carico su short-beta / short-market** (factor di riferimento sullo stesso panel:
SHORTBETA = book su beta; SHORTMKT = market alt equal-weight):
- **Cluster low-vol = short-alt-beta confermato:** XV03 1.00/0.70, XV01/XU02 **0.67/0.64**,
XV02 0.44/0.37. *Non* market-neutral: è un tilt short del mercato alt.
- **NON short-beta:** XM09 0.08/0.15, XR02 0.21/0.18, XL02 0.19/0.26, XS06b 0.36/0.39.
**S3 — Sharpe per anno solare (l'edge è ~solo 2025?):**
| survivor | 2024 | 2025 | 2026 |
|----------|------|------|------|
| XV02_lowidiovol | 0.07 | 1.87 | 2.12 |
| XV01/XU02 lowvol | 1.17 | 1.52 | **0.09** |
| XV03_lowbeta | 0.25 | 0.98 | 0.12 |
| XS06b_lowcorr | 0.26 | 1.34 | 0.32 |
| **XM09_trendgmom** | **0.82** | **0.50** | **0.74** |
| XL02_voltrendmom | 0.30 | **0.14** | **0.43** |
| **XR02_revgated** | **0.84** | **0.40** | **2.68** |
## Conclusioni (oneste)
1. **Cluster low-vol / low-beta (XV01, XU02, XV02 in parte, XV03) = tilt short-alt-beta di regime.**
S2 lo inchioda (carico 0.44-0.70 su short-market): non è un fattore market-neutral, è "short la
spazzatura" mentre gli alt sanguinano vs BTC. XV01/XU02 **già in decadimento (2026 0.09).** Non
può dimostrare di sopravvivere a un flip alt-bull. → **RIGETTATO come sleeve.** Conferma
l'osservazione 4874 (XS04b = regime-dependent short-beta tilt) generalizzata all'intera famiglia.
2. **XL02 (vol-trend momentum) = overfit al panel iniziale.** FULL Sharpe più alto (1.83) ma S3 lo
uccide: 2025 0.14, 2026 0.43. Il numero full è guidato dal 2024, ora è morto. → **RIGETTATO.**
3. **2 LEAD genuini** — distinti (S1), NON short-beta (S2), positivi in **tutti e 3 gli anni** (S3):
- **XM09 — cross-sectional momentum gated dal trend di mercato.** Long top-k/short bottom-k alt,
attivo solo quando la somma trailing del mercato equal-weight è >0. Sharpe 0.82/0.50/0.74,
short-beta-load 0.08, corr TP01 0.07, uplift hold 0.556 / jackknife 0.355. È il candidato più
regime-robusto. **Caveat:** stessa FAMIGLIA di XS01 (x-sec momentum) su universo più largo (49)
con gate diverso (trend di mercato vs dispersione) → più un **possibile affinamento di XS01**
che una sleeve nuova; corr XS01 0.25, ma marginal scorer dice che ADDS oltre XS01.
- **XR02 — short-term reversal gated da alta-vol.** Reversal a 3g attivo solo quando la vol
realizzata di mercato è nel regime alto (>p70 espandente). Sharpe 0.84/0.40/**2.68**,
short-beta-load 0.21, corr a tutto il resto ~0/negativa, hold-out Sharpe 2.27. Microstruttura
reale (overreaction in panico). **Caveat:** H=3 → **turnover alto**; il reversal vive proprio
sull'illiquidità che lo rende costoso da eseguire (l'harness addebita fee sul turnover e regge,
ma il fill reale su alt minori è ottimistico).
## Perché NON deployabili adesso (caveat trasversali)
- **Panel ~2.5 anni a regime unico.** Anche i 2 lead hanno hold-out = 2025-26 = stesso macro-regime.
Suggestivi, non robusti come i 6 anni BTC/ETH.
- **STAT-MODE di esecuzione.** Un book cross-sectional a 10-19 gambe (long-k+short-k) su alt non è
eseguibile col capitale attuale (conto reale ~$600; servono ~$20k per gambe sensate, come già
notato per XS01). Sono segnali da monitorare, non ordini.
- **Lezione confermata (di nuovo):** su un panel corto a regime unico il jackknife drop-one-month
certifica la robustezza DENTRO il regime, non ATTRAVERSO i regimi. Il discriminante decisivo è
stato **S2 (carico su short-beta) + S3 (consistenza per-anno)**, non lo Sharpe né l'uplift
hold-out (che il cluster regime-bet aveva altissimi: upliftHold fino a 1.20).
## Azioni
- **Nessuna modifica al portafoglio live** (TP01 55% + XS01 25% + VRP01 20% invariato).
- **Forward-monitor** i 2 lead (XM09, XR02) quando il panel HL accumula un secondo regime.
- **XM09 come affinamento candidato di XS01** (gate trend di mercato + universo 49) da valutare a
parità di sleeve, NON come sleeve aggiuntiva, in una prossima iterazione.
- Harness `xslib.py` + 43 script + `verify_survivors.py` committati come riferimento riusabile.
+111
View File
@@ -0,0 +1,111 @@
# 2026-06-21 — Blind signal fleet: 52 agenti "esperti di segnali" su curve anonime BTC/ETH
## Obiettivo (richiesta utente)
Far partire ~50 subagenti **esperti di segnali** a cui passare lo storico di **ETH e BTC
in forma ANONIMA** ("senza dire di cosa sono, con curve sovrapposte"): devono trovare come
**anticipare l'andamento**, liberi di scrivere script o reti neurali ad hoc. L'**orchestratore**
valuta la validità su **PnL e maxDD**.
L'idea forte del setup cieco: se gli agenti non sanno che sono BTC/ETH, non possono
pattern-matchare a memoria il crash COVID 2020 / l'orso 2022 / l'halving 2024 — devono trovare
un timing **trasferibile**, non riconoscere l'era. È anche un test di onestà del metodo: l'edge
deve reggere su un hold-out che gli agenti non hanno mai visto.
## Setup — harness cieco e leak-free (prima degli agenti)
> 50 agenti su un harness che perde = 50 fantasie (lezione fondante del progetto). Quindi prima
> l'infrastruttura, poi la flotta.
- `scripts/research/blind/make_blind.py` — esporta BTC/ETH **1d** (via il path certificato
`altlib.get`) come **"Series A" / "Series B"**: rebase a **100** (curve sovrapposte, il livello
non urla più "$60k bitcoin"), **calendario sintetico** dal 2001 (niente era-crypto da
riconoscere), volume normalizzato alla mediana. Split **70% train (visibile agli agenti) / 30%
test (solo orchestratore)**. Mapping A=BTC, B=ETH tenuto FUORI dal meta visibile.
- `scripts/research/blind/blindlib.py` — l'unico modulo che un agente importa. Evaluator
leak-free: la posizione decisa a `close[i]` è **shiftata** e tenuta nella barra `i+1` (impossibile
leakare moltiplicando un peso per il rendimento della stessa barra), fee su turnover (Deribit
0.10% RT). Toolkit di indicatori causali ri-esportati da altlib.
- **Guardia di causalità automatica** (`causality_ok`): ri-chiama `signal()` su un **prefisso
troncato** e pretende che la coda combaci con `signal()` sull'array intero. Qualunque segnale che
sbircia il futuro (shift(-k), finestre centrate, fit globale, statistiche full-sample) **diverge →
squalificato**. È ciò che rende onesta anche la "rete neurale ad hoc": un modello fittato sul df
intero (che a test-time contiene il futuro) fallisce la guardia; passa solo l'expanding/walk-forward.
- `score_all.py` — il **giudice unico dell'orchestratore**: per ogni modulo gira la guardia, valuta
sul **test held-out** A e B, ordina per PnL/maxDD vs benchmark buy&hold.
- `verify_top.py` — secondo strato avversariale: corr al trend canonico TSMOM, fee-stress 0.20% RT,
jackknife drop-block.
Verifica dell'harness: momentum onesto → causale ok, OOS +44% a 19% DD; segnale **deliberatamente
leaky** (guarda domani) → Sharpe 18 assurdo ma **correttamente squalificato**. Benchmark buy&hold
OOS sul tail = **7% PnL, 68% DD, Sharpe 0.22** (il tail 2024-26 contiene un drawdown brutale →
anticipare il movimento ha spazio reale per vincere).
## Flotta — 52 agenti, 52 ipotesi distinte
Workflow `blind-signal-fleet` (52 agenti in parallelo, ~2h, 2.5M token, 971 tool-call). A ognuno
**un'ipotesi diversa** (per non riscoprire tutti il momentum): 11 famiglie — trend/TSMOM,
breakout (Donchian/Keltner/squeeze/pivot/volbreak), mean-rev/oscillatori (RSI/Bollinger/zrev/stoch/
DPO/WillR), vol-regime (vol-target/regime-switch/ATR-ride/dd-derisk/**vol-of-vol**), struttura
(HHLL/channel-pos), statistici (Hurst/autocorr/efficiency/skew/entropy), ciclo (FFT/Kalman),
volume (OBV/PVT/vol-div), **8 ML** (Ridge, logistic, MLP-reg, MLP-clf, GBM, kNN-analog, RLS,
RandomForest) e 5 meta/ensemble.
**Esito flotta: 52/52 riportati, 52/52 passano la guardia di causalità** (zero look-ahead — la
disciplina dell'harness ha tenuto su tutta la flotta, ML inclusi).
## Risultati OOS (orchestratore — PnL & maxDD sul test held-out)
Benchmark buy&hold OOS: **PnL 7%, maxDD 68%**. Top per Sharpe-min (peggiore tra A e B):
| # | strategia | PnL_A | PnL_B | DD worst | Sh_min | famiglia |
|---|---|---|---|---|---|---|
| 1 | macd | +23% | +19% | **11%** | 0.84 | trend |
| 2 | accel | +40% | +22% | 12% | 0.79 | trend (2ª diff) |
| 3 | vol_of_vol | +30% | +32% | 21% | 0.69 | vol-regime |
| 4 | regime_switch | +25% | +46% | 20% | 0.63 | vol-regime |
| 5 | rf (ML) | +12% | +8% | **7%** | 0.62 | ML walk-fwd |
| 6 | obv | +22% | +20% | 16% | 0.60 | volume |
Tutti i top sono varianti **trend/vol-regime**. Mean-reversion e ML (logistic/gbm/mlp) in fondo →
ri-conferma cieca di "mean-rev morto" e "ML walk-forward debole" del progetto. Lo **Sharpe OOS ~0.84
decade dal train ~1.4** (firma classica di overfit/regime). Ma vs buy&hold (7%/68% DD) i top trend
**ribaltano il segno e tagliano il DD ~3-6×**: è il valore reale, identico alla lezione TP01.
## Verifica avversariale — 3 scettici indipendenti (REFUTE, non confirm)
1. **Regime-luck****REFUTED ×3.** I top-5 bar su ~800 OOS forniscono il **67-102% di tutto il
PnL**; togliendo 10 bar la serie va **negativa**; `accel` crolla nel terzo finale (COMB Sharpe
**1.21**); A e B non concordano su *quando* funziona. Edge concentrato, non distribuito.
2. **Trend-redundancy****REFUTED ×4.** Regressione `cand ~ α + β·TSMOM` (Newey-West HAC):
**t(α) = +0.92..+1.51, nessuno supera 1.96**. corr-al-trend 0.34-0.74, β 0.45-0.73; media residua
+0.05-0.08/anno = rumore. Sono TSMOM meglio tarati, **non alpha ortogonale**; contro il TP01 reale
(~1.3) il margine svanisce.
3. **Overfit/robustezza** → MACD **non-refuted** (plateau vero a un asse, 0% celle <0.5) ma Sharpe OOS
onesto **0.84, non 1.40** (numero da docstring = in-sample). `accel` **REFUTED** (il termine di
accelerazione, la sua tesi, **danneggia** l'OOS; LAG knife-edge: 20% → 63% Sharpe; corner
congiunti negativi). `vol_of_vol` **REFUTED** (gate threshold-fit: PCTL 0.80→0.60 distrugge il 73%
dello Sharpe OOS). Fee = drag secondario ~10%, non il killer; il killer è la sensibilità ai parametri.
## Verdetto
**52 agenti ciechi, orchestratore che valuta PnL e maxDD su hold-out, e NIENTE di nuovo
sopravvive alla verifica avversariale.** Ogni "vincitore" è trend-beta di due curve strutturalmente
rialziste; soffitto Sharpe OOS **~0.84** su questo singolo hold-out; nessun alpha statisticamente
distinguibile dal TSMOM. È una **ri-conferma INDIPENDENTE e CIECA del soffitto direzionale ~1.3** del
progetto e del pattern "TSMOM travestito" — raggiunta da agenti che non sapevano nemmeno fossero
BTC/ETH. Il più solido è **macd** (plateau vero, OOS Sharpe 0.84, DD 11%): classe-TP01,
**forward-monitor al più, non deploy**. Conferma le regole: (a) giudicare lo Sharpe **marginale vs
TP01**, non assoluto; (b) un hold-out corto premia chi è stato fortunato in pochi bar.
### Valore metodologico (cosa resta)
L'harness cieco riusabile: `data/blind/` + `blindlib`/`blind_eval`/`score_all`/`verify_top`. La
**guardia di causalità online** ha tenuto 52 strategie (ML incluso) leak-free senza intervento
manuale → strumento da riusare per ogni futura flotta. La pipeline "anonimizza → fan-out cieco →
giudice unico OOS → 3 scettici (regime-luck / trend-redundancy / overfit)" ha ucciso ogni falso
positivo che lo Sharpe assoluto avrebbe promosso.
File: `scripts/research/blind/{make_blind,blindlib,blind_eval,score_all,verify_top}.py`,
`agents/agent_00..51_*.py` (52 moduli), `leaderboard.json`, `verify_top.json`,
`SKEPTIC_VERDICTS.json`. Dati rigenerabili: `data/blind/` (gitignored).
@@ -0,0 +1,88 @@
# 2026-06-21 — Asse intraday/microstruttura: il lead più vicino al reale, ma NON deployabile
## Perché (utente: "cerchiamo qualcosaltro")
Direzionale e relative-value su BTC/ETH esauriti (flotte blind + ortho). L'unico asse mai
sfruttato dopo il reset = il **tempo intraday** (feed certificati 5m/15m/1h; tutto era a 1d).
Meccanismi diversi da trend e relative-value: bias ora/sessione (perp con funding a 00/08/16 UTC),
reversione post-evento (vol/volume/gap), breakout del range del giorno prima.
## Setup
`scripts/research/intraday/intra_score.py`: wrappa `altlib.study_marginal` a un TF a scelta
(compone i rendimenti intraday a daily, li valuta col **marginal scorer indurito** = multi-cut +
edge-in-sample + hedge-vs-alpha) e riporta **turnover + fee-sweep a 0.20% RT**. Il muro: a 0.10% RT
il churn intraday è morte (un flip orario fa 2152 trade/anno → 8.6 Sharpe netto). Vincolo agli
agenti: **basso turnover**, l'intraday come informazione (timing/sizing/gating), non HFT.
## Flotta — 16 agenti
16 ipotesi low-turnover. Esito grezzo: 16 riportati, **10 "earns_slot"** (di nuovo gonfiato).
## Diagnosi orchestratore — separare ortogonale vero da trend-beta
Per corr-a-TP01 (`meta_intra.py`): 2 sono **trend-beta** (close_location 0.81, trend_quality 0.75 —
Sharpe in-sample alto ma preso in prestito dal trend), 3 **mixed**, **5 genuinamente ortogonali**
(|corr|<0.4): open_drive (0.13), prevday_range_breakout (0.15), vol_event_revert_15m (0.1),
volume_spike_revert (0.14), gap_fill (0.04) — 2 famiglie (breakout-continuation + capitulation-revert),
mutuamente de-correlate. **Combo dei 5: Sharpe standalone 1.80, corr-TP01 0.17, uplift +0.33/+0.27/
+0.34/+0.34/+0.53 a OGNI cut** (non solo 2025).
## Gauntlet deterministico (`verify_intra.py`) — passa TUTTO ciò che uccise le onde precedenti
- **In-sample pre-2025 Sharpe 1.75; uplift pre-2025-ONLY +0.281** (l'ortho faceva +0.027 = null).
- **Walk-forward selection** (scegli su solo passato, testa avanti): **+0.303 / +0.368** (l'ortho dava 0.07).
- **Drop-one robusto** (+0.24..+0.31 pre-2025), **fee-robusto a 0.30% RT**, **leak-free**
(online-consistency: max_tail_diff = 0.0 su tutti e 5). Sembrava IL lead.
## Verifica avversariale (3 scettici indipendenti) — il verdetto vero
1. **Execution/microstruttura:** **open_drive = ARTEFATTO di etichettatura UTC.** Spostando il
confine del giorno di 4h l'uplift va NEGATIVO (0.10); togliendo l'ancora UTC (trailing-8h) Sharpe
0.01; funziona solo a 00:00 UTC, solo alle ore 3 e 7. **Scartare.** `prevday_range_breakout` invece
**REGGE** (plateau su k, robusto allo shift del confine, fill eseguibili a close) = unico candidato
onesto, ma la decorrelazione viene tutta dalla gamba SHORT che si appoggia al regime down 2025-26;
anchor=1 only. **Caveat $600:** il vol-target fa ~8500 ribilanciamenti/anno, 97-98% < $1 di nozionale
→ la fee proporzionale modellata su trade infinitesimi è **finzione** a $300/gamba (vale anche per TP01).
2. **Hedge + tail:** **REFUTED.** L'uplift pre-2025 +0.281 sta al **20-24° percentile del null di un
asset a corr-zero** (mediana null +0.371) — essendo a corr +0.175 (non 0) e bassa vol, **aggiunge
MENO del rumore scorrelato**. È **hedge** (corr Sharpe-TP01/uplift 0.57..0.80; TP01-down uplift
+0.79 vs TP01-up +0.20) e **tail-luck** (le gambe revert: top-5 giorni = 76-83% del PnL, <10
eventi/anno, front-loaded 2019-21; combo: metà uplift in ~10 giorni).
3. **Overfit/robustezza:** **ROBUST-PLATEAU** (243-cell joint grid pre-2025 uplift min +0.134/med
+0.211, 99% celle >+0.15; ogni anno positivo). MA segnala lui stesso il **null-pctl 0.20**: "il
beneficio è la matematica di diversificazione di uno stream ortogonale a Sharpe 1.75, NON timing-alpha
specifico-TP01" + storia corta sulle gambe revert + fill modellati vs reali.
## Verdetto
**Niente in live.** L'asse intraday ha prodotto il lead **più vicino al reale** di tutta la ricerca,
ma sotto 3 scettici: **open_drive è artefatto** (UTC-labeling); la combo **fallisce il null a
corr-zero** (aggiunge meno del rumore), è **hedge-shaped** e **tail-luck**; e lo Sharpe modellato è
gonfiato dal micro-ribilanciamento sub-dollaro a $600. Lo Sharpe standalone 1.80 NON è affidabile
(artefatto + coda + finzione di fill). **Resta solo TP01.**
**Lead reale (forward-monitor, non deploy):** `prevday_range_breakout` — l'unico segnale sopravvissuto
allo scettico d'esecuzione (breakout del range del giorno prima, eseguibile, leak-free), con caveat
short-leg/regime-2025. Trattamento = come `dvol_spread` / XS01 / STA05.
### Lezioni harness — CODIFICATE (il vero ritorno)
1.**`altlib.day_boundary_robust(target_fn, tf)`** — shifta il confine del giorno UTC e ri-misura
l'uplift marginale: INVARIANT (segnale di prezzo, spread 0) / ROBUST (effetto calendario vero,
resta positivo) / **ARTIFACT-RISK** (l'uplift si inverte = etichettatura). Verificato: riproduce
da solo il verdetto degli scettici — open_drive → ARTIFACT-RISK (+0.23→−0.33), prevday_breakout
→ ROBUST. Test `tests/test_harness_realism.py`.
2.**`altlib.eval_weights_smallcap(df, target, capital=600, min_order=5)`** — salta i
ribilanciamenti sub-min_order (la finzione del micro-trading a $600), riporta lo Sharpe haircut
reale vs modellato. Vale per ogni sleeve a questo capitale, TP01 incluso. Test idem.
3.**`altlib.causality_ok(target_fn, tf)`** — guardia look-ahead/online-consistency (ricalcola
il target su un prefisso e pretende che la coda combaci con il full): eval_weights shifta la
posizione ma NON vede una feature non-causale (finestra centrata / shift(-k) / stat full-sample).
Integrata in `intra_score` (un leak è squalificato prima dello scoring). + il calendar-artifact
gate (`day_boundary_robust`) ora gira dentro `intra_score`: **open_drive/weekly_seasonality/
overnight → CAL-ARTIFACT, fuori dagli slot da soli**; prevday_breakout resta (ROBUST). Il lab
intraday ora auto-becca leak e artefatti-calendario che ieri richiedevano gli scettici. Test idem.
File: `scripts/research/intraday/{intra_score,meta_intra,verify_intra}.py`,
`agents/agent_00..15_*.py`, `intra_leaderboard.json`.
@@ -0,0 +1,99 @@
# 2026-06-21 — Caccia all'ORTOGONALE a TP01: relative-value BTC/ETH (eseguibile a $600)
## Perché (richiesta utente: "cerca ortogonale a TP01")
La flotta cieca (stesso giorno) ha confermato: niente di NUOVO in direzionale BTC/ETH — tutto è
trend-beta di TP01 (soffitto ~1.3). L'unica via a un nuovo slot LIVE è un meccanismo **ortogonale**
(bassa correlazione, alpha residua). Il più promettente **eseguibile al capitale reale ~$600** è un
**book RELATIVE-VALUE a 2 gambe BTC/ETH** (long una / short l'altra), grosso modo market-neutral →
correlazione naturale bassa col trend, e a 2 gambe è eseguibile (a differenza del book a 19 gambe di
XS01 che serve ~$20k).
## Setup — ortho-lab + giudice MARGINALE (non Sharpe assoluto)
`scripts/research/ortho/ortholib.py`: BTC/ETH 1d allineati su date comuni; `eval_book(book_fn)` con
`book(btc,eth)->(w_btc,w_eth)`, **shift di entrambe le gambe** (no leak), fee su entrambe, serie netta
**giornaliera**; guardia di causalità online; check **eseguibilità a $600** (max gamba ≤ 0.5 = cap
$300/asset). Il giudice è `altlib.marginal_vs_tp01`: **corr a TP01, uplift OOS del blend, alpha
residua, robust_oos** (clean-year + jackknife drop-month). Verdetto = ADDS, **non** Sharpe assoluto.
`ortho_score.py` (giudice), `meta_ortho.py` (corr mutua + persistenza multi-cut), `sleeve_rv.py`.
Sanity: ratio-momentum → ADDS (corr 0.05); ratio-mean-reversion → DILUTES. L'harness discrimina.
## Flotta — 18 agenti relative-value (~40 min)
18 ipotesi distinte: ratio-momentum multi-orizzonte, XS a 2 asset, beta-neutral residuo, Donchian
sul ratio, EMA-cross, accel, carry lento, Kalman-spread, gate-correlazione, gate-vol, inverse-vol,
rebalance-harvest, lead-lag, **DVOL-spread**, **VRP relativo**, dispersione, ensemble.
**Esito grezzo: 18 riportati, 17 "ADDS / earns_slot".****bandiera rossa**: non esistono 17 alpha.
Gli agenti stessi l'hanno annotato ("hold-out corto ~537g", "uplift dipende dal regime ETH-bleed
2025", "forward-monitor non full-weight").
## Diagnosi dell'orchestratore — il "17 slot" è gonfiato
1. **Una scommessa o tante?** corr mutua media **0.43** → collassano a **8 rappresentanti**
de-correlati. Non 17, non 1.
2. **Persistente o solo finestra 2025?** `marginal_vs_tp01` fissa l'hold-out al 2025-01-01 = proprio
la finestra dove ETH ha perso vs BTC e TP01 è debole. Ri-misurando l'uplift a **più cut**
(2022/23/24/25): il basket selection-free era +0.06/+0.06/+0.11/+0.38 (positivo ovunque ma
crescente verso il 2025). Smaschera anche i **falsi** che il robust_oos fisso-2025 non vede:
`kalman_spread` (0.14/0.16/0.10 poi +0.37) e `xs2_zscore` sono **2025-only**.
3. **Selezione walk-forward (senza hindsight):** scegliere i top-4 per uplift sul **solo passato** e
testare in avanti → uplift **0.07** (sel <2023) / +0.05 (<2024) / +0.43 (<2025). **Scegliere la
variante vincente in anticipo è inaffidabile**; il mio "curated 4" è in parte hindsight.
## Verifica avversariale (scettico indipendente) — REFUTED
Sul **basket selection-free** (equal-weight di tutti i book market-neutral, NESSUN cherry-picking):
- standalone Sharpe **0.61**, maxDD 15%, **corr a TP01 0.05** (genuinamente ortogonale).
- **uplift full +0.078 = pre-2025 +0.027 / solo-2025+ +0.401.** Il pre-2025 **+0.027 sta al 49°
percentile di 500 asset-rumore a corr-zero** (+0.029 per costruzione) → è **matematica di
diversificazione, non segnale**.
- **corr(Sharpe annuo TP01, uplift annuo basket) = 0.87**; condizionato: TP01 su → +0.014, TP01 giù
→ +0.369. **È un hedge dei drawdown di TP01, non un premio autonomo.** Paga nel 2022 (orso) e
2025-26 (ETH-bleed) — i due anni peggiori di TP01 — rumore altrove (2023 0.06, 2024 0.12).
- Block-bootstrap P(uplift>0): full 90%, **pre-2025 66% (testa o croce)**, 2025+ 99%.
- Fee: a **0.30% RT il pre-2025 va NEGATIVO** (0.021); sopravvive solo il numero del regime 2025.
- Eseguibilità OK ($264/gamba, turnover 12/yr) — non è quello il problema.
## Verdetto
**Niente di questa flotta merita uno slot LIVE.** Il meccanismo relative-value BTC/ETH è REALE e
genuinamente ortogonale (corr ~0.05), ma è un **hedge della debolezza di TP01 travestito da alpha**:
il suo contributo pre-2025 è indistinguibile da un asset-rumore a corr-zero (49° percentile del null)
e muore a fee realistiche; l'unico payoff vero è una singola finestra di 537 giorni (2025-26).
Deployarlo = deployare un backtest mono-regime. **Resta live solo TP01** (l'unica cosa che supera
tutto questo scrutinio). Coerente con XS01 (stessa famiglia cross-sectional): diversificatore
da monitorare, non alpha da eseguire — e la versione a 2 asset è ancora più sottile della 19-gambe.
### Valore metodologico (cosa resta, ed è importante)
- **Il marginal scorer fisso-2025 è ingannabile** (17/18 "ADDS"). Ciò che ha ucciso i falsi positivi:
**persistenza multi-cut** + **selezione walk-forward** + **bootstrap vs null a corr-zero**. Lezione
da cablare nello scorer: testare PIÙ cut e confrontare l'uplift col **null di un asset-rumore
ortogonale** (un'asset scorrelato con drift positivo "aggiunge" +0.03 per pura matematica — non è
un edge). Un basso-corr che paga solo quando il core è debole è un **hedge**, va prezzato come tale.
- Lab riusabile: `ortholib`/`ortho_score`/`meta_ortho` (giudice marginale + persistenza). I 18 book +
`sleeve_rv.py` (curated, **selection-biased — non deployare**) restano come riferimento.
File: `scripts/research/ortho/{ortholib,ortho_score,meta_ortho,sleeve_rv}.py`,
`agents/agent_00..17_*.py`, `ortho_leaderboard.json`, skeptic `skeptic_{basket,regime,null}.py`.
## AGGIORNAMENTO — lezione codificata in `altlib.marginal_vs_tp01` (stesso giorno)
I tre gate sono ora **codice**, non solo prosa (test `tests/test_marginal_scorer.py`, +5 test):
1. **persistenza multi-cut** (`multicut_uplift`/`multicut_persistent`): uplift a ogni inizio anno,
non solo all'HOLDOUT fisso → uccide i 2025-only (es. `kalman_spread`, negativo a ogni cut pre-2025).
2. **edge in-sample** (`has_insample_edge`): lo Sharpe standalone PRE-holdout dev'essere ≥0.5. È il
discriminante onesto (la basket faceva 0.29). I `null_pctl_*` (vs asset-rumore a corr-zero) restano
come CONTESTO — mostrano che un low-corr "aggiunge" ~+0.03 per matematica, vero per sleeve buoni e
cattivi, quindi non possono essere IL gate; l'edge in-sample sì.
3. **hedge vs alpha** (`is_hedge`): `corr(Sharpe-TP01, uplift annuo)` molto negativa + paga solo
quando TP01 è giù → HEDGE, non alpha.
Verdetti nuovi **HEDGE** e **NOISE**; `earns_slot` ora pretende ADDS + robust_oos + has_insample_edge
+ not is_hedge. **Sull'onda ortho lo scorer indurito ribalta 17/18 "ADDS" → 1** (`dvol_spread`, unico
con edge in-sample reale 0.57; gli altri 16 → NOISE/HEDGE). Controllo: un sleeve sintetico Sharpe~1.3
scorrelato resta **ADDS** (non rigetta i diversificatori veri — XS01-like). La verifica avversariale
di 3 giorni è ora una chiamata di funzione.
@@ -0,0 +1,68 @@
# PREVDAY block-bootstrap — coda-fortuna vs persistente (blocker #2/#3)
**Data:** 2026-06-21 (chiude la trilogia: fill-haircut → turnover/hedge → bootstrap)
**Script:** `scripts/research/intraday/prevday_bootstrap.py`
**Esito:** PREVDAY-full **non** è più coda-fortuna di TP01 e l'edge è **bootstrap-robusto** (full
99% / hold-out 93% dei resample con uplift>0). MA la gamba short (= tutto il valore) è
**tail-dipendente** (top-5 giorni = 130% del suo netto). PREVDAY = tail-hedge legittimo dal payoff
grumoso. Resta forward-monitor.
## Chiarimento di scope
Il "top-5 giorni = 76-83% del PnL" del diario intraday era sulle GAMBE REVERT del combo a 5 segnali
(vol_event/volume_spike/gap_fill), poi SCARTATE. Il sopravvissuto è PREVDAY (breakout-continuation).
Qui si testa PREVDAY STESSO — e la sua gamba SHORT, che (prevday_turnover) è l'intero valore di
portafoglio. Block bootstrap circolare (blocchi 20g, B=3000) per preservare autocorrelazione/regime.
## [A] Concentrazione del PnL nei top-K giorni
| serie | n | totRet | top5 | top10 | top20 | giorni→50% gain |
|-------|--:|-------:|-----:|------:|------:|----------------:|
| PREVDAY full | 2869 | +182% | 22% | 36% | 59% | 411 (14.3%) |
| **PREVDAY short-only** | 2869 | **+28%** | **130%** | 218% | 345% | 312 (10.9%) |
| PREVDAY long-only | 2869 | +154% | 18% | 30% | 49% | 287 (10.0%) |
| TP01 (riferimento) | 2657 | +116% | 19% | 33% | 55% | 213 (8.0%) |
- **PREVDAY-full NON è più coda-fortuna di TP01**: top5 22% vs 19%, e per il 50% del guadagno serve
*più* tempo (14.3% dei giorni vs 8.0% → più distribuito). Il tail-luck del diario era sulle gambe
revert scartate, non su PREVDAY.
- **Gamba short tail-dipendente:** top5 = **130% del netto** → togliendo i 5 giorni migliori la short
va in perdita (gli altri 2864 giorni nettano 8%). Sono i giorni-crash dove la short paga.
## [B] Circular block bootstrap (20g, B=3000)
| campione | PREVDAY Sharpe (mediana [5°,95°], %>0) | blend 80/20 uplift (mediana [5°,95°], %>0, %>+0.10) |
|----------|----------------------------------------|------------------------------------------------------|
| full (2018-08→2026-06) | +1.24 [+0.64,+1.80] 100% | +0.28 [+0.09,+0.47] 99% / 93% |
| hold-out (2025+) | +1.27 [0.01,+2.46] 95% | +0.53 [0.05,+1.21] 93% / 88% |
| short-only hold-out | +1.12 [0.32,+2.41] 90% | +0.53 [0.08,+1.31] 92% / 87% |
- **Full sample: edge robustissimo** — 99% dei resample dà uplift>0 (mediana +0.28). Non è "un blocco
fortunato".
- **Hold-out: regge con coda più larga** (5° pctl appena negativo: hold-out corto ~536g + short
tail-dipendente), ma 93% dei resample >0, 88% >+0.10.
## Verdetto blocker #2/#3
- **#3 tail-luck — DECLASSATO per PREVDAY-full, CONFERMATO per la gamba short.** La strategia intera
non è più concentrata di TP01 (che già deployamo); il motore di valore (la short) sì: vive su <10
giorni-crash/anno. Bootstrap-robusto (non un singolo blocco), ma il forward sarà GRUMOSO, non un
liscio +0.56/periodo.
- **#2 null-corr-zero — RIDIMENSIONATO.** L'uplift è genuinamente positivo (93-99% dei resample), non
rumore; il punto era di *efficienza relativa* (rende meno di un ipotetico asset perfettamente
scorrelato), non di esistenza dell'edge.
## Sintesi della trilogia (fill-haircut + turnover/hedge + bootstrap)
PREVDAY, dopo tre attacchi avversariali:
1. **Eseguibile alla taglia reale** ($600): haircut di fill +0.01 (blocker #4 smontato).
2. **Già a turnover efficiente**: ridurlo erode l'edge; nessuna ottimizzazione (config congelata).
3. **È un HEDGE, non alpha**: tutto il valore è la gamba short → tail-hedge di regime-down, additivo
alla flat-stance di TP01 (blocker #1 inchiodato).
4. **Edge bootstrap-robusto** ma **payoff grumoso** (il valore è in pochi giorni-crash) (blocker #3
declassato sul full, confermato sulla short; #2 ridimensionato).
**Candidato tail-hedge legittimo**, non sleeve-alpha. Resta in FORWARD-MONITOR: la domanda forward
non è più "è eseguibile / è overfit", ma **"la gamba short continua a pagare nei prossimi crash fuori
da 2022 e 2025-26?"**. Se sì → si valuta come overlay di tail-hedge (peso piccolo, atteso payoff
lumpy); se no → era beta-corto del regime down 2025-26.
@@ -0,0 +1,67 @@
# PREVDAY fill-haircut a basso capitale — il blocker d'esecuzione è BENIGNO (1/4 smontato)
**Data:** 2026-06-21 (follow-up di `2026-06-21-intraday-microstructure.md`)
**Script:** `scripts/research/intraday/fill_haircut.py`
**Esito:** l'haircut del fill reale a $600 è **+0.01 Sharpe** (trascurabile). Lo scettico
d'esecuzione (blocker #4) è **benigno**. Gli altri 3 blocker (hedge / null-corr-zero / tail-luck)
restano → PREVDAY resta in **forward-monitor, non deploy**.
## Domanda
Lo scettico d'esecuzione dell'onda intraday aveva segnalato: il vol-target di PREVDAY fa ~8500
ribilanciamenti/anno per gamba, 97-98% < $1 di nozionale a $600; a quel capitale (min_order $5) NON
puoi piazzarli, quindi il libro MODELED (ribilanciamento continuo, frictionless) è una finzione e lo
Sharpe modellato è gonfiato. Il forward-monitor traccia MODELED-$2000 vs REAL-$600 per misurarlo nei
mesi a venire — qui lo stimiamo SUBITO su tutto lo storico, replicando la STESSA logica dei due libri
di `paper_prevday.py` ma sull'intero path 1h (2019-03 → 2026-06, 63.732 barre).
Due libri identici tranne il fill:
- **MODELED**: ribilancia ad ogni barra (fee proporzionale su ogni |Δ|).
- **REAL-$C**: salta i ribilanciamenti con nozionale `|Δpos|·leg_cap < $5` (posizione stale →
tracking error, ma niente fee sui trade infinitesimi). Sweep C ∈ {600, 2000, 20000}.
## Risultati
| libro | FULL Sh | HOLD Sh | CAGR | DD | rebal/yr | skip% | fee-drag/yr |
|-------|---------|---------|------|----|---------:|------:|------------:|
| MODELED ($∞) | +1.23 | +1.27 | +24.3% | 27% | 17.484 | 0.0% | 2.49% |
| REAL-$20k | +1.23 | +1.27 | +24.4% | 27% | 3.747 | 78.6% | 2.47% |
| REAL-$2000 | +1.23 | +1.27 | +24.4% | 27% | 677 | 96.1% | 2.42% |
| REAL-$600 | +1.22 | +1.26 | +24.2% | 27% | 277 | 98.4% | 2.39% |
**HAIRCUT $600 (MODELED REAL): FULL Sharpe +0.01, HOLD-OUT +0.01.**
Domanda-soldi (l'uplift del blend regge col fill reale?):
| PV | w | FULL (uplift) | HOLD (uplift) |
|----|---|---------------|---------------|
| MODELED | 20% | 1.58 (+0.28) | 0.86 (+0.56) |
| MODELED | 30% | 1.65 (+0.36) | 1.08 (+0.78) |
| **REAL-$600** | 20% | 1.58 (+0.28) | 0.86 (**+0.55**) |
| **REAL-$600** | 30% | 1.65 (+0.35) | 1.08 (**+0.77**) |
(TP01 solo: FULL +1.30, HOLD +0.31.) L'uplift hold-out sopravvive **quasi intatto**.
## Lettura
Saltare il **98.4%** dei micro-ribilanciamenti a $600 non costa quasi nulla perché quei trade sono
*individualmente infinitesimi*: sia la fee risparmiata sia il tracking-error introdotto sono
trascurabili. Il PnL è dominato dai ~50 flip di direzione/anno + la deriva lenta del vol-target, che
il libro $600 cattura comunque sui movimenti grandi (la fee-drag passa solo da 2.49% a 2.39%). La
"finzione della fee sub-dollaro" è quindi **benigna**: non gonfia lo Sharpe modellato (MODELED e
REAL-$600 coincidono a ±0.01). NB: lo Sharpe **non si degrada** scendendo di capitale → l'edge
modellato di PREVDAY è eseguibile alla taglia reale; il blocker era altrove.
## Conseguenza sul verdetto
Dei 4 blocker che tenevano PREVDAY fuori dal deploy, il **#4 (fill a basso capitale) è SMONTATO**.
Restano in piedi i 3 strutturali (dall'onda intraday, non rivalutati qui):
1. **hedge-shaped** — l'uplift viene dai regimi TP01-down (uplift +0.79 TP01-down vs +0.20 TP01-up);
2. **fallisce il null a corr-zero** — uplift pre-2025 al 20-24° pctl del null di un asset random
scorrelato (aggiunge MENO del rumore);
3. **tail-luck** — top-5 giorni = 76-83% del PnL delle gambe revert, <10 eventi/anno.
PREVDAY resta il lead **più solido sull'esecuzione** di tutta la ricerca post-reset (il dubbio più
"fisico" è caduto), ma **forward-monitor, non deploy**, finché il track record forward non scioglie
hedge/coda/null. Lezione harness: `eval_weights_smallcap` (il gate min-order) va sempre eseguito
PRIMA di scartare un lead per "fill irreale" — qui avrebbe evitato di sopravvalutare il blocker #4.
@@ -0,0 +1,68 @@
# PREVDAY come overlay di tail-hedge sul portafoglio — simulazione d'impatto (NON deploy)
**Data:** 2026-06-21 (segue la trilogia fill-haircut / turnover-hedge / bootstrap)
**Script:** `scripts/portfolio/prevday_overlay.py`
**Esito:** a peso 10%, PREVDAY taglia il maxDD FULL del portafoglio **14.3% → 9.9% (31%)** e alza
l'hold-out Sharpe **1.66 → 1.97 (+0.31)**. 10% è vicino all'ottimo di DD. MA è tutto IN-SAMPLE: il
prize si materializza solo SE l'edge di PREVDAY persiste forward. PREVDAY resta FORWARD-MONITOR.
## Setup
Simulazione che NON tocca il registry di produzione: prende il portafoglio attivo (TP01 55% + XS01
25% + VRP01 20%), riscala i tre sleeve a (1W) mantenendone le proporzioni, e aggiunge PREVDAY a
peso W. Sweep W ∈ {0,5,10,15,20%}. PREVDAY = libro 1h breakout-continuation, parametri congelati,
50/50 BTC+ETH, fee 0.10% RT. Outer-join del portafoglio: PREVDAY dal 2018, VRP01 dal 2021, XS01 dal
2024 → nel 2019-20 PREVDAY pesa di fatto >W (solo TP01 accanto); nell'hold-out 2025+ (tutti e 4
attivi) pesa esattamente ~W → **l'HOLD-OUT è il confronto pulito a "10%"**.
## Sweep peso overlay
| peso PREVDAY | FULL Sharpe | FULL DD | HOLD Sharpe | HOLD DD | HOLD ret |
|--------------|------------:|--------:|------------:|--------:|---------:|
| BASELINE (55/25/20) | 1.68 | 14.3% | 1.66 | 3.4% | +16.7% |
| 5% | 1.80 | 11.1% | 1.83 | 3.3% | +17.8% |
| **10%** | **1.88** | **9.9%** | **1.97** | 3.3% | **+19.0%** |
| 15% | 1.93 | 10.3% | 2.06 | 3.3% | +20.2% |
| 20% | 1.95 | 10.6% | 2.09 | 3.4% | +21.4% |
(PREVDAY standalone: FULL Sh 1.23 / DD 26.7%; HOLD Sh 1.28 / DD 10.8%.)
## Lettura a 10%
- **FULL: Sharpe +0.20 (1.68→1.88), maxDD 14.3%→9.9% (4.4pp ≈ 31%).** Comportamento da tail-hedge:
la gamba short ammortizza i crash storici (2019-21, 2022).
- **HOLD-OUT: Sharpe +0.31 (1.66→1.97), ret +16.7%→+19.0%, DD 3.4%→3.3% (già bassissimo).** Nel
regime recente il beneficio è rendimento/Sharpe, non taglio DD.
- **10% ≈ ottimo di DD.** Oltre, lo Sharpe sale ancora (1.93→1.95) ma il maxDD FULL smette di
scendere (10.3→10.6%): stai solo aggiungendo rischio direzionale short. Argomento per ~10% in
chiave hedge (massimizza il taglio-coda per unità di rischio aggiunto).
## Per anno (baseline → overlay 10%)
| anno | ret | DD |
|------|-----|----|
| 2019 | +11.3 → +15.2 | 10.3 → 8.2 |
| 2020 | +51.1 → +53.1 | 8.4 → 6.3 |
| 2021 | +32.5 → +28.3 | 5.2 → 4.3 |
| 2022 | 3.0 → 1.6 | 3.7 → 3.0 |
| 2023 | +11.2 → +11.4 | 9.2 → 9.9 |
| 2024 | +24.4 → +25.7 | 3.9 → 3.4 |
| 2025 | +12.0 → +12.0 | 3.4 → 3.3 |
| 2026 | +4.2 → +6.2 | 2.6 → 2.2 |
Migliora o pareggia quasi ovunque; costa solo nel toro 2021 (premio d'assicurazione atteso per un
hedge) e leggermente sul DD 2023; paga nel bear 2022 e nel 2026.
## Verdetto
L'overlay 10% è **attraente in simulazione** — taglia il drawdown FULL di ~31% e alza l'hold-out
Sharpe +0.31, con 10% vicino all'ottimo di DD. Ma:
1. **È in-sample.** I guadagni assumono che l'edge di PREVDAY persista — il forward-monitor esiste
proprio per verificarlo. Questa simulazione quantifica il PRIZE, non lo prova.
2. **Outer-join:** il taglio-DD storico è gonfiato dal peso effettivo >10% nel 2019-20; il read
pulito a 10% è l'hold-out (prize = Sharpe +0.31).
3. Incidentale: il 3-way TP01+XS01+VRP01 baseline qui fa FULL 1.68 / HOLD 1.66.
**Azione: nessuna.** PREVDAY resta FORWARD-MONITOR (registry di produzione invariato). Quando il
track record forward avrà ~2-3 mesi, ri-valutare l'overlay 10% con la stessa metrica (taglio-DD +
hold-out Sharpe) su dati VERAMENTE fuori campione. Lo script è il riferimento per quel confronto.
@@ -0,0 +1,64 @@
# PREVDAY — la fee viene dai FLIP (no free lunch sul turnover) + è un HEDGE, non alpha
**Data:** 2026-06-21 (follow-up di `2026-06-21-prevday-fill-haircut.md`)
**Script:** `scripts/research/intraday/prevday_turnover.py`
**Esito:** (1) ridurre il turnover di PREVDAY erode l'edge — la config congelata è già efficiente.
(2) Il test long-only inchioda il blocker #1: **tutto il valore di portafoglio è la gamba SHORT**
PREVDAY è un **hedge di regime-down**, non alpha. Resta forward-monitor.
## Premessa (da fill_haircut)
Il libro REAL-$600 salta il 98.4% dei ribilanciamenti del vol-target e la fee-drag scende solo
2.49% → 2.39%/anno. Quindi la fee (~2.6%/anno) NON viene dal churn sub-dollaro ma dai **~70 flip di
direzione/anno**. Un deadband d'esecuzione è inutile; l'unica leva è ridurre i flip a LIVELLO DI
SEGNALE. Qui sweep delle leve (buffer, anchor, min-hold) + long-only vs long-short. Libro MODELED
(l'haircut di fill è +0.01, irrilevante). Metrica che conta = **uplift hold-out del blend 80/20**.
## (1) Turnover-reduction — no free lunch
| config | flip/yr | fee/yr | FULL Sh | HOLD Sh | DD | corrTP | blend HOLD upl |
|--------|--------:|-------:|--------:|--------:|---:|-------:|---------------:|
| **BASE** (anchor=1, k=0.30, LS) | 70 | 2.59% | +1.23 | +1.27 | 27% | +0.15 | **+0.56** |
| k=0.50 | 48 | 1.86% | +1.23 | +0.99 | 15% | +0.20 | +0.40 |
| k=0.75 | 32 | 1.31% | +1.06 | +0.13 | 16% | +0.27 | +0.00 |
| k=1.00 | 23 | 1.01% | +0.88 | +0.72 | 22% | +0.36 | +0.22 |
| anchor=2 | 39 | 1.55% | +0.89 | +0.54 | 22% | +0.25 | +0.20 |
| anchor=3 | 27 | 1.14% | +0.67 | 0.18 | 22% | +0.29 | 0.12 |
| anchor=5 | 15 | 0.75% | +1.15 | +0.70 | 19% | +0.41 | +0.25 |
| min_hold=24h | 70 | 2.59% | +1.22 | +1.37 | 32% | +0.15 | **+0.60** |
| min_hold=72h | 65 | 2.39% | +0.86 | +0.67 | 33% | +0.12 | +0.27 |
| combo-LT (k.75+anc2+24h) | 16 | 0.79% | +0.79 | +0.69 | 20% | +0.34 | +0.24 |
- **Allargare buffer/anchor taglia fee e turnover ma l'uplift cala monotonicamente** (k: 0.56→0.40→
0.00). Anchor multi-giorno tutto peggio → conferma il "anchor=1 only" del diario. I flip SONO
l'edge: meno flip = meno edge.
- **min_hold=24h** è l'unico ritocco "quasi gratis" (uplift +0.56→+0.60 a parità di fee) ma
**peggiora il DD 27%→−32%** → non vale cambiare una strategia congelata in forward-monitor.
- **Verdetto: la config base è già sulla frontiera efficiente turnover↔edge. Si lascia congelata.**
## (2) Long-only vs long-short — il blocker #1 inchiodato
| | FULL Sh | HOLD Sh | corrTP | blend HOLD upl | fee/yr |
|--|--------:|--------:|-------:|---------------:|-------:|
| **long-only** (no short) | **+1.55** | +0.52 | **+0.64** | **+0.09** | 1.30% |
| long-short (BASE) | +1.23 | +1.27 | +0.15 | +0.56 | 2.59% |
La versione **long-only ha Sharpe standalone più ALTO** (1.55 vs 1.23) ma è **correlata +0.64 a TP01
e non aggiunge quasi nulla al blend** (+0.09). **Tutto il valore di portafoglio viene dalla gamba
SHORT:** la short *abbassa* lo Sharpe standalone (shortare crypto nel toro 2019-24 perde) ma fornisce
**tutta** la decorrelazione (corrTP 0.64→0.15) e l'uplift hold-out (0.09→0.56).
**PREVDAY non è alpha: è strutturalmente un HEDGE di crash/regime-down.** Costa nel toro, paga
nell'orso (2022, 2025-26 down/chop). È additivo a TP01, che va *flat* nel risk-off ma non *short*.
Questo conferma e affina il blocker #1 dell'onda intraday ("l'uplift viene dai regimi TP01-down"):
non è solo conditional sui regimi down, è **interamente la gamba short** = una scommessa direzionale
che i ribassi continuino.
## Conseguenza sul verdetto
- Niente da ottimizzare: la config congelata è già efficiente; nessun cambio.
- **Riframing utile:** se PREVDAY un giorno avrà un ruolo, è come **overlay di tail-hedge** (non
sleeve-alpha), additivo alla difensività di TP01. Ma resta soggetto agli altri due blocker
(fallisce il null a corr-zero; tail-luck: top-5 giorni = 76-83% del PnL delle gambe revert).
- **Forward-monitor invariato.** Il test forward decisivo: la gamba short continua a pagare fuori da
2022 e 2025-26? Se sì → candidato tail-hedge; se no → era regime-luck.
@@ -0,0 +1,62 @@
# 2026-06-22 — Sweep 65-agenti: crypto -> mercati IB (mercati × timing × anni)
## Obiettivo (goal utente)
Usare >=50 agenti per prendere l'anticipazione crypto->equity e trovare la MIGLIORE soluzione,
provando diversi mercati e timing, su piu' anni.
## Setup
- **Dati**: universo IB esteso a **26 ETF certificati** (azioni US/settori/intl/bond/credito/oro/
commodity/REIT), cache su disco (`fetch_ib_equities.py` + BROAD2). Crypto BTC/ETH 1h (Deribit).
- **Harness onesto** (`crypto_lead_harness.py`): per ogni sessione equity, lead = crypto nella
finestra equity-CHIUSO [P 21:00 -> D 13:00 UTC] (overnight; il weekend e' il caso lungo). Predice
gap/intraday/full. Metriche: corr, **t incrementale vs sessione equity precedente**, Sharpe
eseguibile (sign(lead)*predict, net costi) FULL/IS/OOS, **hit per-anno**.
- **Workflow** (`wf_crypto_lead.js`): grid 416 config (2 lead × 26 mercati × 2 giorni × 2 predict ×
2 finestre). **52 agenti sweep** -> **12 agenti verifica avversariale** (stress 10bps + OOS 2024+ +
multi-anno) -> **1 sintesi**. Totale **65 agenti**, 1.7M token.
## Risultato
### Fenomeno fortissimo: crypto overnight -> GAP di apertura equity
Cluster coerente in cima, TUTTI predict=gap/overnight, su ogni target risk-on:
| lead->target | t-incr | Sh OOS@4bps | @10bps | OOS-recente | anni+ |
|---|---|---|---|---|---|
| ETH->IWM gap | 17.1 | 2.49 | 1.96 | 2.41 | 7/8 |
| ETH->QQQ gap | 17.9 | 2.36 | 1.83 | 2.31 | 7/8 |
| ETH->XLK gap | 17.4 | 2.40 | 1.93 | 2.30 | 7/8 |
| **BTC->QQQ gap** | 15.0 | 2.31 | 1.78 | 2.16 | **9/9** |
| BTC->SPY gap | 14.4 | 2.14 | 1.69(lf) | 2.03 | 9/9 |
Statisticamente schiacciante (t 14-18, sopra Bonferroni su 416 test), regge stress costi e OOS
recente, **positivo 8-9 anni su 8-9**.
### Ma DUE killer (i verificatori avversariali concordi)
1. **NON tradabile via ETF**: il gap e' gia' prezzato all'open dell'ETF -> serve un FUTURE indice
tenuto overnight (MNQ/MES/M2K). A $0.5-2k il margin overnight di anche un micro consuma il
capitale e rischia la liquidazione su un gap avverso -> **fuori portata per costruzione**.
2. **E' RISK-BETA, non alpha**: la finestra-lead crypto e' quasi CONTEMPORANEA al gap (stesso shock
macro overnight, equity chiuso). t enorme = co-movimento risk-on/off, non ETH/BTC che *anticipa*.
Firma: la forza e' negli anni alta-vol (2022 hit 0.71-0.75), piatta negli anni calmi (2019/21/23).
corr ~0.37 -> beta implicito ~37%, alpha residuo piccolo.
### L'unico tradabile via ETF e' troppo debole
ETH->XLE intraday 6h (compri XLE al day-open, chiudi +6h): Sh OOS 0.48@4bps **-> 0.15@10bps** (annuo
4.1%->1.0%), t-incr 2.38 **sotto Bonferroni** (~3.5 su 416 test). Edge netto onesto ~ZERO.
## Verdetto (sintesi multi-agente)
**Nessun edge proprietario deployabile a basso capitale.** Il fenomeno crypto->equity-overnight e'
statisticamente reale e robustissimo su 9 anni, ma e' (a) risk-beta condiviso, non anticipazione
sfruttabile, e (b) catturabile solo con futures overnight, fuori dal nostro capitale. L'unica
versione ETF-eseguibile e' dentro il rumore da multiple-testing. Coerente col soffitto del progetto:
"niente di nuovo regge" alla verifica onesta.
**Migliore soluzione (come FENOMENO da forward-monitor, non deploy):** BTC->QQQ gap overnight — la
storia piu' lunga (9/9 anni), lead noto prima dell'open. Da monitorare; deployabile solo con capitale
~>$20-30k su micro-futures indice e con i costi notturni modellati.
## Lezione
Anche con 65 agenti e una ricerca esaustiva su mercati/timing/anni, la disciplina onesta
(tradabilita' al capitale reale + multiple-testing + beta-vs-alpha) riduce un "Sharpe 2.5 su 9 anni"
a un non-edge per noi. Il valore della ricerca: aver QUANTIFICATO e CLASSIFICATO il fenomeno
(risk-beta overnight) invece di scambiarlo per alpha.
Artefatti: `crypto_lead_harness.py`, `wf_crypto_lead.js`.
@@ -0,0 +1,53 @@
# 2026-06-22 — Crypto × mercati IB: correlazioni e ANTICIPAZIONI (lead-lag)
## Obiettivo
Cercare correlazioni e soprattutto ANTICIPAZIONI tra crypto e mercati IB: un mercato fa capire
l'andamento dell'altro? Dati: cache su disco (BTC/ETH Deribit 1h->1d UTC; ETF eq_* con OPEN). Nessun
IB online. Disciplina: attenzione ai tranelli di timing daily (crypto chiude 00:00 UTC, US equity
21:00 -> lag-0 contaminato), test del segno + OOS + multiple-testing.
Script: `crypto_macro_leadlag.py`, `crypto_weekend_signal.py`.
## (1) Correlazione contemporanea
Crypto = asset RISK-ON: corr BTC/ETH ~ **+0.32/0.37** con SPY/QQQ/IWM, **+0.25/0.28** con HYG
(credito), **+0.13** GLD, **~-0.02** TLT (bond). Atteso.
## (2) Lead-lag giornaliero: NIENTE
corr(BTC_{t-k}, ETF_t) ha picco a **k=0** (~0.32) e crolla a rumore (±0.05) per |k|>=1. Al daily
**nessuno anticipa l'altro** (ne' crypto->equity ne' viceversa). Honest negative.
## (3) EFFETTO WEEKEND: anticipazione PULITA, significativa, OOS-robusta
La crypto si muove Sab+Dom (azionario chiuso) -> quel movimento e' info PRIOR al lunedi'.
- **Anticipa il GAP del lunedi'**: corr +0.22/+0.24 (SPY/QQQ/IWM/HYG), hit 59-62%, e **si RAFFORZA
OOS (2022+): +0.30/+0.36**. Coerente su 4 ETF (non cherry-pick).
- Intraday del lunedi' (open->close) piu' debole ma presente (corr 0.10-0.15, OOS 0.18-0.22).
### Validazione avversariale
- **(A) INCREMENTALE vs venerdi'**: regressione `Mon ~ weekend_crypto + friday_eq`. Coeff weekend
crypto significativo ovunque (QQQ gap **t=+4.7**, intr t=+2.9; SPY +4.4/+2.0; IWM +4.7/+2.7);
friday_eq NON significativo. -> e' info CRYPTO-SPECIFICA del weekend, non momentum equity.
- **(B) TRADABILE** (osservo weekend crypto Dom 24:00, entro Monday OPEN, esco CLOSE, net 4bps):
| ETF | hit | Sharpe FULL / IS / OOS22+ | long-flat OOS | ann |
|---|---|---|---|---|
| QQQ | 60% | 1.46 / 1.61 / 1.33 | **1.91** | ~+9-11% |
| SPY | 60% | 0.96 / 0.91 / 1.01 | 1.70 | ~+5% |
| IWM | 56% | 0.89 / 0.73 / 1.04 | 1.07 | ~+6% |
## Verdetto
**Trovata UNA anticipazione reale**: il weekend crypto anticipa il lunedi' azionario (massimo su QQQ,
risk-on/tech). Significativa (t>4 sul gap), incrementale al venerdi', tradabile net costi, **regge e
si rafforza OOS**, coerente su piu' ETF. Meccanismo economico sensato: crypto = proxy 24/7 del
risk-sentiment; nel weekend l'equity e' chiuso e lunedi' "recupera" la direzione crypto.
### Caveat onesti
- **Capacita' bassa**: ~52 lunedi'/anno, intraday -> ~+9%/yr sul capitale impiegato il lunedi', non
una macchina da compounding. E' un segnale TATTICO, non un cornerstone.
- Il GAP (t=4.7) e' piu' forte dell'intraday (t=2.9) ma per catturarlo serve entrare PRIMA del Monday
open -> via **futures indice IB (MNQ/MES, aperti la domenica sera)**: enhancement eseguibile da
validare (cattura gap+sessione).
- Multiple-testing 3 ETF x 2 target: ma TUTTI significativi e coerenti -> effetto ampio, non fortuna.
- Niente IB online qui (cache); per il deploy servirebbe il feed crypto live la domenica sera.
## Prossimo (se si procede)
Validare la variante FUTURES (MNQ domenica sera -> cattura il gap del lunedi') e il sizing a basso
capitale; eventualmente paper-trade. E' la prima ANTICIPAZIONE cross-mercato trovata: crypto come
lead di sentiment sul lunedi' equity.
@@ -0,0 +1,40 @@
# 2026-06-22 — Combo DEPLOYABLE: TP01 (Deribit) + GTAA (IB)
## Perche'
Il combo crypto-pieno (TP01+XS01+VRP01)+GTAA diversificava (Sharpe 1.81), ma XS01/VRP01 sono
STAT-MODE (non eseguibili a $600). Validazione del combo ONESTO/eseguibile: solo le gambe deployable
a basso capitale — TP01 (gia' armato live su Deribit) + GTAA vt12 (eseguibile su IB, frazioni,
switch mensile). `eq_tp01_gtaa_combo.py`. TP01 compoundato sul calendario giorni-di-borsa.
## Risultati (finestra comune 2019-03 .. 2026-06, ~7y)
| | Sharpe | CAGR | volAnn | maxDD |
|---|---|---|---|---|
| TP01 (crypto, Deribit) | 1.25 | 16.4% | 12.9% | 14% |
| GTAA vt12 (equity, IB) | 1.12 | 6.0% | 5.3% | 8% |
| **blend 50/50** | **1.48** | 11.3% | 7.5% | **8%** |
| blend 40/60 (best cap-mix) | 1.52 | 10.2% | 6.6% | 8% |
| risk-parity (29c/71e) | 1.52 | 9.1% | 5.9% | 8% |
**corr TP01<->GTAA = +0.21**. Il blend (1.48-1.52) batte entrambe le gambe (best solo 1.25),
maxDD 14%->8%. **DIVERSIFICA anche da deployable.**
## Caveat onesti
- Per-anno 50/50: 2019 2.11, 2020 2.51, 2021 1.66, **2022 -2.64**, 2023 1.40, 2024 1.73, 2025 0.98,
2026 0.94. Anni boom iniziali gonfiano lo Sharpe assoluto; il **2022 e' negativo** (trend whipsaw
su entrambe le gambe nel bear). Recenti ~0.95. -> il numero robusto e' il GUADAGNO da
diversificazione (+0.27 Sharpe del blend vs solo), non il livello assoluto.
- **Costo deployability**: crypto-pieno+GTAA = 1.81 vs deployable = 1.48. I ~0.33 di Sharpe persi sono
cio' che XS01/VRP01 darebbero se eseguibili (servirebbe ~20k).
- **Cross-venue** Deribit+IB: due conti, capitale split. Entrambe switch mensile/basso turnover,
frazionabili a $0.5-2k.
## Verdetto
Combo deployable VALIDO: due trend difensivi scorrelati (corr 0.21) su mercati diversi -> Sharpe
~1.5 / maxDD ~8%, meglio di ciascuna gamba. E' il candidato concreto per un paper-trade cross-venue.
NON risolve EUR50/g (resta capitale), ma e' la migliore configurazione rischio-aggiustata
EFFETTIVAMENTE eseguibile trovata finora. Lezione cross-mercato confermata: il salto di qualita' non
e' un nuovo alpha ma un SECONDO mercato scorrelato.
## Prossimo (se si procede)
Paper-trade della gamba GTAA su IB (forward-only, come paper_trend per TP01), per validare
l'esecuzione cross-venue a rischio zero prima di qualunque capitale reale.
@@ -0,0 +1,57 @@
# 2026-06-22 — EQ-GTAA01 (trend multi-asset) + COMBO cross-mercato equity×crypto
## (1) EQ-GTAA01 — trend difensivo multi-asset (GTAA)
EQ-TREND01 (trend su SPY) taglia il DD. Diversificare le SORGENTI di trend (azioni US/tech/small +
bond + oro + high-yield) migliora il rischio-aggiustato. `eq_gtaa_trend.py`: ogni asset gestito col
proprio trend long-flat (TSMOM multi-orizzonte), equal-weight tra gli asset disponibili (outer-join,
cash dove off/assente). Universo SPY/QQQ/IWM/TLT/GLD/HYG. Causale, netto fee, OOS 2015+.
| strategia | CAGR | Sharpe (pre15/OOS) | maxDD | corr SPY |
|---|---|---|---|---|
| SPY buy&hold | 9.7% | 0.58 (0.45/0.82) | 55% | — |
| EW statico (no trend) | 9.4% | 0.59 | 62% | 0.89 |
| SPY-trend mono | 5.5% | 0.56 (/0.78) | 30% | 0.72 |
| **GTAA lf vt12%** | 3.8% | **0.64** (0.53/**0.89**) | **15%** | **0.64** |
| GTAA vt12 (6-asset, 2016+) | 5.6% | **1.08** | **8%** | 0.60 |
DD nei bear (GTAA vs SPY): dot-com 32%/49% · GFC **14%/55%** · COVID **10%/34%** · 2022 11%/24%.
Marginale vs SPY: corr 0.64; 50/50 uplift +0.041 FULL / **+0.086 OOS** (meglio del mono-SPY). Plateau
stabile (Sh 0.55-0.61, DD 25-35%). **Migliore sleeve equity**: Sharpe più alto, maxDD bassissimo
(8-15%), corr SPY più bassa (0.64) = diversificatore migliore. Tradeoff: CAGR molto più basso
(fortemente difensiva). Caveat: la finestra 6-asset (Sh 1.08) è tutta OOS ma un solo regime (toro).
## (2) COMBO cross-mercato — equity-trend × crypto
La via che alza il Sharpe COMPLESSIVO senza nuovo alpha: combinare due book scorrelati.
`eq_crypto_combo.py`: crypto = portafoglio attivo TP01+XS01+VRP01 (`StrategyPortfolio.combined_daily`,
rinormalizzato); equity = GTAA lf vt12%. Crypto compoundato sul calendario giorni-di-borsa (cattura
i weekend). Finestra comune = era crypto (2019-03 .. 2026-06, 1827 giorni di borsa).
| | Sharpe | CAGR | volAnn | maxDD |
|---|---|---|---|---|
| crypto TP01+XS01+VRP01 | 1.60 | 18.7% | 11.1% | 14% |
| equity GTAA vt12 | 1.12 | 6.0% | 5.3% | 8% |
| **blend 50/50** | **1.81** | 12.4% | 6.6% | **7%** |
| risk-parity (32c/68e) | 1.78 | 10.1% | 5.5% | 8% |
**Correlazione crypto↔equity = +0.167** (bassissima). Il blend 50/50 fa **Sharpe 1.81 > di ciascuno**
(crypto 1.60, equity 1.12), **maxDD dimezzato 14%→7%**. VERDETTO: DIVERSIFICA (blend > miglior solo
di +0.21 Sharpe). È il guadagno STRUTTURALE: due fonti di rischio scorrelate alzano il Sharpe
complessivo senza cercare un nuovo edge.
### Caveat onesti
- **Finestra crypto corta (~7y) e favorevole**: il crypto Sharpe 1.60 e' alto (regime toro + XS01/VRP01
STAT-MODE a storia corta). Gli SHARPE ASSOLUTI sono ottimistici. Ma il PUNTO della diversificazione
(corr 0.17, blend > solo, DD dimezzato) è robusto al livello assoluto.
- **Cross-venue**: crypto su Deribit, equity su IB → due conti, due percorsi d'esecuzione. A $0.5-2k
totali, ogni sleeve è minuscola. La parte equity (GTAA) e la TP01 sono entrambe eseguibili a basso
capitale; XS01/VRP01 restano STAT-MODE (il blend "reale" deployable è ~TP01 + GTAA).
## Lettura strategica
Il fronte equity da' due cose: (a) una sleeve difensiva robusta (GTAA, maxDD ~10%), (b) — piu'
importante — un DIVERSIFICATORE quasi-scorrelato al crypto che alza il Sharpe del portafoglio
complessivo da ~1.6 a ~1.8. Non risolve €50/g (resta capitale), ma e' il primo miglioramento
STRUTTURALE del rischio-aggiustato complessivo trovato in tutta la ricerca post-reset, ed e' del tipo
giusto (diversificazione vera, non alpha fittizio). Prossimo: validare il combo deployable TP01+GTAA
(solo le due gambe eseguibili), e valutare l'operativita' cross-venue.
@@ -0,0 +1,45 @@
# 2026-06-22 — Fronte EQUITY aperto + EQ-MOM01 (momentum settoriale): NON batte SPY
## Apertura fronte (branch research/equities-ib)
Le 4 ondate crypto hanno esaurito gli angoli su BTC/ETH (soffitto ~1.3). L'unico modo di superarlo è
un **mercato diverso**. Aperto il fronte azioni/ETF via IB (paper, `gnzsnz/ib-gateway`, read-only).
**Dati certificati + cache su disco** (`fetch_ib_equities.py``data/raw/eq_*.parquet`, ADJUSTED_LAST
div+split, gitignored = cache locale; loader `eqlib.py` con lru_cache → ricerca legge da disco, MAI
da IB). Universo: 9 SPDR settoriali classici dal **1998 (27.5y)** + XLRE(2015)/XLC(2018) + SPY(1996,
30y)/QQQ/IWM/GLD/HYG/TLT. Tutti integri (monotoni, no dup, no spike>50%, 0 gap lunghi).
NB bug timestamp risolto: `pd.Timestamp` a risoluzione µs → salvati in secondi, corretti a ms.
## EQ-MOM01 — momentum cross-sectional settoriale
Costruzione causale (`eq_sector_momentum.py`): ogni 21g, momentum = blend lookback [63,126,252]g con
skip-21 (12-1 classico), z-score cross-sectional. long-only top-k (full-invested, confronto
like-for-like con SPY) e long-short (dollar-neutral, test alpha puro). Netto fee, hold-out OOS 2015+.
### Risultati (9 settori, 1998-2026)
| strategia | CAGR | Sharpe (pre15/OOS15+) | maxDD | corr SPY |
|---|---|---|---|---|
| **SPY buy&hold** | 8.2% | **0.51** (0.31/0.82) | 55% | — |
| EW 9 settori | 8.9% | 0.56 (0.44/0.76) | 53% | 0.96 |
| MOM long top-3 | 7.7% | 0.50 (0.32/0.76) | 47% | 0.85 |
| MOM long vol-target 15% | 7.3% | 0.52 | 39% | 0.75 |
| **MOM long-short top-3** | 0.9% | **0.08** (0.19/0.08) | 32% | 0.20 |
### Verdetto: NESSUN edge vs SPY
- **Long-short Sharpe 0.08** → l'alpha cross-sectional di momentum settoriale è **morto** su 27 anni
(decadimento post-2000 noto in letteratura). Niente alpha market-neutral.
- **Long-only ≈ SPY**: corr 0.85, **uplift marginale ~0.00** (blend 75/25 +0.012 FULL / +0.001 OOS;
50/50 +0.015 / 0.010). È un SPY a beta più basso, non un edge. Plateau stabile ma sempre ~0.50
(vs SPY 0.51); sugli 11 settori (2018+) fa peggio (0.69 vs 0.82). Fee-robusto (ma niente da salvare).
- L'unico beneficio (maxDD 55%→39%) è del **vol-target**, non del momentum (lo daresti a SPY stesso).
## Lezione (coerente col progetto)
Il momentum **relative-value** è morto anche in equity, come nel crypto (ortho wave). Il baseline
equity da battere è SPY buy&hold (Sharpe ~0.51 full / 0.82 OOS), ostico come il toro crypto.
## Prossimo angolo plausibile (NON ancora testato)
L'analogo equity di TP01 (l'unica cosa che ha retto nel crypto = trend DIFENSIVO): **time-series
trend su SPY long-flat/long-bonds** — non per battere il CAGR ma per **tagliare il 55% di drawdown**
restando vicino al ritorno. È il punto dove vive il valore robusto in equity (e dove il cross-section
NON guarda). Da provare con lo stesso gauntlet: marginale vs SPY, OOS lungo, plateau.
@@ -0,0 +1,48 @@
# 2026-06-22 — EQ-TREND01: trend DIFENSIVO su SPY = edge difensivo REALE (analogo di TP01)
## Contesto
Il momentum cross-sectional settoriale è morto (EQ-MOM01: long-short Sharpe 0.08, long-only ≈ SPY).
Ma nel crypto l'unica cosa che ha retto NON era relative-value: era **TP01**, un trend DIFENSIVO che
taglia il drawdown. L'equity ha lo stesso buco: SPY buy&hold Sharpe ~0.54 ma maxDD **55%**.
## Costruzione (causale, stile TP01)
`eq_spy_trend.py`. TSMOM multi-orizzonte [21,63,126,252]g, target = frazione di orizzonti in
trend-up (allocazione graduale 0..1), opz. vol-target. Posizione decisa a ≤i-1, tenuta da i. Netto
fee. Varianti: long-flat (cash in risk-off), long-bonds (TLT, solo 2016+), SMA-200 (Faber). Dati da
cache eqlib (ADJUSTED, nessun IB). Periodo 1997-2026, OOS 2015+.
## Risultati
| strategia | CAGR | Sharpe (pre15/OOS) | maxDD | in-mkt |
|---|---|---|---|---|
| SPY buy&hold | 9.0% | 0.54 (0.38/0.82) | 55% | 99% |
| **SMA-200 (Faber)** | 7.0% | **0.65** (0.52/0.88) | **29%** | 76% |
| TSMOM lf cap1.0 | 5.7% | 0.57 (0.44/0.78) | 30% | 92% |
| TSMOM lf vt15% | 5.7% | 0.62 (0.51/0.78) | **25%** | 92% |
**Drawdown nei bear (TSMOM vs SPY):** dot-com 26%/49% · GFC **19%/55%** · COVID 17%/34% · 2022 16%/24%.
**Plateau** (long-flat): ogni config Sharpe 0.56-0.65 (> SPY 0.54), maxDD 25-31% (~metà di SPY).
SMA-200 il più semplice E il migliore (Sh 0.65, OOS 0.88, DD 29%). **Fee-robusto** (Sh 0.48 a
0.10%/lato), basso turnover.
**Marginale vs SPY:** corr 0.73. blend 50/50 uplift +0.035 FULL / +0.031 OOS (modesto positivo);
100% trend uplift 0.012 / 0.041 (nel toro recente la difesa costa).
## Verdetto: edge DIFENSIVO reale (non alpha) — analogo di TP01
- ✅ Sharpe 0.54→0.62/0.65, **maxDD dimezzato** (55%→~27%, nei bear lenti più che dimezzato),
plateau robusto, fee-robusto, **eseguibile a $0.5-2k** (switch mensile SPY/cash).
- ⚠️ NON genera ritorno (CAGR 2/3pp): è risk-management, come TP01.
- ⚠️ I tagli grossi (dot-com/GFC) sono IN-SAMPLE; l'OOS 2015-26 è quasi tutto toro → lì ha seguito
SPY a beta minore (ma COVID, OOS, dimezzato). La difesa "serve" nei bear, rari nell'OOS.
- ⚠️ long-bonds (TLT) non convince (TLT distrutto 2022).
## Lettura strategica
Primo positivo del fronte equity, e dello stesso TIPO che ha retto nel crypto: trend difensivo, non
relative-value. Conferma la lezione cross-mercato: **il valore robusto è nel ridurre il rischio
(trend long-flat), non nel battere il buy&hold**. Da solo non risolve €50/g (problema di capitale).
## Prossimo angolo plausibile
**Trend multi-asset / GTAA** sull'universo ETF in cache (SPY/QQQ/IWM + TLT/GLD/HYG): un portafoglio
di trend long-flat su classi d'attivo diverse di solito batte il trend mono-SPY sul rischio-aggiustato
(diversificazione dei trend). + domanda cross-mercato: la sleeve equity-trend DIVERSIFICA il
portafoglio crypto (TP01+XS01+VRP01)? (esecuzione split Deribit+IB).
+96
View File
@@ -0,0 +1,96 @@
# 2026-06-22 — Funding-CARRY cross-sectional su Hyperliquid (FC01): LEAD fragile, NON regge
## Contesto
Onda "nuova ricerca mirata" (l'utente ha chiesto di cercare un angolo non coperto dalle due grandi
ondate — sweep 104-ipotesi e ortho relative-value, entrambe esaurite sul *prezzo* BTC/ETH). L'unico
meccanismo con una **fonte di ritorno diversa** non ancora testato su dati certi è il **carry da
funding**: incassare il cashflow dei perp stando delta-neutral.
### Scan di fattibilità dati (prima di tutto, lezione v2.0.0)
- **Funding price-clock** (drift attorno agli stamp 00/08/16) sul feed Deribit certificato →
già testato nell'onda intraday (`agent_03_funding_clock_15m`) = **FAIL** ("il funding è un cashflow
perp-vs-spot; il prezzo index non ha drift tradabile attorno allo stamp al netto del trend").
- **Funding carry su Deribit** (dove eseguiamo) → ccxt `fetch_funding_rate_history` = **0 righe**
(bloccato), Cerbero MCP espone solo `get_historical` (candele), endpoint funding = 404.
- **Funding carry su Hyperliquid** → API pubblica `/info {"type":"fundingHistory"}` = **disponibile**,
oraria, tokenless, serie native dal 2023-05. HL è già l'universo certificato di XS01.
### Dato scaricato e certificato
`scripts/research/fetch_hl_funding.py` (backoff anti-429) → **19 major** (gli stessi di XS01),
`data/raw/hlfund_<sym>_1h.parquet`. Certificazione: cadenza ~1h, **0 gap**, copertura 98-100%,
funding annualizzato per asset da **APT +1.0%** a **NEAR +21.6%** (mediana ~+11.7%). Pochi `cap_hit`
(ore con |funding|>0.06%/h) su INJ/TIA/SEI, plausibili in alt ad alta vol. Dato pulito.
## Ipotesi e costruzione (FC01)
Book dollar-neutral che **SHORTA i k perp ad alto funding** e **COMPRA i k a basso** → incassa il
premio (chi è long paga il funding). Ritorno perp per un long = `price_ret funding`. Causale come
XS01: ogni H=10 giorni, segnale = media causale del funding giornaliero realizzato sugli ultimi L
giorni (shift 1), rank cross-section, vol-target 20%, fee 0.05%/lato sul turnover.
`scripts/research/funding_carry_hl.py`. Domanda chiave: **edge reale e ORTOGONALE a XS01**, o XS01
travestito? (gli alt ad alto funding sono spesso i pompati = quelli che XS01 *compra*; qui li
*shortiamo* → potenziale anti-correlazione, oppure il carry domina).
## Risultati
### Premio reale ma direzione-dipendente
`carry` (short alto-funding) batte sistematicamente `anti` (long alto-funding, sempre molto negativo)
**il premio di funding esiste**: shortare i perp ad alto funding paga, in aggregato.
### Ma il book NON regge il gauntlet (19 asset, 2024-2026, 904g)
- **Standalone base (L=7 k=5): FULL Sharpe 0.12, in-sample 0.44, HOLD 0.50, DD 28.6%**, 2.8%/anno.
Decadimento netto: 2024 **+0.44** → 2025 0.06 → 2026 **1.42**.
- Correlazioni: TP01 0.02, **XS01 0.19** (ortogonale, come da ipotesi — NON è XS01 travestito),
VRP01 +0.05.
- **`marginal_vs_tp01` = DILUTES**: `has_insample_edge=False` (in-sample 0.44 < 0.5),
`multicut_persistent=False`, blend w25 uplift FULL 0.21 / HOLD 0.39.
- **Non aggiunge a XS01**: uplift w25 FULL 0.04 / HOLD 0.19.
### Il colpo di grazia: FRAGILITÀ all'universo
Un preview su 17 asset (mancavano NEAR e AAVE) dava FULL **+0.62**, ADDS, +0.22 uplift — un PASS
tentatore. Sui 19 completi: **DILUTES**. Jackknife lascia-fuori-uno (base L=7 k=5):
```
19 asset: FULL -0.12 HOLD -0.50
-SUI FULL -0.39 ... -BTC FULL +0.17
-SEI FULL -0.31 -AAVE FULL +0.26
-BNB FULL -0.29 -NEAR FULL +0.30
=> FULL oscilla in [-0.39, +0.30] togliendo UN solo asset (range 0.70), attraversa lo zero.
```
Togliere **NEAR o AAVE** (i due assenti nel preview) **recupera il segno** → il preview era fortunato
*proprio* perché quei due non c'erano ancora. **Un edge robusto non cambia segno per un singolo nome.**
Le poche celle "buone" del plateau (es. L=7 k=3: HOLD 0.91) hanno **in-sample debole + hold-out forte**
= la firma del hold-out-luck che la metodologia indurita uccide.
## Perché fallisce (meccanismo)
Tensione fondamentale **carry vs momentum**: il funding-carry shorta i forti (alto funding = domanda
long aggressiva), ma in un mercato alt toro i forti **continuano a correre** (NEAR/AAVE: alto funding
*e* prezzo su → shortarli perde più del premio incassato). Il premio di funding è reale in aggregato,
ma il book cross-sectional equal-weight top-k è dominato da pochi nomi a funding estremo che *anche*
trendano, e su 2.5 anni / 19 nomi questo basta a ribaltare il segno.
## Verdetto
**FC01 NON è uno sleeve.** Né deploy (è STAT-MODE: 10 gambe market-neutral, non eseguibile a $600),
né lead affidabile: fragile all'universo (sign-flip su un nome), DILUTES vs TP01, non aggiunge a XS01,
in-sample edge < 0.5, niente persistenza multi-cut, decadimento 2026. Conferma — di nuovo — il
soffitto del progetto: promettente su un sottoinsieme fortunato, collassa sotto il gauntlet onesto.
**Win metodologico:** lo scorer indurito + il jackknife d'universo hanno intercettato un falso
positivo che il preview a 17 asset avrebbe promosso.
## Lascito / lavoro futuro (NON inseguire ora)
- I 19 parquet funding (`hlfund_*`) restano certificati per ricerca futura. Il fetcher NON va in cron
(FC01 fallito → niente da monitorare in forward).
- Idee se mai si tornasse sul carry (NON ora): (a) **gate sul LIVELLO** di funding (short solo quando
estremo, regime-filter alla VRP01 IV-rank) invece dello short-top-k incondizionato; (b) cap sul peso
per-nome / neutralizzazione momentum per togliere il dominio NEAR/AAVE. Entrambe rischiano
overfitting su storia corta — soglia di prova alta.
## Nota IB (thread parallelo, stessa sessione)
Esplorato come fonte per il **basis CME crypto** (cugino eseguibile del carry). Gateway paper
`gnzsnz/ib-gateway` su `127.0.0.1:4002` (read-only, `docker-compose.yml`), sonda `ib_probe.py`.
Esito dati: **backtest del basis NON fattibile** (ContFuture back-adjusted; contratti scaduti = 1
barra). IB resta valido per esecuzione/forward, non per scoprire l'edge. Dettagli nel corpo sessione.
@@ -0,0 +1,33 @@
# 2026-06-23 — Combo DEPLOYABLE in PAPER: TP01 (Deribit) + GTAA (IB), cross-venue
## Decisione
Dopo aver esaurito (onestamente) la ricerca di nuovi edge e anticipazioni cross-mercato, l'unica cosa
VERA e deployabile e' la DIVERSIFICAZIONE: TP01 (crypto, Deribit) + GTAA (equity, IB), corr ~0.21 ->
blend Sharpe ~1.5, maxDD dimezzato (diari 2026-06-22-deployable-combo). Si va in PAPER cross-venue.
## Costruito
- **`src/portfolio/gtaa.py`** — GTAA come sleeve di prima classe: trend difensivo long-flat TSMOM
[21/63/126/252g], vol-target 12%, EW su SPY/QQQ/IWM/TLT/GLD/HYG. Espone `gtaa_returns()` (Sharpe
full 0.64, 7542 barre 1996+) e `gtaa_weights()` (pesi ETF CORRENTI azionabili). Legge cache eq_*.
- **`scripts/live/paper_combo.py`** — paper-tracker FORWARD-ONLY del blend 50/50 TP01+GTAA (crypto
compoundato sul grid giorni-di-borsa). Stato in data/paper_combo/. Mostra le posizioni azionabili
su entrambi i venue. SOLO le gambe eseguibili (XS01/VRP01 STAT-MODE esclusi).
- **`fetch_ib_equities.py --only SPY,QQQ,...`** — refresh mirato dei 6 ETF GTAA (per il cron).
- **`scripts/cron_daily.sh`** — aggiunto: up gateway IB (idempotente) -> refresh ETF GTAA ->
avanza paper_combo. Dipendenza cross-venue gestita (gateway paper sempre-up, restart unless-stopped).
## Stato iniziale (2026-06-23)
Paper combo init a 2000, forward da 2026-06-22. Posizioni azionabili:
- TP01 (Deribit): BTC/ETH 0.0x (flat, TSMOM risk-off — coerente col live).
- GTAA (IB): SPY 13% / QQQ 8% / IWM 9% / TLT 17% / GLD 2% / HYG 17% / cash 34% (difensivo).
Catena end-to-end testata: gateway -> refresh ETF -> avanza paper. OK.
## Onesta'
- E' PAPER (rischio zero). Valida l'OPERATIVITA' cross-venue prima di capitale reale.
- Sharpe atteso ~1.5 e' ottimistico (finestra crypto corta/favorevole); il dato robusto e' la
diversificazione (corr 0.21, DD dimezzato), non il livello assoluto.
- A capitale reale e' un portafoglio su DUE conti (Deribit ~$600 + IB); GTAA frazionabile a basso
capitale, TP01 gia' armato. Prossimo passo eventuale: dashboard del combo + (molto dopo) capitale.
## Prossimo
Lasciar girare il paper forward (cron giornaliero) e ricontrollare l'equity tra qualche settimana.
@@ -0,0 +1,38 @@
# 2026-06-23 — Cross-market crypto-lead OLTRE l'SP500: bond, commodity, indici esteri -> niente
## Obiettivo
Estendere il test "crypto anticipa il mercato?" oltre SP500/azionario USA: commodity, bond, indici
ESTERI (Europa/Asia, fasi orarie diverse = il caso a priori piu' favorevole a un lead vero).
## Dati (IB, orari, cache fut_*_1h)
ES/NQ/RTY (gia'); + ZN (T-note 10y), ESTX50 (Euro Stoxx50), DAX, NKD (Nikkei). Storia ~2-2.4y (2024+).
Commodity GC/CL/HG: VUOTE (market-data subscription COMEX/NYMEX mancante sul paper) -> non testate.
## Test (`fut_leadlag_generic.py`): crypto[T-8h->T] -> future[T->T+6h], non-sovrapposto, controllo=moto proprio future
- ES/NQ/RTY: nessun edge (gia' noto).
- ZN (bond): NEGATIVO (0/3 anni).
- NKD (Nikkei): debole (t_crypto 0.2, Sharpe 0.66 ~ overnight drift, non crypto).
- **ESTX50 / DAX: forte all'apparenza** — BTC->T0h: t_crypto ~7.8, Sharpe 2.5, ann ~22%, 3/3 anni.
## Ma e' un ARTEFATTO DI CONFINE UTC (deep-dive `eu_overnight_deepdive.py`)
- **Picco a coltello a T=00:00 UTC**: t/Sharpe salgono T20->T0 (2.5->7.8 / 0.24->2.45) e CROLLANO a
T=1h (t 1.3, Sharpe -0.09). Un lead vero non e' a coltello su una sola ora.
- **GAP test**: inserendo 1h tra fine-segnale (00:00) e inizio-cattura, l'effetto MUORE
(Sharpe 2.45 -> -0.52, t 7.8 -> 1.6).
- **Singola ora**: T=0h/H=1h (cattura 00:00->01:00) Sharpe +2.93 (t 8.7); T=1h/H=1h (01:00->02:00)
Sharpe -1.02. L'INTERO "edge" e' la barra di confine 00:00->01:00.
- vs SEMPRE-LONG: always-long overnight e' negativo (-0.8/-1.2), quindi non e' overnight-drift; ma
l'uplift del crypto e' tutto nella barra di confine.
-> Firma esatta di `day_boundary_robust` (CLAUDE.md): effetto che vive/muore spostando il confine del
giorno UTC di poche ore = etichettatura/contaminazione, NON anticipazione economica.
## Verdetto
NIENTE di tradabile oltre l'SP500 nemmeno. Su TUTTI i mercati il legame crypto->X e' o co-movimento
contemporaneo (risk-beta) o artefatto di confine. L'anticipazione crypto->altri-mercati sfruttabile
NON esiste su dati onesti (finestre non-sovrapposte + boundary-robust + gap). Conferma definitiva del
soffitto del progetto, ora anche cross-mercato.
## Cosa resta di valore (immutato)
La diversificazione TP01(crypto)+GTAA(equity), corr 0.21 -> Sharpe portafoglio ~1.5, DD dimezzato.
Quello e' strutturale e deployabile; l'anticipazione cross-mercato no.
Script: fetch_ib_futures.py (multi-exchange), fut_leadlag_generic.py, eu_overnight_deepdive.py.
@@ -0,0 +1,29 @@
# 2026-06-23 — "Monitor Deribit / trade IB": il gap crypto->equity e' LOOK-AHEAD
## Idea testata (utente)
Guardare crypto live su Deribit (24/7) e tradare l'indice su IB sul segnale del gap overnight.
## Trappola trovata
Il segnale crypto [P 21:00 -> D 13:00 UTC] e il "gap" equity [P close -> D open 13:30] coprono QUASI
LE STESSE ORE. Condizionare il gap sul crypto-overnight = correlare due ritorni dello STESSO intervallo
notturno -> look-ahead. All'entrata (D 13:00, pre-open) il gap e' GIA' avvenuto: non catturabile.
## Prova (net 2bps, sqrt(252))
| target | OVERLAP gap (look-ahead) | TRADABILE intraday (post-entrata) |
|---|---|---|
| SPY | Sharpe 3.60 (OOS 5.23) | -0.03 (OOS 0.12) |
| QQQ | Sharpe 4.01 (OOS 5.47) | 0.25 (OOS 0.43) |
| IWM | Sharpe 3.98 (OOS 5.72) | 0.15 (OOS 0.44) |
Lo "Sharpe 5" e' artefatto. L'edge REALE tradabile via ETF (intraday, entri all'open) ~0, muore a costi.
NB: anche i Sharpe "gap" del workflow 65-agenti erano (a) look-ahead di overlap e (b) sotto-annualizzati
(sqrt(52) invece di sqrt(252)); il verdetto "non deployabile" resta, rafforzato.
## Cosa resta possibile (non testato, serve dato)
L'unica versione onesta dell'idea: entrare a META' notte via FUTURES IB e vedere se crypto [P21:00->T]
predice il future indice [T->open] su finestre NON sovrapposte (crypto come sensore di rischio piu'
veloce). Richiede dati INTRADAY dei futures (ES/NQ/RTY), non in cache -> data step se si vuole indagare.
## Lezione
Un risultato "troppo bello" (Sharpe 5) e' un test di disciplina: era overlap di finestre. Catturato.
Script: crypto_overnight_equity.py (versione artefatto), crypto_overnight_honest.py (decomposizione).
@@ -0,0 +1,37 @@
# 2026-06-23 — "Monitor Deribit / trade IB" su futures: test ONESTO non-sovrapposto -> edge ~0
## Idea
Monitorare crypto live (Deribit 24/7) ed entrare sul FUTURE indice IB (ES/NQ/RTY, tradato di notte)
a meta' notte, catturando il moto SUCCESSIVO -> finestre NON sovrapposte (no look-ahead, vs il "gap"
che era contemporaneo al segnale).
## Dati
`fetch_ib_futures.py` -> data/raw/fut_{es,nq,rty}_1h.parquet (ContFuture orario, UTC). ES 3y (2023-06+),
NQ 2.75y, RTY 2.3y. (NB: ContFuture NON accetta endDateTime -> chiamata singola "4 Y" = ~3y max orari.)
## Test (`fut_overnight_leadlag.py`)
entrata a T (ora UTC notturna): segnale = crypto[P21:00->T]; controllo = future[P21:00->T] (moto
PROPRIO del future); cattura = future[T->open 13:00]. Incrementale: crypto predice la cattura OLTRE il
moto proprio del future? Trade: sign(crypto[P21:00->T]) * future[T->open], net 2bps. T in {0,3,6,9}h.
## Risultati
| future | miglior Sharpe (trade crypto) | t_crypto incrementale | esito |
|---|---|---|---|
| ES (S&P500) | ~0 / negativo (-0.03..-0.93) | 0..1.5 | NESSUN edge |
| NQ (Nasdaq) | 0.41 (T=3h) | 0.5 (debole) | momentum del future, non crypto |
| RTY (Russell) | 0.40-0.77 | 2.0-2.7 (BTC->RTY) | soffio debole, non robusto |
- **SP500: NIENTE.** Il crypto della prima notte non predice l'ES della seconda. Il "Sharpe 5" del gap
era interamente look-ahead (finestre sovrapposte): catturato e ucciso.
- **RTY (small-cap)** e' l'unico con t_crypto incrementale ~2-2.7 e crypto che AGGIUNGE oltre il moto
proprio del future (futOwn Sharpe negativo). MA: Sharpe 0.4-0.5 modesto, 24 config (multiple-testing),
storia 2.3y, per-anno INCOERENTE (BTC->RTY T=3h: 2024 +0.99 / 2025 +0.52 / 2026 -0.31).
## Verdetto
L'idea "monitor Deribit / trade IB" NON da' un edge tradabile, men che meno su SP500. Il forte
fenomeno crypto<->equity e' CO-MOVIMENTO contemporaneo (risk-beta overnight), non anticipazione: quando
si impone una finestra causale non-sovrapposta, l'edge svanisce (efficienza di mercato). L'unico
residuo (crypto->small-cap overnight) e' debole, borderline su multiple-testing e instabile per anno
-> forward-monitor al piu', NON deploy. Coerente col soffitto del progetto.
Script: fetch_ib_futures.py, fut_overnight_leadlag.py. (look-ahead documentato: 2026-06-23-crypto-overnight-lookahead.md)
+141
View File
@@ -0,0 +1,141 @@
# 2026-06-23 — SKH01 "Skyhook": porting onesto del sistema ES dual-timeframe su BTC/ETH
Branch: `strategy_skyhook`. Engine: `src/strategies/skyhook.py`. Harness: `scripts/research/skyhook/skyhooklib.py`.
Test: `tests/test_skyhook.py` (5 pass). Ricerca: `scripts/research/skyhook/{sweep,grid,check_v1}.py` + `runs/`.
## Il brief
Sistema "Skyhook" (origine ES / E-mini S&P, genetico, a doppio timeframe), da portare su crypto:
- **data2 = 690 min (segnale)**, **data1 = 230 min (esecuzione)**. NB **690 = 3 × 230**.
- NON trend-follower: entra **solo** quando coincidono (a) un **regime** di volatilità/volume e
(b) un **pattern** di breakout.
- Pipeline per barra: indicatori (BuzVola su ATR, BuzVolume su volume, tipo-Chande 0-100) →
fasce regime → pattern (Donchian/breakout su data2) → composer (regime AND pattern) →
ingresso (max 1/giorno, stop-and-reverse) → uscite (time-based asimmetrico uscitalong=24 /
uscitashort=18 + stop/profit).
- Ancore demo: trend lineare → **BuzVola=50** (vol steady → neutro), **BuzVolume=100** (volume in rampa).
## Ricostruzione (fedele + onesta)
- **Resample dal feed 5m certificato** con `origin='epoch'`: 230 min = 46×5m, 690 min = 138×5m,
e i confini 690 sono un **sottoinsieme** dei confini 230 → una barra HTF chiude esattamente su
una chiusura LTF. Merge HTF→LTF causale: `merge_asof` backward sulla **chiusura HTF** (≤ chiusura
LTF), così una barra HTF è usata solo quando è davvero chiusa. (~2287 barre/anno LTF, ~762 HTF.)
- **BuzVola / BuzVolume = `chande01`** (Chande Momentum Oscillator normalizzato 0-100): serie
steady → 50, rampa-su → 100, rampa-giù → 0. Le ancore demo sono soddisfatte a livello di
indicatore (è la lettura fedele: "vol steady → neutro"). NB: l'EMA-ATR su un *linspace* sintetico
dà 100 per drift di warm-up/floating-point, non per comportamento reale — su BTC reale BuzVola
oscilla intorno a 50 (EMA-ATR vs SMA-ATR corr 0.90).
- **Pattern** = Donchian breakout leak-free (shift(1)) su HTF, `ptn_n` barre (default 13 da 13/13/1).
- **Regime** = bande-soglia tunabili su BuzVola/BuzVolume (i magici interi 4/3/2 - 4/2/2 non sono
nel brief; ricostruiti come `[vola_lo,vola_hi]` × `[vol_lo,vol_hi]`).
- **Composer** = regime AND pattern. **Ingressi** ≤1/giorno (prima barra qualificante).
- **Uscite**: time-based asimmetrico (`uscitalong`/`uscitashort` barre LTF) + hard stop/profit. Lo
"stop 2000 / profit 5000" in $ del sistema ES → **multipli di ATR LTF** (scale-free): default
`sl_atr=2.0`, `tp_atr=5.0` (~ rapporto 40:100 pt ES), con modalità `pct` alternativa.
- Engine espresso come **entries `{dir,tp,sl,max_bars}`** per `backtest_signals` (motore onesto del
progetto: TP/SL intrabar, max_bars, non-overlap). Causalità verificata con prefix-recompute
(0 mismatch).
## Baseline → V1 (lever scout + grid, inline, veloce)
- **Baseline** (default 13/13, sl2/tp5, vola[35,95], vol_lo50): causale, fee-surviving, FULL Sharpe
BTC +0.91 / ETH +0.64, ma **HOLD-OUT debole** (BTC 0.09 / ETH +0.17) → FAIL del gate onesto.
- **Lever scout** (`sweep.py`): gli **short servono** (long_only → HOLD 0.52); il **regime gate
conta** (togliere la banda vola → HOLD 0.80); il **floor di volume** a 50 *frenava* l'hold-out
(vol_lo=40 o 0 → PASS); **breakout più lento** (ptn_n=55) e **stop più larghi** (sl2.5/tp6)
alzano l'hold-out.
- **Grid combinato** (`grid.py`): vincitrice **SKH01-V1**
`SkyhookParams(ptn_n=55, sl_atr=2.5, tp_atr=6.0, vola_lo=35, vola_hi=95, vol_lo=0.0)`:
- **min-asset FULL +0.69, HOLD-OUT +0.64** (BTC 0.64 / ETH 0.64), **PASS**, fee-surviving a 0.30%RT.
- BTC FULL +0.69/+275% DD49% ; ETH FULL +1.01/+871% DD31% ; entrambi HOLD-OUT positivi.
- **Marginal vs TP01 = ADDS** e regge i gate induriti: **corr 0.06** (ortogonale, NON trend-beta),
`has_insample_edge=True` (Sharpe in-sample standalone 1.15), `is_hedge=False`, multi-cut
persistente. Blend **0.75·TP01 + 0.25·SKH01: HOLD Sharpe 0.31 → 0.74 (+0.44), DD 11.9%**;
blend 50/50 HOLD 0.88, DD 17.8%.
- Unico sub-gate fallito: `clean_year_uplift` +0.014 (sotto 0.02) → `earns_slot=False` per un pelo,
nonostante tutto il resto sia forte. **Debolezza principale: DD standalone alto (40-49%).**
→ SKH01 è un **diversificatore quasi-ortogonale** reale (non un TP01 travestito): da solo è
volatile, ma come sleeve al 25% migliora moltissimo l'hold-out del portafoglio a DD bassissimo.
## Onda 1 (`skyhook-improve`, 30 agenti) — winner intermedio
Famiglie: param (RR, ptn_n, regime bands, exit bars, chande, local), regime-redef (percentile,
realized-vol, vol-expansion, LTF), pattern (confirmation, ROC, Keltner, NR, dual), exit + overlay,
ognuna verificata da 2 scettici. Risultato: **winner intermedio**
`SkyhookParams(ptn_n=45, sl_atr=2.5, tp_atr=7.0, uscitalong=24, uscitashort=16, vola_lo=35, vola_hi=95, vol_lo=0)`
**minFull +0.83, minHold +0.81** (vs V1 +0.69/+0.64), causale, fee-surviving 0.30%RT, marginal
**ADDS** (corr 0.05, has_insample_edge, robust_oos, multicut, clean_year_uplift +0.37), blend w25
uplift_hold +0.58. **MA standalone maxDD ancora 34% (BTC) / 31% (ETH) → l'unico goal mancato era il DD<30%.**
## Onda 2 (`skyhook-improve-v2`, 14 famiglie DD-reduction) — SKH01-V2-DD vince
Obiettivo: tagliare il **DD standalone <30%** tenendo hold-out + `earns_slot`, e alzare l'uplift di
portafoglio. 14 famiglie (ensemble param/struct, vol-target, DD kill-switch, RR/stop grid, regime
tight, percentile, vol-expansion, breakout confirmation, dual-TF, asimmetria L/S, cadenza, chande,
Keltner), ognuna verificata da 2 scettici avversariali (window-luck/multicut/jackknife +
causalità/fee/plateau/overfit). Esito: **il winner intermedio cade.** Nuovo campione **SKH01-V2-DD**
(famiglia ASYM_LS, `src/strategies/skyhook.py:SKH01_V2_DD`, run `runs/SKH2_ASYM_LS.py`):
- **Config:** stesso SEGNALE del winner (`ptn_n=45, vola_lo=35, vola_hi=95, vol_lo=0, exit-bars 24/16`)
ma EXIT commutati da ATR a **percentuale fissa ASIMMETRICA** — long `sl=4% / tp=10%`, short
`sl=2% (più stretto) / tp=8%`. Motivazione meccanica: in crypto lo short si fa steamrollare da uno
spike vola e lo stop-ATR si allarga lasciando correre la perdita → il %-SL stretto sullo short
**cappa la perdita per-trade** che FORMA il maxDD. (Implementato come override per-direzione nel
motore, backward-compatible: campi `*_short=None` → comportamento simmetrico invariato.)
- **Numeri veri (verificati indipendentemente via `sk.study(SKH01_V2_DD)`):** standalone maxDD
**BTC 21.4% / ETH 27.4%** (<30% ✓, vs 34.4/30.5 del winner) — **goal RAGGIUNTO**; minFull **+0.99**,
minHold **+1.26**; causalità **0/400** entrambi gli asset; fee@0.30%RT BTC +1.05 / ETH +0.80
(positiva anche a 0.40%). Marginal vs TP01 **ADDS** (corr 0.09, has_insample_edge, is_hedge=False,
robust_oos, multicut, clean_year_uplift +0.57). **Blend 0.75·TP01 + 0.25·SKH: uplift_hold +0.87**
(vs +0.58 del winner); **blend 50/50: full 1.84 / hold 1.59 / DD 10.7%**. earns_slot=True,
beats_winner=True. **Plateau reale** (i vicini Spct_mb14/16 sl2% tengono DD 27-28%), non knife-edge.
Entrambi gli scettici: holds_up=True, confidence high, killer_finding=null.
**Top-3 dell'onda 2 (criteri onesti):**
| # | Famiglia | maxDD (BTC/ETH) | minHold | w25 uplift_hold | Verifica |
|---|---|---|---|---|---|
| **1** | **ASYM_LS → SKH01-V2-DD** | 27.4% (21.4/27.4) | +1.26 | **+0.87** | 2/2 high, killer=null ✅ |
| 2 | ENS_STRUCT (3-regime ensemble) | **22.9%** (21.2/22.8) | +1.00 | +0.67 | 2/2 high — ma 3 motori da eseguire |
| 3 | TPSL_DD (%-SL/TP hard) | 28.0% (28/25.5) | +1.11 | +0.75 | 1/1 (rate-limit) — caveat hedge-like |
**Lezioni anti-DD:**
- **Ha funzionato (STRUTTURA dell'exit, non i parametri):** cambiare il MECCANISMO di uscita — %-SL
hard, asimmetria L/S, o ensemble di exit/regime diversi (decorrelazione). Il DD del winner nasce
dalla coda intra-trade negli spike ATR; il %-SL la cappa.
- **NON ha funzionato (la leva non raggiunge il DD vincolante):** DD kill-switch entry-only (sopprime
solo le NUOVE entry, non chiude il trade aperto che forma il maxDD → floor 33-36%); vol-target
causale (DD<30 e uplift≥0.55 mutuamente esclusivi; cap>1 PEGGIORA il DD levereggiando nel pre-crash);
cadenza/FREQ (accorciare gli hold short fa esplodere ETH a 50-66%); dual-TF (LTF è resample dello
stesso prezzo → quasi-tautologico, DD invariato).
- **Bocciato dagli scettici come overfit:** PATTERN_CONF (sub-30 solo a vola_lo=45, knife-edge: sl_atr
±0.5 → ETH 40-47%; la conferma "close_loc" da sola NON taglia il DD). Esempio canonico del perché
serviva la doppia verifica.
- **Non promuovibili:** PCTL_DD (numeri spettacolari ma **0 verifiche**, le 2 sono morte per rate-limit
→ forward-monitor, non fidato); ENS_PARAM / TPSL_DD (battono i gate ma uplift recency/hedge-loaded,
concentrato nei regimi TP01-down → forward-monitor).
**Promozione (questa sessione):** `SKH01_V2_DD` canonico nel motore + override exit-short
asimmetrici (backward-compatible, V1/winner invariati) + 3 test nuovi (8/8 pass).
**Sleeve cablato @0.25 effettivo** (`src/portfolio/sleeves.skyhook_sleeve``active_sleeves`): i tre
sleeve preesistenti scalati nel restante 0.75 mantenendo il rapporto 55:25:20 → **TP01 41.25% / XS01
18.75% / VRP01 15% / SKH01 25%**. Report del portafoglio (4 sleeve, `run_portfolio.py`):
| | FULL Sharpe | FULL DD | HOLD-OUT Sharpe | HOLD-OUT DD |
|---|---|---|---|---|
| 3 sleeve (TP01+XS01+VRP01) | 1.68 | 14.3% | 1.63 | 3.4% |
| **+ SKH01 @25%** | **2.13** | **7.8%** | **2.30** | 3.5% |
| Δ | **+0.45** | **6.5pt** | **+0.67** | ~0 |
→ aggiungere Skyhook **alza lo Sharpe full +0.45 e DIMEZZA il DD full (14.3→7.8%)**, e alza l'hold-out
+0.67 a DD invariato. Portafoglio combinato: FULL Sh 2.13 / ret +365% / DD 7.8%, HOLD Sh 2.30 / DD 3.5%,
positivo ogni anno (2019-26, DD annuo ≤7.8%) vs buy&hold 50/50 FULL Sh 0.93 / DD 76%.
**Caveat onesti / NON deploy:** è un portafoglio di **ricerca** (peso fisso, no costi di ribilanciamento
reale a $600; lo Sharpe daily-step di Skyhook è la convenzione del lens). ETH DD standalone 27.4% ha
margine sottile vs 30%. Prima di un eventuale deploy: ri-verificare la causalità sul **codice di
esecuzione reale** (qui è l'harness di ricerca) e i costi del book a 230m (ribilanciamento più frequente
del resto). XS01/VRP01 restano STAT-MODE/lead. Per ora: research win + sleeve cablato, forward-monitor.
+66
View File
@@ -0,0 +1,66 @@
# 2026-06-23 — Tail-hedge / protezione DD del combo (incl. OPZIONI): vince la guardia-drawdown
## Obiettivo (goal utente)
Trovare uno sleeve/overlay da AGGIUNGERE al combo (TP01+GTAA) per proteggere il drawdown e gli anni
tipo 2022. Valutare anche le opzioni.
## Diagnosi del rischio (decisiva)
Il MaxDD del combo (1x) e' **8.4%** e il 2022 fu **-4.4%**: NON un crash, un **grind lento** (peggior
giorno -2.8%, peggior mese 2022 -1.6%). Il doppio trend (TP01+GTAA long-flat) gia' taglia i crash
veloci. Il tail residuo = (a) whipsaw da mercato choppy (2022), (b) gap/crash overnight LATENTE (TP01
non reagisce intraday, non nel campione storico), (c) la LEVA.
## Candidati testati (`tail_hedge_lab.py`)
| protezione | MaxDD | 2022 | Sharpe | CAGR |
|---|---|---|---|---|
| combo baseline | 8.4% | -4.4% | 1.48 | 11.3% |
| **+ guardia-DD -4%** | **5.8%** | **-1.8%** | 1.38 | 9.2% |
| + vol-target 5% | 8.4% | -5.9% | 1.46 | 8.0% |
| + opzioni (put/put-spread, budget 3%/y) | 8.4% | -4.4% | 1.48 | 11.3% |
### OPZIONI (valutate): NON adatte al 2022
- Put-spread/long-put LONG su indice 50/50 BTC/ETH (mirror di VRP01), premio BS su DVOL reale, payoff
sul path. Strike corretti (compra -0.30delta, vende -0.10delta).
- Sempre-on costa **~50%/anno** di premio -> con budget 3%/anno size ~0.06-0.10x = effetto ~nullo.
- Nel 2022 (grind, niente crash settimanali) **sanguinano** (scadono inutili) -> Δ2022 ~0.
- Pagano SOLO nei crash secchi: stress -30% overnight -> put paga **+25% netto**, put-spread +3.8%.
- Verdetto: assicurazione BLACK-SWAN cara e fuori-bersaglio per il grind. Utile solo come piccola
copertura del gap overnight latente, NON come fix del 2022.
### GUARDIA DRAWDOWN: centra il rischio
De-risk (esposizione 1.0->0.4) quando il DD da picco supera -4%, ri-rischia a -1.6%. Targetizza il
grind: MaxDD 8.4%->5.8%, 2022 -4.4%->-1.8%, ogni anno DD intra <=5.4%. Costo: Sharpe 1.48->1.38,
CAGR -2.1pp (de-risca sui cali, perde rimbalzo — prezzo onesto della protezione).
### A LEVA (dove il tail morde)
guard applicato pre-leva: 2x 2022 -15.6%->-10.9%, MaxDD 28%->24%; 3x resta MARGIN-CALL (DD 39%>=33%).
-> la protezione rende il 2x sopportabile; il 3x va evitato comunque.
## Raccomandazione
AGGIUNGERE una **guardia-drawdown a livello di portafoglio** al combo (overlay, niente premio):
e' la protezione che colpisce il rischio reale (grind/2022) a costo Sharpe minimo. Le opzioni NO come
fix del 2022; eventualmente una micro-allocazione deep-OTM come assicurazione black-swan separata.
Vol-target NON aiuta (il 2022 non e' uno spike di vol).
## Onesta'
- Il guard e' REATTIVO (de-risca dopo l'inizio del DD, restituisce un po' di rimbalzo) -> costa CAGR.
- Trade: -2.1pp CAGR per dimezzare il MaxDD e azzerare quasi il 2022. Sensato se la priorita' e' il DD.
- Parametri (-4% trigger) semplici; il meccanismo (non la soglia esatta) e' la sostanza.
Script: tail_hedge_lab.py.
## Aggiornamento — protezioni CLASSICHE (stop-loss), goal "prova anche SL" (`stops_lab.py`)
Confronto equo (trigger/re-entry sul NAV di mercato, non sull'equity congelata):
| protezione | Sharpe | MaxDD | 2022 | CAGR | in-mkt |
|---|---|---|---|---|---|
| baseline | 1.48 | 8.4% | -4.4% | 11.3% | 100% |
| **soft-guard -4% (0.4x)** | **1.38** | **5.8%** | **-1.8%** | 9.2% | 100% |
| trail-stop -4% (uscita tot.) | 1.07 | 7.5% | +0.0% | 6.6% | 42% |
| trail-stop -6% (re:newhigh) | 1.34 | 6.6% | -2.1% | 9.0% | 72% |
| trail-stop -8% | 1.41 | 8.3% | -4.2% | 10.0% | 87% |
| stop mensile -5% | 1.48 | 8.4% | -4.4% | 11.3% | 100% (mai scatta) |
| vol-stop (>90pctl) | 1.48 | 8.4% | -4.4% | 10.4% | 100% |
VERDETTO: lo SL classico funziona solo a -6% (e resta inferiore al soft-guard); a -4% fa WHIPSAW
(Sh 1.48->1.07, fuori mercato 58%) perche' l'uscita TOTALE viene choppata nel grind. Il soft-guard
alla stessa soglia non whippa (de-risk parziale 0.4x). Stop mensile/vol inutili (bersaglio sbagliato).
Conferma: per un DD da grind, de-risk PARZIALE > stop-loss duro. Soft-guard -4% confermato come scelta.
+69
View File
@@ -0,0 +1,69 @@
# 2026-06-26 — Cash-and-carry (basis trade) delta-neutral su HL (CC01): premio REALE, Sharpe ARTEFATTO, NON deployabile
**Goal utente:** dopo lo scarto del gamma scalping, "provare" gli altri due angoli proposti —
funding-carry cross-sectional e basis/cash-and-carry. Il **funding cross-sectional (FC01) è già
SCARTATO** (diario 2026-06-22: DILUTES, sign-flip su un nome). L'angolo non testato è il
**cash-and-carry delta-neutral (CC01)**. Branch `research/gamma-scalp-options`,
script `scripts/research/cash_carry_hl.py`.
## Meccanismo (diverso da FC01)
FC01 pickava cross-section (short alto-funding / long basso-funding) → scommessa relativa, fragile.
CC01 **non picka**: harvesta il premio di funding AGGREGATO restando delta-neutral sullo *stesso*
asset. Long spot + short perp (stessa size): le gambe lineari nel prezzo si cancellano → ritorno
**+funding** (lo short incassa il funding quando f>0), zero esposizione direzionale. Dati: funding
orario reale HL dal 2023-05 (`hlfund_*_1h.parquet`), gli stessi 19 major di XS01.
## Risultato grezzo — e perché NON va creduto
| config | Sharpe | CAGR | maxDD | per-anno |
|---|---|---|---|---|
| BTC/ETH CC-static | **+12.9** | +13% | 0.8% | 2023:+10 2024:+23 2025:+8 2026:+1% |
| BTC/ETH CC-gated | +13.9 | +14% | 0.3% | tutti positivi |
| 19-major CC-gated | +11.6 | +16% | 0.4% | tutti positivi |
**Uno Sharpe di 13 con DD 0.3% è un ALLARME, non un edge.** È la firma di un modello che cattura
solo un cashflow liscio (il funding) e azzera la volatilità reale. Il marginal scorer dà **ADDS /
robust_oos / has_insample_edge=True / multicut_persistent** su OGNI config — ma questo **espone un
punto cieco dello scorer**: si fida della vol riportata dal candidato e non ha un gate "Sharpe
implausibile → rischio nascosto". Un Sharpe di 13 dovrebbe squalificare-e-indagare, non passare.
## Il rischio è NASCOSTO, non assente
- **Mark-to-market della base** (`premium` col → `r = funding Δpremium`): sgonfia lo Sharpe solo
13→11. La colonna premium di HL è già lisciata/clampata → a risoluzione daily il basis-vol è
minimo. **Quindi il basis-from-data NON è il rischio vero.**
- **I rischi che giustificherebbero uno Sharpe realistico (~1-3) sono ASSENTI dal dataset:**
1. **2022 mancante.** Lo storico funding parte 2023-05 → niente deleveraging LUNA/3AC/FTX, il
regime di funding profondamente negativo + basis blow-out che farebbe il vero drawdown.
2. **Procyclicità.** Funding aggregato BTC/ETH: +23% nel toro 2024 → **+1.7% nel bear 2026**
(e 19-major CC-static 2026 = **1%**). Solo 10% di giorni a funding negativo *in-sample* — ma
in un vero bear quella frazione esplode. Il carry **non è all-weather**: è un risk-on premium.
3. **Liquidazione dello short** in uno squeeze e **slippage** su spot+perp: non modellati.
- **Sharpe reale di un crypto basis-trade ≈ 1-3 con code brusche** (Mar-2020, Mag-2021, FTX), non 13.
## Eseguibilità a $600 — muro indipendente
Serve spot **+** perp per gamba: BTC/ETH = 4 posizioni, 19-major = 38. Su Deribit (dove operiamo) lo
storico funding è **bloccato** (404) e non tradiamo spot HL. **STAT-MODE**, come XS01/VRP01 ma peggio
(doppia gamba per asset). Non deployabile a questo capitale.
## Verdetto
**CC01 = premio di funding REALE (~+8-14%/anno aggregato, positivo ogni anno in-sample) e
genuinamente ortogonale a TP01 (corr ~0.05, NON direzionale).** È la "fonte di ritorno diversa" più
concreta trovata finora. MA:
- lo **Sharpe headline è fiction** (rischi di coda strutturalmente fuori dal dataset);
- è **procyclico** (si comprime/inverte nel bear — proprio quando servirebbe);
- **non eseguibile** a $600 / sul nostro venue.
**LEAD da rivedere a scala** (capitale ~20k+ e un venue con funding eseguibile), **non uno sleeve**.
Nessun impatto sul book live (branch separato).
## Sottoprodotto metodologico (raccomandazione)
CC01 ha passato ogni gate del marginal scorer pur essendo un'illusione di rischio. **Prossima
indurita dello scorer:** un gate di *plausibilità dello Sharpe* — uno standalone Sharpe ≫ 4 deve
declassare a "SUSPECT/INVESTIGATE" invece di alimentare ADDS, perché segnala vol sottostimata
(mark-to-cashflow, dati che escludono il regime di stress, leva nascosta). Documentato qui, non
implementato in questa passata per non toccare lo scorer condiviso su `main`.
@@ -0,0 +1,58 @@
# 2026-06-26 — "Short su fondamentali/notizie NEG ma prezzo SU": screener forward, edge non provato
**Goal utente (chiarito):** se i dati finanziari/notizie di un'azienda sono negativi ma la
quotazione è positiva (sale), andare SHORT — scommessa che il prezzo scenda a riallinearsi ai
fondamentali. Branch `research/equity-meanrev-ib`, script `scripts/research/eq_fundnews_short.py`.
## Gate dati (lezione v2.0.0) — NON backtestabile
I fondamentali e le notizie scaricabili dalla rete (Yahoo) sono **snapshot CORRENTI**, non
point-in-time storici. Applicarli a prezzi passati = **look-ahead** (restatement + survivorship):
esattamente la classe di errore che ha prodotto la libreria fasulla v2.0.0. Un backtest onesto
richiede un DB point-in-time (Compustat PIT, news storiche con timestamp) — **assente**. Quindi,
come per la vol term-structure: **niente backtest**, l'unica via onesta è uno **screener forward**.
## Cosa è scaricabile (feasibility, fatto)
- **Fondamentali strutturati** via Yahoo quoteSummary (flusso cookie+**crumb**, tokenless):
`recommendationMean` (1=buy..5=sell), `revenueGrowth`, `earningsHistory` surprise%,
`recommendationTrend` (skew buy/sell). ✅
- **Notizie**: Yahoo news search (headline + publisher), sentiment lessicale crudo. ✅ (proxy debole)
- **Momentum**: chart API (return 1m/3m). ✅
## Screener costruito + eseguito dal vivo
`fund_neg` ∈ [0,1] (media di: recMean→sell, surprise negative, ricavi in calo, analisti a sell) +
`news_neg` lessicale + momentum. **SHORT candidate = (fond/news neg) AND prezzo in salita** (la
divergenza). Idempotente, logga forward su `data/raw/fundnews_short_screen.parquet`.
**Run di oggi (2026-06-26): NESSUN candidato.** Quasi tutto l'universo ha momentum 1m **negativo**
(mercato in flessione ampia, coerente col bear) → la gamba "prezzo che sale" non scatta. I peggiori
per fondamentali (TSLA 0.48, BA 0.39, NKE 0.38) stanno comunque *scendendo*. Output sensato.
## L'intuizione analitica chiave (il valore vero di questa analisi)
La premessa ha una **tensione interna** che la rende la versione *rischiosa* dell'anomalia:
- **Shortare un prezzo che SALE combatte il momentum** — una delle anomalie più robuste e persistenti
(i winner continuano a vincere su 3-12 mesi). Si scommette contro di essa.
- **Il PEAD** (post-earnings drift) dice che dopo cattive notizie il prezzo continua a **scendere**;
ma qui il prezzo *sale malgrado* le cattive notizie → spesso significa che il mercato sta
**prezzando informazione** che i fondamentali *trailing* non contengono (turnaround, M&A, squeeze).
- Quindi: la versione *pulita* dell'edge "short su fondamentali deboli" funziona meglio quando il
prezzo **conferma** (fondamentali deboli + prezzo che SCENDE = momentum e fondamentali allineati),
**non** quando diverge. La richiesta "shorta il titolo che sale su brutte notizie" è il caso
contrarian, più difficile e storicamente più punito (squeeze, perdita illimitata).
## Eseguibilità (muro)
Short = **borrow** (locate + fee; hard-to-borrow caro/assente), **perdita illimitata**, **squeeze**,
**PDT $25k** per i day-trade, IB instabile qui, $600, universo single-stock (non i nostri ETF). NON
deployabile.
## Verdetto
**Non un edge schierabile, né dimostrabile ora.** Deliverable onesto = lo **screener forward**
(funzionante, da dati di rete) + il log che accumula i candidati per una validazione futura, con
la chiara avvertenza che l'edge è **non provato** e che la *direzione contrarian* della scommessa
(short sulla forza) è la parte fragile. Strumento utile (fond+news+momentum da rete in un colpo),
tesi da maneggiare con scetticismo. Nessun impatto sul book live (branch separato).
@@ -0,0 +1,57 @@
# 2026-06-26 — Scalping azioni IB "quando sottoquotate" + check dati dalla rete
**Goal utente:** su IB, comprare azioni quando "sottoquotate" (oversold/sotto fair-value), con
verifica incrociata dei dati dalla rete. Branch `research/equity-meanrev-ib`,
script `scripts/research/eq_meanrev_ib.py`. Due pezzi.
## 1) CHECK DATI DALLA RETE — il pezzo richiesto (e perfettamente in-metodo)
Confronto i dati certificati IB (`data/raw/eq_*_1d.parquet`, ADJUSTED_LAST) con una **sorgente di
rete indipendente** (Yahoo Finance chart API, tokenless). È la lezione fondante del progetto: non
fidarti di un feed solo (il disastro v2.0.0 era un feed contaminato).
**Risultato (180g, BTC… no: 6 ETF):** dopo l'allineamento corretto **tutti CONCORDE**, deviazione
sui rendimenti **≤1.2bps**, ultimo close identico (0.0bps). Il feed IB è validato.
**La lezione (errore che ho fatto e corretto):** un primo confronto naïf (nostro close *adjusted*
vs `close` *grezzo* di Yahoo) ha **falso-allarmato 4/6 ticker** a 30-52bps (SPY 30, TLT 40, HYG 52).
Le divergenze erano **tutte su singoli giorni = stacco dividendo**: confrontavo dividend-adjusted vs
non-adjusted. Usando l'`adjclose` di Yahoo (apples-to-apples) → ~0bps. **Regola: ogni divergenza va
SPIEGATA prima di gridare "feed sporco" — e prima di tradarci sopra.** Lo strumento resta come
validatore di feed riutilizzabile / template del pre-trade price-check live.
## 2) "SCALPING quando sottoquotata" — non testabile/eseguibile; testato lo swing MR
Lo **scalping intraday non è valutabile**: (a) non abbiamo dati intraday (solo `eq_*_1d`), (b) non
è eseguibile — **PDT rule**: il day-trading di azioni US sotto **$25.000** è limitato a 3
day-trade/5gg → lo scalping è *regolatoriamente bloccato* al capitale del progetto (l'analogo equity
del muro STAT-MODE a $600 sul crypto), (c) IB Gateway è instabile qui (timeout ordini diagnosticato).
Versione onesta e testabile = **swing mean-reversion** "compra quando sottoquotata": Connors RSI2<10
+ filtro trend MA200, exit a MA5. Causale (segnale ≤ close[i], entry a close[i]), netto fee, hold-out 2015+:
| ETF | FULL Sh | DD | CAGR | expo | HOLD Sh | **B&H HOLD Sh** |
|---|---|---|---|---|---|---|
| SPY | +0.75 | 15% | +5% | 13% | +0.70 | **+0.81** |
| QQQ | +0.50 | 16% | +4% | 14% | +0.56 | **+0.92** |
| IWM | +0.32 | 22% | +2% | 13% | +0.15 | +0.53 |
| DIA | +0.38 | 13% | +2% | 14% | +0.55 | +0.74 |
| EEM | +0.41 | 20% | +3% | 13% | +0.36 | +0.46 |
Fee sweep SPY: Sh 0.82 (0bps) → 0.75 (3) → 0.70 (5) → 0.58 (10bps RT).
**Lettura onesta:** la mean-reversion "buy the dip" sugli indici equity ha un edge **reale ma
modesto** (Sharpe ~0.5-0.75, investito solo ~13% dei giorni) **che NON batte il buy&hold
risk-adjusted** (B&H hold-out 0.81 su SPY vs 0.70 della MR), con CAGR piccolo (2-5%) e sensibile ai
costi. È capital-efficient in teoria (cash 87% del tempo) ma il valore aggiunto vs "tieni l'indice"
è negativo o nullo, e la frequenza *scalping* che potrebbe aggiungere valore è bloccata dalla PDT.
## Verdetto
- **Check dati dalla rete: FATTO e utile** — feed IB validato (≤1.2bps vs Yahoo); strumento
riutilizzabile. Unico vero keeper della sessione equity.
- **Scalping "sottoquotate": NON deployabile** — non testabile (no intraday), non eseguibile (PDT
$25k, IB instabile). Lo swing MR daily testabile **non batte il buy&hold** → niente edge schierabile.
Conferma il pattern del progetto: l'idea promettente sopravvive solo finché non incontra
eseguibilità + benchmark onesto. Nessun impatto sul book live crypto (branch separato).
@@ -0,0 +1,74 @@
# 2026-06-26 — "Scalping BTC/ETH con copertura in opzioni" = gamma scalping → SCARTATO
**Domanda (goal utente):** analizzare lo scalping su BTC/ETH con copertura in opzioni come
possibile nuovo sleeve. **Esito: negativo, strutturale, su tutte le frequenze. Non è uno sleeve,
non è nemmeno un hedge.** Branch `research/gamma-scalp-options`, script
`scripts/research/options_gamma_scalp.py`.
## Cos'è davvero "scalping con copertura in opzioni"
L'interpretazione rigorosa è il **gamma scalping**: compri un'opzione (la *copertura* = long
gamma), delta-hedgi il sottostante a cadenza fissa (lo *scalp*), e il P&L netto è
≈ dollar-gamma × (vol realizzata² vol implicita²). È lo **specchio esatto del VRP01** (short-vol):
VRP01 incassa IVRV (positivo in media), il gamma scalping incassa **RVIV** (negativo in media).
Modello (mirror della struttura VRP per comparabilità): long straddle ATM, tenor 7g, IV = DVOL
Deribit (la stessa fonte del VRP), delta-hedge sui prezzi certificati, fee opzioni cap 12.5% del
premio + fee perp 0.05%/lato sull'hedge turnover, return-on-notional vol-targeted 20%.
## La diagnostica strutturale (il cuore)
| asset | IV (DVOL) | RV 1d | IVRV 1d | RV 1h | IVRV 1h |
|---|---|---|---|---|---|
| BTC | 60.9% | 56.0% | **+4.9pp** | 64.5% | 3.6pp |
| ETH | 74.9% | 76.0% | 1.0pp | 81.0% | 6.1pp |
- A **rehedge giornaliero** l'IV ≈ o > la RV → il long gamma **paga il VRP** (sei sul lato sbagliato
del premio). Perde gross, prima di ogni fee.
- A **rehedge orario** la RV *supera* l'IV (BTC +3.6pp, ETH +6.1pp gross) — sembrerebbe un edge…
**ma è una trappola doppia:** (a) la RV_1h è gonfiata da microstruttura (bid-ask bounce), quindi
il "gross edge" è in parte fittizio; (b) il rehedge orario paga **24× la fee di hedge**, che
spazza via qualunque edge intraday reale.
## I numeri (ogni variante, ogni anno, ogni frequenza: PERDE)
| variante | rehedge | Sharpe | CAGR | per-anno |
|---|---|---|---|---|
| NAKED | 1d | **3.99** | 56% | 2021..2026 tutti 25..68% |
| CHEAP-GATED (IVr<0.30) | 1d | 3.05 | 47% | tutti negativi |
| RICH-SKIP (IVr>0.90) | 1d | 3.92 | 55% | tutti negativi |
| NAKED | 1h | **6.06** | 71% | tutti 38..81% (peggio: le fee) |
| CHEAP-GATED (IVr<0.30) | 1h | 4.96 | 64% | tutti negativi |
Il gate "compra vol solo quando è a sconto" (lo specchio del gate vincente del VRP, *vendi vol solo
quando è cara*) **migliora ma non salva**: 3.05 invece di 3.99. Il segno resta negativo perché
l'IV-rank basso non garantisce RV > IV su 7 giorni.
## Scoring marginale vs TP01
Tutte le varianti: **DILUTES**, `is_hedge=False`, `has_insample_edge=False` (IS Sharpe 3..4.5),
blend-25 uplift hold 1.2/1.5. Non aiuta nemmeno come hedge: perde sia quando TP01 è su
(uplift 1.2..1.6) sia quando TP01 è giù (uplift 2.5..3.2). Corr a TP01 ≈ 0 ma il drift negativo
domina la matematica di diversificazione.
## Eseguibilità a ~$600 (muro indipendente)
- **BTC**: contratto 1 BTC, min 0.1 BTC → notional minimo **$5.968** ≫ $600 → **NON eseguibile**.
- **ETH**: min 0.1 ETH → **$157** → marginalmente OK, ma un solo straddle = ~25% del conto in premio.
Anche se l'edge esistesse, BTC è fuori e ETH è troppo grosso per diversificare.
## Conclusione
Lo "scalping con copertura in opzioni" è **schiacciato tra due muri**: rehedge lento → paghi il
premio (RV < IV); rehedge veloce → paghi le fee (24×/day). **Nessuna frequenza vince.** Conferma
due lezioni di prim'ordine del progetto, ora quantificate sul long-vol:
1. **Le fee uccidono lo scalping** (il rehedge orario, vera frequenza di scalping, è la variante
*peggiore*: 6 Sharpe).
2. **Vol-da-modello è fragile in entrambe le direzioni.** Regola gemella del VRP: *niente long-vol
scalp da modello in deploy*.
**Il VRP01 (lato short, gated, rischio-definito) resta l'unico edge opzioni del progetto**
e funziona proprio perché sta sul lato *giusto* dello stesso premio che il gamma scalp paga.
SCARTATO. Script preservato come riferimento. Nessun impatto sul book live (branch separato).
@@ -0,0 +1,66 @@
# 2026-06-26 — TP01 × DVOL vol-targeting: NON migliora (il taglio di DD è solo de-levering)
**Goal utente:** "continua" ad analizzare strategie. Dopo i tre angoli di diversificazione tutti
STAT-MODE (gamma scalp scartato, funding cross-sectional già morto, cash-and-carry lead non
deployabile), ho puntato sull'angolo a **più alto valore perché ESEGUIBILE**: migliorare il
risk-sizing del book **live** TP01 (BTC/ETH perp Deribit, già armato). Branch
`research/gamma-scalp-options`, script `scripts/research/tp01_dvol_overlay.py`.
## Ipotesi
TP01 vol-targeta sulla vol **realizzata** 30g (backward-looking). Il **DVOL** (vol implicita 30g
Deribit, forward-looking, che spesso anticipa i salti di vol) come denominatore → de-risking più
tempestivo prima dei crash → DD più basso / hold-out migliore senza affondare il FULL.
Onestà: DVOL parte 2021-03 → confronto TUTTE le varianti sulla **finestra comune 2021-04 → 2026**
(1891g, perdo il toro 2019-2020 pre-DVOL). Causale, fee 0.10% RT, config canonica TP01.
## Risultati (finestra comune, hold-out 2025+)
| variante (denominatore vol) | FULL Sh | FULL DD | CAGR | HOLD Sh |
|---|---|---|---|---|
| **realized** (baseline) | **+0.75** | 12.3% | +8% | +0.30 |
| dvol (implicita) | +0.70 | 9.3% | +6% | +0.33 |
| blend 50/50 | +0.72 | 10.4% | +7% | +0.32 |
| max(realiz, dvol) | +0.70 | 9.2% | +6% | +0.36 |
| derisk (gate DVOL>p90 ×0.5) | +0.75 | 12.3% | +8% | +0.30 |
Le varianti DVOL **abbassano il DD** (12.3% → ~9.2%) ma **anche** Sharpe FULL (0.04/0.05) e CAGR
(8% → 6%). Lo Sharpe è scale-invariant → sospetto: il taglio di DD è solo *posizioni più piccole*
(l'IV > RV per il VRP → denominatore più grande → leva minore), non vero timing.
## Il controllo decisivo
Confronto le varianti DVOL col **realized a target_vol RIDOTTO** (stesso de-levering, senza DVOL):
| | FULL Sh | DD | CAGR | HOLD Sh |
|---|---|---|---|---|
| **max-DVOL** | +0.70 | 9.2% | +6% | +0.36 |
| **realized @ vol-tgt 15%** | **+0.75** | 9.4% | +6% | +0.30 |
| **realized @ vol-tgt 13%** | +0.75 | **8.1%** | +5% | +0.30 |
**Conclusivo:** il realized a 15% eguaglia il DD del max-DVOL (9.4% ≈ 9.2%) a Sharpe **più alto**
(0.75 > 0.70) e stesso CAGR; a 13% fa DD ancora più basso (8.1%), sempre a 0.75. **Il taglio di DD
del DVOL è interamente "leva minore", replicabile MEGLIO con un semplice target_vol più basso.**
## Verdetto
**DVOL vol-targeting NON migliora TP01.** Risk-adjusted è marginalmente *peggiore* (FULL 0.70 vs
0.75 a parità di DD). L'unico residuo a favore — hold-out +0.06 (max 0.36 vs 0.30) — è **single-window**
su 5 anni scarsi di storia DVOL: sotto la soglia di **persistenza multi-cut** del progetto (la lezione
che ha ucciso 13/14 falsi positivi nello sweep alt). Il gate **DVOL-spike de-risk è RIDONDANTE col
trend**: quando il DVOL esplode (crash) TP01 è già flat (momentum negativo → posizione 0) → il gate
non tocca nulla (Δ 0.00 su tutto). Niente da deployare.
## Lezioni
1. **Per meno DD sul book live, la leva giusta è `target_vol`, non un overlay DVOL.** Abbassare TP01
da vol-tgt 20% → 15% taglia il DD 12.3% → ~9.4% allo **stesso Sharpe** (0.75). Dial pulito e noto,
se mai si volesse un profilo più difensivo (oggi 20% è la scelta canonica — invariata).
2. **La vol implicita non batte la realizzata come denominatore di sizing per un trend long-flat**:
il segnale di trend gestisce già il de-risking direzionale; il denominatore fissa solo la
magnitudine, e la realizzata lo fa marginalmente meglio per unità di rischio.
3. Conferma indiretta del soffitto: anche un raffinamento "ovvio" e *eseguibile* su TP01 non produce
alpha; al massimo sposta il punto sulla stessa frontiera rischio/rendimento.
SCARTATO come miglioria. Nessun impatto sul book live (branch separato, config canonica invariata).
@@ -0,0 +1,47 @@
# 2026-06-26 — Calendar-vol / term-structure DVOL: il DATO STORICO NON ESISTE (data-first gate)
**Goal utente:** "continua" — angolo scelto: scaricare e certificare la term-structure DVOL per
testare un calendar-vol (front IV vs back IV). **Esito: bloccato a monte dal gate "il dato prima
della strategia" (lezione v2.0.0).** Branch `research/gamma-scalp-options`.
Script: `scripts/research/probe_vol_termstructure.py` (scan) + `log_vol_termstructure.py` (forward).
## Scan di fattibilità (prima di costruire qualunque backtest)
Cosa l'API pubblica Deribit espone davvero per la vol per-scadenza:
| dato | disponibile? |
|---|---|
| Snapshot CORRENTE della term-structure ATM (mark_iv per scadenza) | **SÌ** (book_summary_by_currency, tokenless) |
| DVOL storico | solo **30g** fisso — nessun indice 7g/60g/90g pubblico |
| Trade-history IV per strumento | solo per strumenti **VIVI** (gli scaduti spariscono) |
| **Serie storica continua front-vs-back IV** | **NO** — il front-month rotola/espira → irricostruibile |
**Snapshot oggi (2026-06-26), per riferimento:**
- BTC spot $59.9k: 7g 45.6% · 30g 43.2% · 60g 42.7% · 90g 42.9% · 180g 44.5% — **contango** lieve.
- ETH spot $1.58k: 7g 57.6% · 30g 56.4% · 90g 57.5% · 180g 59.2% — contango (+1.6pp slope).
- (I valori sono interpolati a tenor fissi: il front a 1-giorno grezzo, 38%/54%, è rumore escluso.)
## Verdetto
**Un calendar-vol NON è backtestabile ora su dati certificati.** La storia per-scadenza non è
pubblica su Deribit (la nostra fonte di verità), e — coerentemente con la metodologia — **nessun
edge va creduto senza backtest OOS su dati certificati**. Costruire un calendar-vol su uno snapshot
singolo o su una storia ricostruita-a-pezzi sarebbe esattamente il tipo di scorciatoia che ha
prodotto la libreria fasulla v2.0.0. Quindi: **stop, niente backtest.**
## L'unica via legittima: costruire il dato in avanti
`scripts/research/log_vol_termstructure.py` — logger forward idempotente: ogni run prende lo snapshot
ATM, lo interpola ai tenor fissi {7,30,60,90,180}g e appende una riga/asset a
`data/raw/vol_term_<asset>.parquet`. Seminate le prime righe BTC/ETH oggi. Test offline
`tests/test_vol_termstructure.py` (interpolazione pura).
**Non auto-cablato in cron** (è ricerca forward, e non tocco il cron live senza ok). Per accumulare:
aggiungere una riga giornaliera al crontab. Dopo **~6-12 mesi** → certificare (monotonia, spike,
cross-venue) e SOLO ALLORA testare front-vs-back. Prima, nulla.
## Lezione
Il data-first gate ha funzionato: ha fermato un backtest su un dato che non esiste, invece di
produrre un numero non falsificabile. La term-structure è in **contango** oggi (regime calmo) —
osservazione da forward-monitor, non un edge. Nessun impatto sul book live (branch separato).
+118
View File
@@ -0,0 +1,118 @@
# 2026-06-29 — DVOL come segnale DIREZIONALE/REGIME su BTC/ETH: l'unico edge è un HEDGE, non alpha
**Filone A — "DVOL-direzionale".** Tesi: usare la vol IMPLICITA Deribit (DVOL, `data/raw/dvol_*.parquet`,
2021-03→oggi) come **segnale direzionale o di regime** sul perp BTC/ETH (long-flat o L/S sul LIVELLO di
mercato), non come denominatore del vol-target. Script `scripts/research/dvol_directional.py`, test
`tests/test_dvol_directional.py`. Branch `research/equity-meanrev-ib` (separato, nessun impatto live).
## Cosa è diverso dal lavoro DVOL precedente
- `tp01_dvol_overlay.py` (2026-06-26): DVOL come **denominatore** del vol-target → solo de-levering, SCARTATO.
- VOL03/04/10/11 (sweep alt 100-agent): DVOL che **gata/scala un TSMOM** → eredita lo Sharpe di trend di
TP01 (il marginal scorer li boccia NEUTRAL/REDUNDANT).
- `agent_14_dvol_spread` (onda ortho): IV **relativa BTC-vs-ETH**, market-NEUTRAL 2-leg (l'unico LEAD vivo).
Qui invece: DVOL/IV-RV come segnale **direzionale STANDALONE sul livello di mercato**, per vedere se porta
alpha direzionale **ortogonale** a TP01 (non un overlay sul trend). Tutto causale (decisione ≤ `close[i]`,
tenuta in `i+1` dallo shift di `eval_weights`), fee 0.10% RT, vol-target 20%, leva cap 2x, harness onesto
condiviso `altlib`. Allineamento DVOL: `al.dvol` (merge_asof backward) → DVOL close del giorno *t* (≈
contemporaneo a `close[i]`), noto a decisione; verificato leak-free (`causality_ok` max_tail_diff 0.0).
DVOL parte 2021-03 → pre-DVOL il segnale è flat. Valuto sia **FULL** (col flat pre-2021, deflaziona lo
Sharpe) sia **ERA-only** (da 2021-10, equo per la tesi).
## 1) Probe direzionale (corr segnale[i] vs ritorno[i+1], pooled BTC+ETH, era DVOL)
| segnale | corr | long bps | flat bps | **edge bps** | frac_long |
|---|---|---|---|---|---|
| VRP-Z+ (long VRP ricco, IV-RV alto) | +0.010 | +7.8 | 0.9 | **+8.6** | 0.52 |
| VRP-Z (flip) | 0.017 | 0.9 | +7.8 | 8.6 | 0.48 |
| **DVOL-LV fear (rank>0.5 → long)** | **+0.024** | +20.4 | +0.9 | **+19.5** | 0.14 |
| DVOL-LV calm (rank<0.5 → long) | 0.013 | +0.8 | +21.2 | 20.4 | 0.86 |
| DVOL-MOM (DVOL in calo → long) | 0.041 | 10.0 | +22.9 | **32.9** | 0.59 |
| VRP>0 (quasi buy&hold) | +0.003 | +5.3 | 0.7 | +5.9 | 0.72 |
Lettura: l'unico contenuto direzionale reale è **"buy-the-fear"** (long quando il DVOL è alto nel suo
percentile espandente: edge +19.5 bps il giorno dopo). Il VRP-ricco→long è coerente ma debolissimo (+8.6).
Il "DVOL in calo → long" è **negativo** (33 bps): comprare quando la paura scende è perdente (regola
falsificata). Nota: il percentile espandente è dominato dai picchi 2021-22 → "fear" scatta solo nel 14%
delle barre (gli spike veri), non metà del tempo.
## 2) Robustezza assoluta (study_weights 1d, fee sweep 0.00-0.20% RT) — ERA-only il giudizio equo
| segnale | abs | minFull Sh | minHold Sh | feeOK | **ERA Sh** | ERA DD | ERA CAGR |
|---|---|---|---|---|---|---|---|
| **DVOL-fear q0.4 LF** | WEAK | +0.39 | +0.14 | sì | **+0.59** | **8%** | +5% |
| VRP-Z60 LF | FAIL | +0.42 | 0.39 | sì | +0.46 | 23% | +7% |
| DVOL-fear q0.5 LF | FAIL | +0.31 | 0.17 | sì | +0.40 | 10% | +3% |
| VRP-Z90 LF | FAIL | +0.32 | 0.26 | sì | +0.32 | 29% | +4% |
| VRP-Z90 L/S | FAIL | +0.25 | +0.32 | sì | +0.31 | 28% | +3% |
| DVOL-calm q0.5 LF | FAIL | +0.00 | 1.05 | no | +0.09 | 37% | 0% |
| DVOL-MOM k10/k20 LF | FAIL | 0.6/0.7 | <1 | no | 0.6/0.7 | ~40% | ~10% |
| DVOL-MOM k10 L/S | FAIL | 1.16 | 1.29 | no | 1.23 | 72% | 23% |
Nessun segnale supera lo Sharpe assoluto in **valore** (tutti < 0.6, soffitto direzionale BTC/ETH ~1.3
confermato). Unico con profilo decente: **DVOL-fear q0.4 long-flat** (ERA Sh +0.59, DD **8%**) — il DD
bassissimo perché è long solo nei picchi di paura (poche barre, mean-reversion). Le famiglie momentum e
"buy-the-calm" sono nettamente negative e non sopravvivono nemmeno alle fee.
## 3) Marginal vs TP01 (il gate vero) — DVOL-fear q0.4 long-flat
| | corr→TP01 | in-sample Sh | uplift_full w25 | uplift_hold w25 | multi-cut persistente | is_hedge | verdetto |
|---|---|---|---|---|---|---|---|
| **ERA-only** (2021-10+) | 0.37 | 0.54 (has_edge) | +0.06 | +0.17 | sì | **No** | **ADDS** (earns_slot=True) |
| **FULL** (gate ufficiale) | 0.28 | 0.64 (has_edge) | +0.03 | +0.17 | sì | **Sì** | **HEDGE** (earns_slot=**False**) |
Il candidato ha tutto ciò che serve a un nuovo sleeve **tranne una cosa**: il gate canonico full-history
lo classifica **HEDGE**, non alpha. `hedge_yearly_corr(TP01-Sh, uplift) = 0.76`, `uplift TP01-up 0.003`
/ `uplift TP01-down +0.194`**paga SOLO quando TP01 è debole**. Ha perfettamente senso: il DVOL esplode
durante i crash, proprio quando il trend di TP01 è flat/in-drawdown; comprare la paura cattura il rimbalzo
e smorza il DD del portafoglio, ma **non è un premio permanente**. Il blend 0.75·TP01 + 0.25·cand alza
l'hold-out 0.30→**0.47** (w50 → 0.62) e taglia il DD a ~11%/8% — un effetto **drawdown-dampener** reale,
ma classificato (giustamente) come hedge.
Perché ERA dice ADDS e FULL dice HEDGE: il rivelatore di hedge richiede ≥3 anni; sulla finestra ERA
(2021-10+) la `corr(TP01-Sh annuale, uplift)` è meno netta e non scatta. **Il gate full-history è quello
giusto** (più dati per il test di hedge) → mi attengo a quello: **HEDGE, non alpha.**
Gli altri tre candidati (VRP-Z60/90, DVOL-fear q0.5): **NEUTRAL o HEDGE**, mai ADDS. I VRP-Z hanno beta a
TP01 alto (0.88-0.90) → sono trend-correlati travestiti (resid Sharpe ~0), uplift hold-out negativo.
## 4) Causalità, alignment, eseguibilità, sign-falsification
- **Causale**: `causality_ok` ok=True, max_tail_diff **0.0** su tutti i candidati (rank espandente +
z-score ricalcolati su prefisso = identici → nessun future-peeking). Test dedicato `test_expanding_rank_is_causal`.
- **Alignment DVOL**: laggando il segnale di +1 giorno (extra-conservativo, usa solo DVOL di ieri) l'ERA
Sharpe del leader scende +0.59 → **+0.45**. L'edge sopravvive ma è **sensibile all'allineamento**
(parte del vantaggio è nel reagire allo spike DVOL del giorno stesso) → cautela in esecuzione.
- **Eseguibile a $600**: `eval_weights_smallcap` (min_order $5, cap $300/asset): haircut Sharpe **≈ 0.00**
su BTC ed ETH (segnale long-flat a basso turnover, ~210-270 trade su tutta la storia) → lo Sharpe netto
onesto a $600 = quello modellato. È l'unico aspetto pienamente promosso.
- **Sign-falsification**: tesi buy-the-fear ERA Sh +0.40 vs flip buy-the-calm +0.09; VRP-Z+ +0.32 vs
VRP-Z (flip) 0.14. Il segno della tesi è quello giusto (l'edge è reale, non rumore simmetrico).
## Verdetto onesto: **LEAD (hedge / drawdown-dampener), NON sleeve.** SCARTATO come alpha direzionale.
- Nessun segnale DVOL-direzionale ha Sharpe assoluto sopra ~0.6 → **conferma il soffitto BTC/ETH
direzionale ~1.3** (la via per superarlo resta il cross-sectional XS01, non un nuovo segnale a 2 asset).
- L'unico con edge in-sample reale + eseguibile + leak-free è **DVOL-fear "buy-the-fear" long-flat**, ma il
gate canonico lo bolla **HEDGE** (`is_hedge=True`, paga solo quando TP01 è in difficoltà). Per la regola
del progetto un hedge **non si arma come slot di alpha****earns_slot=False**.
- È comunque un **LEAD utile in forward-monitor** come **smorzatore di drawdown** del portafoglio: il blend
porta l'hold-out 0.30→0.47/0.62 e abbassa il DD. Se in futuro si vorrà esplicitamente un tail/DD-hedge
*eseguibile* (a differenza del tail-hedge in opzioni, non eseguibile a $600), questo è il candidato più
pulito visto finora — ma da prezzare **come hedge**, non come ritorno atteso permanente.
## Caveat
1. **Storia DVOL <5 anni** (2021-03→oggi, ~4.7 anni; era valutata 2021-10+) → multiple-testing e
finestra corta. Il multi-cut 2026 è un assurdo +1.944 (manciata di giorni, picco DVOL recente):
l'uplift hold-out è trascinato dal regime 2025-26 ad alta-paura, non da un edge stazionario.
2. **È un hedge, non alpha**: il valore è condizionato ai drawdown di TP01 (2022, ed eventuali futuri).
In un toro lungo a bassa vol il segnale resta **flat l'86% del tempo** e non contribuisce nulla.
3. **Sensibile all'allineamento** DVOL (haircut 0.14 Sharpe col lag +1g): l'esecuzione reale dovrebbe
usare il DVOL già stampato a decisione, non assumere il close contemporaneo.
4. Long-flat → cattura il rimbalzo post-paura ma **non protegge** durante la discesa (non è uno short):
è "buy-the-dip gated by fear", con tutti i rischi del comprare coltelli che cadono se il regime peggiora.
Nessun impatto sul book live (branch separato, nessuno sleeve registrato, config canonica invariata).
+145
View File
@@ -0,0 +1,145 @@
# 2026-06-29 — Filone B: INTRADAY REGIME BTC/ETH — ERM (efficiency-ratio) è un LEAD reale, forward-monitor
**Tesi.** Cercare un meccanismo **sub-daily** sui dati certificati 1h→12h BTC/ETH che sia ortogonale
**sia** a TP01 (TSMOM trend daily, long-flat) **sia** a SKH01 (regime BuzVola/BuzVolume + Donchian a
230m). SKH01 prova che il sub-daily PUÒ funzionare ed essere quasi-ortogonale: qui un MECCANISMO DIVERSO,
basato sulla **qualità del moto intraday** (efficiency-ratio / vol-expansion / thrust) come **regime** che
condiziona una posizione direzionale tenuta ~1 giorno. Script `scripts/research/intraday_regime.py`, test
`tests/test_intraday_regime.py`. Branch `research/equity-meanrev-ib` (separato, nessun impatto live).
Killer ricorrente del progetto sotto le 12h = **muro-fee 0.10% RT + overfitting**. Ricetta SKH01:
decisione sub-daily ma **hold ~1 giorno** → pochi trade → la fee non uccide. Ogni meccanismo qui è
costruito a basso turnover e giudicato col **fee-sweep alla sua frequenza reale**.
## Meccanismi provati (tutti come posizione CONTINUA decisa ≤ `close[i]`, causali)
| | meccanismo |
|---|---|
| **ERM** | **Efficiency-Ratio regime momentum** (Kaufman): ER = \|moto netto su L barre\| / \|percorso\|. Prendi la direzione del moto netto **solo quando ER ≥ soglia** (regime intraday "pulito"/trendy), altrimenti flat |
| VEM | Vol-Expansion Momentum: direzione = segno del moto, attiva solo quando vol-corta > vol-lunga |
| VBR | Volatility/thrust breakout (Larry-Williams ROLLING, no calendario): segui i moti > k·ATR |
| TOD | Time-of-day seasonality — **CONTROLLO calendario**, incluso APPOSTA per `day_boundary_robust` |
## Selezione + fee-sweep a frequenza reale (vincitori per famiglia, min-asset)
```
ERM: 8h L=2.0 thr=0.35 L/S minFull +0.88 minHold +0.99 f@.20 +0.55 feeOK=True turn/y 125
VEM: 12h Lmom=3 Ls=2 Ll=10 minFull +0.72 minHold -0.29 f@.20 +0.51 feeOK=True (hold<0 → out)
VBR: 12h k=1.0 atr=14 L/S minFull +0.33 minHold +1.20 f@.20 +0.25 feeOK=True
TOD: 1h minFull -3.99 minHold -4.49 feeOK=False (controllo → FAIL atteso)
```
Solo **ERM** e **VBR** sopravvivono al gate fee+OOS. VEM ha hold-out negativo. TOD esplode (vedi sotto).
## Il candidato: ERM 8h L=2.0 thr=0.35 (L/S) — `earns_slot=True`
```
abs=PASS marginal=ADDS EARNS_SLOT=True
standalone: cand FULL 0.919 / HOLD 1.105 (TP01 ref FULL 1.297 / HOLD 0.303)
corr->TP01 full 0.146 hold 0.057 beta 0.197 resid Sharpe 0.738 alpha/yr 0.121
robust_oos=True (clean-year +0.103, drop-best-month +0.283)
multi-cut persistence: 2020 .166 / 2021 .167 / 2022 .298 / 2023 .337 / 2024 .418 / 2025 .497 / 2026 2.861 persistent=True
has_insample_edge=True (standalone PRE-holdout Sharpe 0.874, > null-pctl 0.317)
is_hedge=False (yearly corr(TP01-Sh, uplift) -0.762; paga sia TP01-up 0.139 sia TP01-down 0.384)
blend w25: FULL 1.481 (+0.184) HOLD 0.80 (+0.497) DD 11.0%
corr con SKH01: full 0.278 hold 0.291
day_boundary=INVARIANT (spread 0.0) haircut $600 ≈ 0.00 su BTC/ETH
```
È il **primo sub-daily da SKH01** a passare TUTTI i gate del marginal scorer indurito: edge in-sample
reale (non diversification-math), persistenza multi-cut, robust_oos, NON hedge, scorrelato a TP01 (0.15).
### ERM aggiunge OLTRE SKH01? (gate #5 — il book esistente ne ha già uno sub-daily)
| blend | FULL Sh | FULL DD | HOLD Sh | HOLD DD |
|---|---|---|---|---|
| TP01 | +1.30 | 14.3% | +0.30 | 7.5% |
| TP01+SKH 75/25 | +1.78 | 9.4% | +1.17 | 6.2% |
| **TP01+SKH+ERM 60/25/15** | **+1.88** | 8.9% | **+1.46** | 5.3% |
| TP01+SKH+ERM 55/20/25 | +1.84 | 8.8% | +1.48 | 5.1% |
Sì: corr con SKH01 solo 0.28 → ERM **aggiunge oltre SKH** (FULL +0.10, HOLD +0.29 a peso 15%, DD ancora
giù). Non è SKH01 travestito.
## Il controllo TOD (calendario) — fa esattamente ciò che doveva
`TOD` (direzione per ora-del-giorno, media espandente causale) è incluso come **trappola**: è il tipo di
effetto che uccise `open_drive` (artefatto di etichettatura UTC). Esito: **FAIL** (FULL 3.99, 31.811
trade, fee-killed), marginal=DILUTES. `day_boundary_robust=INVARIANT` → l'effetto è **robustamente
negativo** a ogni offset (non un artefatto di confine giorno: è proprio che la time-of-day-direzionale non
ha edge e sanguina fee). Il controllo conferma che l'harness non si fa ingannare e che il segno
dei segnali di prezzo (ERM/VBR) è reale, non rumore di calendario.
## Causalità / eseguibilità
- **Leak-free**: `causality_ok=True`, max_tail_diff **0.0** su tutti i candidati (ER, rank espandente,
medie su prefisso = identiche → nessun future-peeking). Test dedicato in `test_intraday_regime.py`.
- **day_boundary_robust=INVARIANT** (spread 0.0) per ERM/VBR/TOD: segnali di prezzo, non di calendario.
- **Eseguibile a $600**: `eval_weights_smallcap` haircut **≈ 0.00** su BTC ed ETH. **MA** ERM a 8h fa
~3.158 trade BTC / ~2.823 ETH su tutta la storia (turnover 125/anno): haircut nullo nel modello, ma
l'esecuzione reale sub-daily sul book è operativamente più pesante di un segnale 1d (slippage/spread
intraday non interamente catturati dalla fee proporzionale).
## Caveat (perché LEAD, non sleeve)
1. **Plateau hold-out a UNA SOLA RIGA.** Il FULL è robusto su tutta la griglia L∈[2.0,3.0] (+0.6..+1.0),
ma l'**hold-out è positivo SOLO a L=2.0** (a L=2.5/3.0 crolla a 0.5..0.8). Il plateau sul full è
ampio, quello che conta — l'hold-out — è single-row. Da rinforzare prima di credere alla stazionarietà.
2. **Standalone FULL 0.92 < soffitto ~1.3.** Coerente col soffitto direzionale BTC/ETH: il valore di ERM
è **marginale/diversificante** (corr 0.15 a TP01, 0.28 a SKH01), non assoluto. Non rompe il soffitto.
3. **Multiple-testing non deflazionato.** 102 celle testate (60 ERM + 16 VEM + 24 VBR + 2 TOD) senza
deflated-Sharpe (a differenza del filone C). Il multi-cut 2026 = +2.861 è una manciata di giorni che
gonfia. Storia sub-daily certificata utile ~quanto SKH01 → finestra non lunghissima.
4. **Esecuzione 8h** = complessità operativa reale (vedi sopra), oltre il modello a haircut nullo.
## Analisi di robustezza / de-bias (`intraday_regime_analysis.py`) — il lead NON regge
I caveat #1 (plateau hold-out single-row) e #3 (multiple-testing) erano i sospetti giusti. Tre test di
de-bias li trasformano da sospetto in **bocciatura** dello slot:
| test | esito |
|---|---|
| **A) Deflated-Sharpe** (Bailey & Lopez de Prado) su 122 trial cercati | **FAIL.** DSR 0.000 (tutti) / **0.163 (escludendo i trap TOD)** / 0.241 (solo-ERM) — tutti ≪ 0.95. Lo Sharpe winner (0.92) è sotto lo Sharpe-max-atteso-null (1.162.51): il search ha trovato celle a 1.6 full / 1.7 in-sample, il winner 0.92 **non è eccezionale**. |
| **B) Selezione IN-SAMPLE-only** (scelgo la cella ERM col solo Sharpe < 2025) | **earns_slot=False.** La cella migliore pre-hold-out è un'**ALTRA** (8h L=2.0 thr=0.4 **long-flat**), con corr→TP01 **0.53** (è trend-beta travestito) → marginal=**NEUTRAL**. Il winner max-hold **non si seleziona senza guardare l'hold-out** → il suo `earns_slot=True` era **selezione-sull'hold-out**. |
| **C) Ensemble del plateau** (media 20 celle L×thr, niente cherry-pick) | **earns_slot=False.** marginal=ADDS, in-sample Sh 1.01, corr→TP01 0.18 — ma **`robust_oos=False`** (clean-year + jackknife): l'uplift hold-out è trascinato dal **2026 (+2.09 multicut)**, manciata di giorni. |
**Dove vive l'(eventuale) edge** (per-anno, blend 3-way 60/25/15 vs 2-way 75/25): uplift FULL solo **+0.10**,
**negativo nel 2021 (0.23) e 2022 (0.15)**, positivo altrove; l'uplift HOLD **+0.30 è concentrato nel
2026 (+0.46)**. corr(ERM,SKH) 0.28 full (fino a 0.42 in alcuni anni) → **parziale sovrapposizione con SKH**,
non ortogonalità piena.
**Lettura.** Il segnale efficiency-ratio non è rumore puro (l'ensemble ha in-sample Sh ~1.0, positivo nella
maggior parte degli anni), ma come **slot** fallisce ogni de-bias: il `earns_slot=True` della scoperta era
prodotto da **(1) selezione della cella sull'hold-out** + **(2) coda 2026** + **(3) multiple-testing non
corretto**. È lo stesso falso-positivo che l'alt-sweep 100-agent imparò a uccidere — qui ucciso dai gate.
## Caveat originari (ora risolti dall'analisi sopra)
1. ~~Plateau hold-out single-row~~**confermato fatale**: l'edge hold-out a L=2.0 è cell-selection.
2. ~~Multiple-testing non deflazionato~~**deflazionato: DSR FAIL** anche senza i trap.
3. Esecuzione 8h: irrilevante ormai (lo slot non c'è).
## Verdetto onesto: **NON è uno slot. Falso positivo da selezione-hold-out + coda 2026.** SCARTATO come sleeve.
Lo "earns_slot=True" della scoperta **non sopravvive** alla de-selezione: deflated-Sharpe FAIL (anche
escludendo i controlli), selezione in-sample-only → NEUTRAL su un'altra cella (trend-beta corr 0.53),
ensemble del plateau → robust_oos FAIL. **Conferma ennesima del soffitto direzionale BTC/ETH ~1.3**: un
segnale a 2 asset non lo supera; la via resta il cross-sectional (XS01). Resta al più una **curiosità in
forward-monitor** (l'efficiency-ratio ha un debole edge in-sample reale), ma da non armare come alpha.
Gli altri tre meccanismi: VBR=NOISE, VEM hold-out<0, TOD=controllo FAIL come atteso.
**Lezione harness (CODIFICATA).** Lo script di scoperta selezionava il vincitore per `min_hold` massimo
sulla griglia = **selezione-sull'hold-out**, il punto cieco che ha generato il falso PASS. Il marginal
scorer da solo non basta se la *cella* è scelta guardando l'hold-out: serve **(a)** scegliere la cella
in-sample-only (o walk-forward) **prima** di valutare il marginal, e **(b)** deflazionare per il numero di
celle/famiglie testate. Stesso buco segnalato per CC01 ("Sharpe implausibile") e per l'alt-sweep
(hold-out-fitting): qui in forma "selection-on-holdout". Ora è **codice** in `altlib` (LESSON 4): tre
funzioni nuove — `deflated_sharpe()` (Bailey & Lopez de Prado), `select_cell_insample()` (scelta cella
col solo Sharpe pre-HOLDOUT), e il gate combinato **`study_family_honest()`** (`earns_slot_honest =
earns_slot[cella in-sample] AND deflated-Sharpe≥0.95`). Verificato: su ERM il gate ritorna
`earns_slot_honest=False` (cella in-sample = trend-beta NEUTRAL, DSR 0.74). Analisi completa in
`scripts/research/intraday_regime_analysis.py`; test in `tests/test_harness_realism.py`.
**Regola nuova: una strategia direzionale grid-searched si giudica con `study_family_honest`, non
chiamando `study_marginal` sulla cella a max hold-out.**
Nessun impatto sul book live (branch separato, config canonica invariata).
@@ -0,0 +1,71 @@
# 2026-06-29 — Filone D: MACRO regime-gate sul book crypto — RIDONDANTE col trend, SCARTATO
**Tesi.** Usare segnali macro/cross-market — equity (SPY/QQQ/IWM), credito (HYG/LQD), oro (GLD/SLV),
tassi (TLT/IEF) — come **gate risk-on/risk-off** sul book BTC/ETH, per migliorare il *timing* del
drawdown di TP01: regime risk-off (credito che cede, equity sotto trend, fuga sui bond) → riduci/azzera
l'esposizione crypto; risk-on → lascia agire TP01. **È eseguibile** (gata solo BTC/ETH perp, non aggiunge
gambe). Script `scripts/research/macro_regime_gate.py`, test `tests/test_macro_regime_gate.py`. Branch
`research/equity-meanrev-ib` (separato, nessun impatto live). Dati: `data/raw/eq_*_1d.parquet` (ETF daily,
allineati causale `merge_asof backward` sul calendario SPY).
**NON è un lead-lag direzionale** (già morto: diari 2026-06-22/-23). L'angolo nuovo = un overlay
binario/continuo di **de-risk** sul book esistente.
## Il rischio noto in partenza (CLAUDE.md)
La lezione DVOL-spike (2026-06-26): un gate di de-risk rischia di essere **ridondante col trend** — TP01
è già long-flat e va a 0 nei crash (Δ 0.00). Questo script DOVEVA dimostrare che il gate aggiunge **oltre**
quel che TP01 fa da solo. **Non ci riesce.**
## Gate provati (tutti causali: SMA/ratio/z-score rolling, merge_asof backward)
`SPY>MA{50,100,150,200,250}`, `HYG>MA`, ratio di credito `HYG/LQD`, `HYG/IEF`, combo a maggioranza
(SPY+HYG+HYG/LQD, binario e continuo), flight-to-quality (`TLTup&SPYdn`, `GLDup&SPYdn`), regime di vol
equity `SPYvol_z1` (proxy "VIX-spike" senza VIX). g_off ∈ {0.0, 0.5}.
## Esiti
I gate di trend equity alzano lo Sharpe FULL della combo (SPY>MA150/200/250 → FULL ~1.22-1.25 vs TP01-solo
1.30) ma **non l'hold-out** (HOLD ~0.17-0.19) → è **de-levering**, non timing: tagliano DD spegnendo il
book in mercati equity laterali, non anticipando i crash crypto. Il miglior profilo DD è `SPYvol_z1`.
### Deep-dive `SPYvol_z1` — il controllo decisivo (ridondanza col trend)
| | exposure TP01 risk-off | exposure risk-on | giorni risk-off | **giorni in cui il gate LAVORA** | corr(1-gate, 1-expo) |
|---|---|---|---|---|---|
| BTC | 0.023 | 0.093 | 18% | **3%** | 0.278 |
| ETH | 0.013 | 0.068 | 16% | **2%** | 0.296 |
"Il gate lavora" = giorno risk-off **E** posizione TP01 non già flat. Accade nel **2-3% dei giorni**: nel
resto, quando il gate vorrebbe de-riskare, TP01 è **già flat da solo**. Il gate spegne un motore già spento.
### Marginal scorer vs TP01 (gate come candidato-sleeve)
```
abs=FAIL marginal=REDUNDANT EARNS_SLOT=False
corr->TP01 full 0.989 hold 0.984 beta 0.978 resid Sharpe 0.739
multi-cut persistent=True has_insample_edge=True (standalone 1.634) is_hedge=False
blend w25: full 1.323 (+0.026) hold 0.257 (-0.046) blend w50: full 1.348 (+0.051) hold 0.21 (-0.093)
```
corr→TP01 **0.989**, beta 0.98: lo stream gated **È** TP01. L'uplift hold-out è **negativo** (de-levering
che toglie ritorno fuori dai crash). overlay-delta (gatedsolo) come stream a sé: `verdict=NEUTRAL`.
## Causalità / eseguibilità (gli unici aspetti promossi)
- **Leak-free**: `causality_ok=True` (max_tail_diff 0.0); STRICT align (1 barra equity extra di lag) →
FULL invariato; `day_boundary_robust=INVARIANT` (spread 0.0). Allineamento macro→crypto backward-only.
- **Eseguibile a $600**: haircut `eval_weights_smallcap`**0.00** su BTC ed ETH. Fee-survivente
(0.00→0.30% RT: 1.42→1.33). Tecnicamente impeccabile — semplicemente **non aggiunge alpha**.
## Verdetto: **SCARTATO (ridondante col trend).** earns_slot=False.
Conferma esatta della lezione in CLAUDE.md: un overlay di de-risk su un book che è **già** long-flat e
già a 0 nei crash non ha quasi nulla da fare (lavora il 2-3% dei giorni, corr→TP01 0.99). Il taglio di DD
che mostra è **de-levering**, replicabile meglio con un `target_vol` più basso (stessa lezione del
TP01×DVOL overlay del 2026-06-26). Il macro-regime **non anticipa** i drawdown crypto meglio del prezzo
crypto stesso. Nessuno sleeve registrato; nessun impatto sul book live.
**Sottoprodotto utile:** il gate `redundancy_diag` (exposure risk-off vs risk-on + "quota giorni in cui il
gate lavora") è il test pulito da riusare ogni volta che si propone un overlay di de-risk — se "il gate
lavora" è basso e corr→TP01 ~1, è ridondante, a prescindere dallo Sharpe FULL che mostra.
@@ -0,0 +1,106 @@
# 2026-06-29 — Ricerca strategie a 5 thread paralleli: 0 nuovi sleeve, 1 LEAD che rompe 2 muri su 3
**Mandato.** "Cerca altre strategie" (+ "senza correlazioni, a segnale" + "a 1 gamba in/out a segnale").
Cinque ricerche parallele su aree genuinamente inesplorate, tutte sull'harness onesto condiviso
(`altlib` + `xsec_v2_nonmom`) con TUTTI i gate: causalità (prefix-check), netto fee 0.10% RT + sweep,
OOS hold-out 2025+, **deflated-Sharpe** (multiple-testing), **gate anti-selection-on-holdout**
(`study_family_honest`: cella scelta IN-SAMPLE-only), marginal vs TP01/XS01, corr vs book, haircut $600.
Branch `main`, **nessun impatto live** (solo file nuovi, nessuno sleeve registrato).
Premessa onesta (base-rate): il soffitto direzionale BTC/ETH ~1.3 è già confermato e lo sweep di 104
ipotesi (2026-06-20) non produsse nulla di nuovo che reggesse. L'attesa era "quasi tutto SCARTATO".
## Esiti per thread
| # | Thread | File | Verdetto |
|---|--------|------|----------|
| 1 | **XSEC low-risk cousins** (MAX/lottery, idio-vol, Amihud) | `xsec_v3_lowrisk.py` | 1 LEAD (IVOL), 0 sleeve |
| 2 | **XSEC momentum-structure** (risk-adj/accel/frog-in-pan/vol-managed vs XS01) | `xsec_v3_momstruct.py` | tutto REDUNDANT/SCARTATO |
| 3 | **Meta-allocazione** (allocazione dinamica tra i 4 sleeve) | `meta_allocation.py` | pesi fissi vincono |
| 4 | **Segnali ortogonali ETH/BTC** (relative-value dollar-neutral) | `orthogonal_signals.py` | 2 LEAD (STATARB, DVOLSPREAD) |
| 5 | **1-gamba a segnale** (MACD/RSI/Supertrend/Donchian/BBands/EMA) | `signal_inout_1leg.py` | 0/12 earns_slot |
**Netto: 0 nuovi sleeve.** Il soffitto regge. Test 143/143.
### Thread 1 — Low-risk cross-sectional (51 alt HL)
Tre fattori mai provati (il filone C aveva fatto total-vol e BAB, non questi). **IVOL** (idiosyncratic-vol
basso, 19-major B30 H5 k8): FULL 1.06 / HOLD **1.22** / corr ~0 a XS01 e TP01 / positivo ogni anno /
uplift portafoglio HOLD +0.42/+0.50 — l'unico LEAD di valore. **MAX** e **AMIHUD-liquido** sono lo stesso
tema "evita speculativo/illiquido/volatile" in altre vesti (corr fra loro 0.33-0.59). **AMIHUD
long-illiquido SCARTATO** (premio illiquidità invertito in crypto: vincono i major liquidi). Bocciatura
del claim forte: **deflated-Sharpe 0.30-0.37 ≪ 0.95** (96 trial), storia ~2.5 anni, book 10-16 gambe →
**STAT-MODE**. Nota di rigore: il naive best-HOLD atterrava su celle in-sample-negative (holdout-fitting) →
l'agente ha auto-aggiunto il gate has_insample_edge. → **forward-monitor IVOL**.
### Thread 2 — Momentum-structure vs XS01
4 varianti (risk-adjusted, acceleration, frog-in-pan, vol-managed). **Nessuna batte né diversifica XS01**
(standalone 1.42). Sostituire XS01 con una variante **distrugge l'hold-out** del portafoglio (0.58…−1.38)
— prova diretta che l'edge di XS01 sta nella sua struttura SPECIFICA (blend z-score [30,90] + gate
dispersione), non in varianti generiche. Deflated-Sharpe max 0.49. Tutte REDUNDANT/SCARTATO.
### Thread 3 — Meta-allocazione dinamica
Vol-parity / momentum-of-sleeves / dispersion-regime / drawdown-control vs pesi fissi, con costo di
ribilancio realistico. **Nessuno batte i pesi fissi OOS.** Vol-parity = trappola da manuale (+0.09…+0.44
sui tagli in-sample 2022-24, **0.11 sull'hold-out 2025** → intercettato dal multi-cut). Drawdown-control
RIDONDANTE (TP01 va già flat nei crash, il gate non si attiva mai). I 4 sleeve sono già quasi-scorrelati
(corr ~0.12 max) → i pesi fissi sono già vicini al risk-parity ottimo statico. **Mantenere i pesi fissi.**
### Thread 4 — Segnali ortogonali ETH/BTC (il risultato più notevole)
Relative-value dollar-neutral sul ratio log(ETH/BTC): 6 segnali, evaluator a 2 gambe (fee × 2), cella
scelta in-sample-only.
| segnale | FULL/HOLD | corr→book | β-mkt | marginal | DSR (grid/same-sign) | exec $600 | verdetto |
|---|---|---|---|---|---|---|---|
| **STATARB-RESID** (residual relative-mom ETH−β·BTC, W45 **sgn+1**) | 0.84/0.56 | **0.027** | 0.013 | **ADDS** | 0.056 / 0.929 | haircut ~0 | **LEAD** |
| DVOLSPREAD (IV relativa, W60) | 0.74/0.77 | 0.017 | 0.012 | ADDS | 0.082 / 0.907 | haircut ~0 | LEAD |
| RATIO-MOM/REV/ACCEL | 0.25-0.68 / ≤0 | ~0 | ~0 | NEUTRAL | <0.23 | ok | NEUTRAL (diversification-math) |
| VOLSPREAD | 0.24/1.47 | ~0 | 0.013 | DILUTES | — | — | SCARTATO |
**STATARB-RESID rompe 2 dei 3 muri storici:** è **ortogonale per costruzione** (corr→book 0.027, beta di
mercato 0.013 — meglio di SKH ~0.09) **ED eseguibile a $600** (book a 2 gambe BTC+ETH perp Deribit,
haircut ≈ 0, fee-survive fino a 0.30%/gamba → **NON STAT-MODE**, a differenza di XS01 e delle opzioni). Il
muro che **resta** è l'**edge**: Sharpe 0.84 / DSR 0.929 same-sign (ottimistico) ma comunque <0.95.
Verificato indipendentemente dal coordinatore: residuo causale (β OLS rolling backward, decisione a
close[i], return in i+1), fee a 2 gambe corretta. **⚠ Correzione di etichetta:** la cella vincente è
**sgn=+1**, NON sgn=1 → NON è mean-reversion ma **momentum relativo sul residuo** (long lo spread quando
ETH è ricco vs il suo fit su BTC: le dislocazioni ETH-vs-BTC *continuano* a 1d; la MR pura sgn=1 perde
1.4 in-sample). L'ortogonalità (β~0) viene dalla struttura dollar-neutral, non dal verso. → **LEAD
forward-monitor** (monitorabile a costo reale ~0), NON deploy. **CABLATO:** `scripts/live/paper_statarb.py`
(config CONGELATA W=45/sgn=+1, doppio libro MODELED/REAL-$600, riusa il segnale esatto di
`orthogonal_signals.py`), aggiunto al cron giornaliero accanto a `paper_prevday`; test `tests/test_paper_statarb.py`.
**DVOLSPREAD** ri-valida l'ex-lead `dvol_spread`: ADDS ma storia DVOL corta (2021+) → resta forward-monitor
come già noto. Secondario crypto-vs-macro = "TSMOM travestito" (corr→book 0.17-0.20), non ortogonale.
### Thread 5 — 1-gamba a segnale (eseguibile)
12 famiglie (MACD/RSI/Supertrend/Donchian/BBands/EMA, ±ADX) su 1d/12h/8h. **0/12 earns_slot_honest.**
**Eseguibilità validata** (haircut $600 = 0 ovunque; RSI-MR ~2.5 trade/anno) — ma è l'unica cosa che
regge. I trend-follower sono **TP01 travestito** (corr 0.44-0.79, full ~1.2-1.3 = il soffitto) e le celle
sub-daily scelte in-sample **collassano OOS** (dimostrazione da manuale del gate selection-on-holdout). La
mean-reversion è morta (BBands-MR has_insample_edge=False). I "low-corr interessanti" (RSI-MR, MACD-LS,
Donchian-LS) sono **HEDGE non alpha** (`is_hedge=True`, pagano solo quando TP01 è debole), e con
deflated-Sharpe <0.95 (RSI-MR 0.861; Donchian-LS passa DSR ma is_hedge). **A $600 un 1-gamba a segnale è
eseguibile ma non aggiunge nulla a TP01.**
## Sintesi / cosa ho imparato
1. **0 nuovi sleeve, soffitto ~1.3 riconfermato** dal lato direzionale e dal lato struttura-momentum. La
ricerca è onesta: ogni candidato è stato ucciso dal gate giusto (deflated-Sharpe, is_hedge,
selection-on-holdout, sostituzione-XS01, multi-cut), non da un giudizio a occhio.
2. **Il LEAD di valore è STATARB-RESID** (ETH/BTC residual mean-reversion). È il primo stream visto che è
**insieme ortogonale (β~0) ED eseguibile a 2 gambe** — cadono i due muri che bloccano XS01 (STAT-MODE)
e le opzioni. Manca solo l'edge sopra-soglia. È il candidato n.1 per il **forward-monitor**, e l'unico
che — se la finestra forward confermasse l'edge — sarebbe *deployabile* a $600 (non statistico).
3. **Forward-monitor (STAT-MODE / sub-soglia):** IVOL (idio-vol XS, 19-major), DVOLSPREAD (storia corta),
STATARB-RESID (eseguibile — il più promettente). Nessuno armato come sleeve.
4. **I gate nuovi funzionano:** `study_family_honest` (selection-on-holdout) ha intercettato i collassi
OOS dei trend 1-gamba e dei low-risk XS; il deflated-Sharpe ha tenuto sotto la soglia ogni Sharpe ~1
su storia corta. La lezione del filone B (de-bias prima di credere) è ora applicata di default.
## Caveat
- Universi/finestre: HL ~2.5 anni, DVOL dal 2021 → multiple-testing reale; tutti i LEAD sono sotto la
soglia deflazionata. Niente di questo va creduto come alpha finché una finestra forward non lo conferma.
- Nessuno sleeve registrato, config canonica invariata (TP01+XS01+VRP01+SKH01 a pesi fissi). Book live
intatto. Tutto il lavoro è statistico/forward, su `main` come ricerca.
Script: `scripts/research/{xsec_v3_lowrisk,xsec_v3_momstruct,meta_allocation,orthogonal_signals,signal_inout_1leg}.py`.
Test: i rispettivi `tests/test_*.py` (143/143 verdi).
+65
View File
@@ -0,0 +1,65 @@
# 2026-06-29 — Filone C: cross-sectional NON-momentum su Hyperliquid — DEBOLE / forward-monitor
**Tesi.** XS01 (sleeve attivo) è momentum cross-sectional sui 19 major HL. Lezione del progetto
(2026-06-19/20): **espandere il numero di asset NON aiuta il momentum** (gli small-cap diluiscono/
invertono il segnale). Quindi qui NON si ri-prova l'espansione-universo: si cerca un **meccanismo
DIVERSO dal momentum** che, market-neutral e scorrelato, possa diversificare il portafoglio. Script
`scripts/research/xsec_v2_nonmom.py`, test `tests/test_xsec_v2.py`. Branch `research/equity-meanrev-ib`.
## Meccanismi provati (tutti L/S dollar-neutral, vol-target ~20%, ribilancio periodico, CAUSALI)
| | meccanismo |
|---|---|
| REV | short-term reversal grezzo (long loser / short winner di breve) |
| IREV | reversal **idiosincratico** (sul residuo dopo aver tolto il mercato, beta-adjusted) |
| LOWVOL | factor **low-vol** (long bassa vol realizzata / short alta vol) |
| IMOM | momentum **idiosincratico** (sul residuo, ≠ raw mom) — *riferimento* |
| BAB | betting-against-beta (long basso beta / short alto beta) |
| MOM | momentum grezzo — *riferimento* |
Universi: **19 major** e **51 all** (i parquet certificati). Gate canonico di selezione: FULL>0.5,
HOLD>0, |corr→XS01|<0.6 (escluse le famiglie momentum MOM/IMOM, che sono riferimento, non candidati).
## Esiti — un solo candidato non-momentum supera il gate standalone
```
[OK] LOWVOL 19-major B30 H10 k5 FULL +1.07 HOLD +1.07 DD 19% corrXS +0.16 corrTP -0.28
[--] BAB 19-major B60 H10 k8 FULL +0.47 HOLD +1.15 DD 28% corrXS +0.20 corrTP -0.27
[--] REV/IREV (19 e 51) FULL ~0 o NEGATIVO (reversal cross-sectional non paga)
[--] LOWVOL 51-all FULL +0.42 (il long-tail diluisce, come per il momentum)
```
- **REV / IREV negativi** (FULL 0.10..0.70): il reversal cross-sectional grezzo o idiosincratico **non
è un edge** su questo universo/finestra — coerente con la morte storica del mean-reversion del progetto.
- **BAB** ha un buon hold-out ma FULL solo +0.47 (sotto soglia) e DD 28%.
- **LOWVOL 19-major** (betting-against-vol) è l'unico idoneo: FULL **1.07** / HOLD **1.07** / DD 19%,
causale (max_tail_diff 0), corr→XS01 +0.16 (scorrelato), corr→TP01 0.28.
- Espandere a **51 asset peggiora** anche il low-vol (FULL 1.07→0.42): riconferma che i margini
cross-sectional sono nella **struttura del segnale**, non nel numero di asset.
### Uplift portafoglio (4 → 5 sleeve, LOWVOL come 5° sleeve)
```
BASE (TP01+XS01+VRP01+SKH01) FULL 2.12 DD 8% | HOLD 2.25 DD 3%
+LOWVOL @10% FULL 2.17 (+0.05) | HOLD 2.57 (+0.32)
+LOWVOL @15% FULL 2.19 (+0.06) | HOLD 2.62 (+0.37)
```
## Il muro (perché NON è uno sleeve)
1. **Deflated Sharpe 0.130 ≪ 0.95** (N=216 trial globali; soglia Sharpe-max-null annualizz. 1.79). Con il
numero di celle/famiglie/universi testati, lo Sharpe 1.07 **non è significativo** dopo la correzione
per multiple-testing. Per-anno: 2024 +0.23 / 2025 +0.50 / **2026 0.09** (il 2026 è già negativo).
2. **Storia ~2.5 anni** (HL nativo 2024-2026): finestra troppo corta per un fattore cross-sectional.
3. **Non eseguibile a $600**: book L/S a molte gambe (10+ per lato) → **STAT-MODE**, mai deploy. Stesso
vincolo strutturale di XS01 (serve ~20k di capitale).
## Verdetto: **DEBOLE / forward-monitor (STAT-MODE).** Nessuno sleeve registrato.
Il **low-vol cross-sectional** (betting-against-vol sui 19 major) è l'unico meccanismo non-momentum con un
profilo decente e scorrelato sia a XS01 sia a TP01, e migliorerebbe l'hold-out del portafoglio (+0.32/+0.37).
**MA** non supera il deflated-Sharpe (multiple-testing), ha storia cortissima ed è non-eseguibile a questo
capitale. → lavoro **puramente statistico**, da tenere in forward-monitor come *secondo* segnale
cross-sectional a fianco di XS01, da rivalutare solo a scala (capitale ~20k+) e con più storia HL.
Reversal cross-sectional (REV/IREV) **confermato non-edge** su HL. Nessun impatto sul book live.
@@ -0,0 +1,91 @@
# 2026-07-01 — Breadth / market-internals del mercato ALT come segnale su BTC/ETH — SCARTATO
**Tesi.** Gli "internals" del mercato crypto — la partecipazione degli alt — come segnale
direzionale o gate di de-risk su BTC/ETH perp (2 gambe, eseguibile a ~$600): % di alt sopra la
propria SMA(N), advance/decline, % di alt che battono BTC (risk-appetite relativo), breadth-thrust.
Script `scripts/research/r0701_breadth_internals.py` (non committato per policy del filone; harness
`altlib`). Dati: i 51 parquet certificati `data/raw/hl_*_1d.parquet` → panel di **49 alt**
(esclusi hl_btc/hl_eth dalla breadth; hl_btc solo come riferimento per la famiglia RS), barre a
volume 0 mascherate (lezione backfill 2026-06-20; il fetch le aveva già ripulite: vol0=0 su tutti
i file, gate comunque attivo).
**Limite strutturale dichiarato in partenza:** l'universo HL parte dal 2024-01 → dopo il warmup
(max 120g) la finestra comune è **2024-05-05 → 2026-07-01 (~2.2 anni)** e l'in-sample pre-HOLDOUT
è **~8 mesi del toro 2024**. Qualunque esito poteva essere al massimo un lead.
## Famiglie e griglia (108 celle, tutte contate nel deflated Sharpe)
4 famiglie × N∈{20,50,100} × soglia∈{0.3,0.5,0.7} × forma∈{LS, long-flat, gate-su-TP01}:
- **FAM-MA**: % di alt validi con close > SMA(N) (breadth classica).
- **FAM-AD**: frazione di advancers (ret 1g>0), SMA(N).
- **FAM-RS**: % di alt che battono BTC sul ritorno a N giorni (≈ market-neutral, l'angolo più ortogonale).
- **FAM-TH**: breadth-thrust = Δ a N giorni della breadth MA20 (thrust/collapse), score 0.5+Δ.
Tutte causali (rolling/shift soltanto), MIN_VALID=20 asset per data (osservato: 42-49). LS/LF
vol-target 20% cap 2x (sizing TP01-style); GATE = posizione TP01 × gate binario. Fee 0.10% RT +
sweep 0-0.30%. Procedura onesta = mirror di `study_family_honest` sulla finestra comune (il
padding pre-2024 avrebbe contaminato il ranking full-history: le celle GATE con gate=1 pre-storia
erediterebbero lo Sharpe 2019-2024 di TP01): **cella scelta col SOLO Sharpe in-sample**, DSR su
tutti i trial, `marginal_vs_tp01` di altlib sulla cella scelta.
## ⚠️ Bug trovato e corretto: allineamento merge_asof su indice non-ns
La prima versione di `_align` usava `b.index.view("int64")//10**6` per i timestamp della breadth:
su un DatetimeIndex tz-aware **a risoluzione non-ns** (pandas 2.x) la scala esce sbagliata →
`merge_asof backward` matchava OGNI barra BTC/ETH all'**ultimo** valore della breadth = **il futuro
broadcast su tutta la storia**. Sintomo: decine di celle con lo stesso identico Sharpe (il segnale
era una costante). **`causality_ok` NON lo vede** — la serie breadth è un input esterno *fisso*,
quindi il target sul prefisso troncato coincide col target full per costruzione. Fix: epoca
esplicita `(idx - Timestamp(1970, tz=UTC)) // Timedelta(1ms)` (come `resample_tf`). **Lezione
harness:** ogni allineamento di un panel esterno via merge_asof va fatto con epoch-ms esplicita, e
il sintomo "molte celle con Sharpe identico" è un red-flag di allineamento rotto (gemella
dell'osservazione merge_asof del 2026-06-20).
## Esito (procedura onesta, finestra comune 2024-05+)
104/108 celle valutabili (4 degeneri flat), 47 con FULL>0. **Cella scelta in-sample** (IS 2.11,
la selezione non tocca mai l'hold-out): **TH N=100 thr=0.7 long-flat** — long solo dopo un
breadth-thrust (+0.2 di breadth MA20 in 100g), attiva il 32% dei giorni.
| metrica | valore |
|---|---|
| standalone finestra comune | IS **+2.11** → FULL **+0.99**, HOLD **+0.41** |
| assoluto (per-asset, trimmed) | **PASS** — minFull +0.68, minHold +0.38, fee-survive 0.30%RT, DD 7-11% |
| marginale vs TP01 | **ADDS** — corr full **0.401**/hold 0.358, resid Sharpe 0.87, multicut {2025:+0.076, 2026:+0.366} persistente, is_hedge=False |
| **robust_oos** | **False** — jackknife drop-best-month **0.068** (l'uplift hold-out sta in piedi su UN mese) |
| **deflated Sharpe** | **0.433** su 104 trial (null-max atteso 1.10) — lontanissimo dal PASS ≥0.95 |
| earns_slot / earns_slot_honest | **False / False** |
| causality_ok | True (post-fix) |
| smallcap $600 | haircut ≈ **0.00** (BTC 0.01, ETH +0.00; 137-152 trade) — eseguibile |
**Ridondanza col trend (il rischio n.1, lezione macro-gate):** qui NON è la modalità di morte.
corr(pos, TP01pos) 0.15-0.30 e il segnale "lavora" (off mentre TP01 non è flat) nel **24-32% dei
giorni** (il macro-gate lavorava nel 2-3%). Le forme direzionali LS/LF sono genuinamente diverse
da TP01 (corr→TP01 0.1-0.4). La forma **gate-su-TP01** invece sì: best gate = NEUTRAL a corr
0.803, e i gate a soglia bassa = REDUNDANT corr 1.0 (gate mai off → TP01 identico). **La breadth
come gate di de-risk non aggiunge nulla; come segnale direzionale è diversa dal trend ma l'edge
non è dimostrabile.**
**Il gemello in hindsight (trasparenza, NON selezionabile).** TH N=100 thr=0.7 **LS** fa FULL 1.13
/ HOLD 1.06, corr→TP01 **0.26**, marginal ADDS con robust_oos=True e jackknife +0.46. MA il suo
in-sample (1.30) è sotto quello della cella lf (2.11): sceglierlo = **selezione-sull'hold-out**
(esattamente il falso positivo ERM del 2026-06-29). E comunque **DSR 0.518 < 0.95**: anche la
lettura più caritatevole muore sulla deflazione multiple-testing.
## Verdetto: SCARTATO (niente sleeve, niente forward-monitor cablato)
1. La cella scelta onestamente è ADDS ma **robust_oos=False** (uplift a un mese) e **DSR 0.433**
su 104 trial: su ~8 mesi di in-sample (toro 2024) un IS di 2.1 è indistinguibile dal massimo
atteso per caso (1.10) e non regge.
2. Il candidato migliore col senno di poi (TH-LS) sarebbe selezione-sull'hold-out e fallisce
comunque il DSR (0.518) — il gate `study_family_honest` fa esattamente il suo lavoro.
3. Il limite è la **storia**: 2.2 anni totali, 8 mesi di in-sample. Non c'è modo onesto di
dimostrare l'edge oggi.
**Cosa resta.** (a) La famiglia **breadth-thrust (TH)** è l'unico angolo con celle OOS-positive e
bassa/negativa corr a TP01 — **rivisitabile quando il panel HL avrà ≥1-2 anni di storia nativa in
più** (in-sample multi-regime, DSR ricalcolabile); nessun cablaggio forward oggi, il costo
dell'attesa è zero. (b) Il breadth-**gate** su TP01 va in bacino con macro-gate e DVOL-gate: terza
conferma che TP01 non ha bisogno di de-risk esterno (long-flat, già flat nei crash). (c) Il fix
`_align` (epoch esplicita) è la lezione riusabile per ogni futuro panel esterno.
@@ -0,0 +1,58 @@
# 2026-07-01 — Book live: verifica gate SKH01 + emersione errori silenziosi
## Contesto
Il BOOK DERIBIT armato (TP01 0.75 + SKH01 0.25 nettati) è **flat da quando è stato armato
(2026-06-23)**: 193 run orari, tutte HOLD, zero ordini reali. Domanda: il flat è legittimo o il
gate di SKH01 è muto per un bug?
## Verifica del gate SKH01 — SANO
- **Logica viva:** `skyhook_entries` produce 335 entry (BTC, 222 long/113 short) e 341 (ETH,
226/115) su tutta la storia. Non è degenere.
- **Shorta davvero i crash:** ha aperto SHORT sulla gamba di crollo di fine maggio/inizio giugno —
BTC 05-28→06-04 ($73k→$64k), ETH 06-02→06-06 ($1865→$1555).
- **Flat da 06-23 = legittimo:** ultimo entry 06-06, `max_bars=16 × 230m ≈ 2,5g` → chiuso ~06-08/09,
**prima** dell'arming (06-23). Dal grind post-crash nessun setup breakout+regime valido → flat
corretto per design ("NON trend-follower"). Contesto prezzo al 01-07: BTC 53% dal picco, ETH
67,5%, momentum negativo su 1/3/6/12 mesi → anche TP01 (long-flat TSMOM) è a 0x.
- **Entrambi i feed valutano senza crash:** certificato e live `fresh_5m``skh_error=None`.
## Bug scoperto e corretto — pattern "eccezione ingoiata → stato safe silenzioso"
`src/live/` aveva più `try/except` che, in errore, producono uno stato safe (flat/fallback) **senza
farlo emergere**. Rischio: quando l'errore è transitorio ma reale, l'esecutore opera su dati sbagliati
credendoli legittimi.
### (1) `skh_error` — CORRETTO
`book_report` scriveva `skh_error` in un dict locale **mai incluso nel return**`r.get("skh_error")`
sempre `None`; e `book_execute` non lo leggeva comunque. Un feed SKH rotto avrebbe forzato SKH→flat in
silenzio (entry mancato, nessun alert). Fix: `skh_error` esposto nel return + `book_execute` emette
log `⚠️ SKH FEED ERRORE` + alert Telegram. (commit 31369b3)
### (2) Gate fail-safe posizione (Opzione A) — CORRETTO
`src/live/shadow.py::_positions`: se la read della posizione reale Deribit lancia, assume flat (0.0)
con una `note`, MAI propagata (`pos_src`) a `book_report`/`book_execute`. Severità mitigata a valle
da `rebalance_signed` che **rilegge la posizione fresca** (no doppia-posizione), ma resta il caso
"target≈0 + posizione aperta + read fallita → close saltato quel run" (transitorio, backstoppato dal
disaster-SL 30%). **Scelta A = gate fail-safe:** `_positions` ritorna un `pos_error` esplicito →
propagato `shadow_report → book_report → book_execute`; se presente (ONLINE ma posizione IGNOTA)
l'esecutore **NON opera a cieco** (return + alert), come già fa per `online`.
### (3) Diagnostica equity (Opzione B) — CORRETTO
`src/live/shadow.py::_equity`: se `account_summary('USDC')` e tutte le per-asset falliscono,
`real_eq=None` e `shadow_report` ripiega su `paper_cap` (~$2000 dallo state paper) mentre il conto
reale è ~$598 → il book dimensionerebbe su $2000 invece di $598 (**sovradimensiona ~33%**). Il danno
è limitato dall'**hard-cap $300/asset** in `book_net_target`. **Scelta B = SOLO DIAGNOSTICA** (niente
gate/halt, l'hard-cap già protegge il downside): `shadow_report` calcola `eq_fallback` (ONLINE +
equity reale non leggibile + no override), propagato `→ book_report → book_execute`, che stampa
`⚠️ EQUITY FALLBACK` + alert Telegram **ma prosegue** (a differenza del gate posizione, che blocca).
## Test
Suite completa **156/156** (era 148; +4 gate A + 4 diagnostica B). Dry-run reale di `book_execute`
invariato (nessuna riga d'errore, nessun ordine, conto $598.06 al target). Path live: `pos_error=None`,
`skh_error=None`, `eq_fallback=None`.
## Sintesi finale — i 3 pattern "errore silenzioso" del path live sono ora tutti tracciati
| # | Punto | Comportamento | Emersione |
|---|-------|---------------|-----------|
| 1 | `book_report` feed SKH | SKH → flat | log `⚠️ SKH FEED ERRORE` + alert |
| 2 | `_positions` read fallita | posizione → flat | **HALT** (non esegue) + alert (gate A) |
| 3 | `_equity` non leggibile | sizing → paper_cap | log `⚠️ EQUITY FALLBACK` + alert (diagnostica B) |
+114
View File
@@ -0,0 +1,114 @@
# 2026-07-01 — Funding rate come segnale TIME-SERIES direzionale su BTC/ETH (R0701): SCARTATO
## Contesto
Filone: il **funding orario Hyperliquid come proxy di POSIZIONAMENTO/sentiment** con valenza
direzionale a orizzonte giornaliero su BTC/ETH — NON carry. Angolo diverso dal prior art già
chiuso: **FC01** (carry cross-sectional delta-neutral 19 alt → LEAD fragile SCARTATO,
`2026-06-22-funding-carry-hl.md`) e **funding price-clock** intraday (drift attorno agli stamp →
FAIL, onda intraday). Qui l'ipotesi è: funding estremo = affollamento long → fade; funding in
espansione = domanda persistente → follow; funding affollato = de-risk del trend (gate).
Attrattiva a priori: 2 gambe BTC/ETH perp = **eseguibile al capitale reale ~$600** (non STAT-MODE
come XS01/opzioni) — se avesse retto sarebbe stato deployabile.
Script: `scripts/research/r0701_funding_ts.py`.
## Dati e causalità (data-first)
- `data/raw/hlfund_{btc,eth}_1h.parquet`: **2023-05-12 → 2026-06-22, 1138/1138 giorni validi,
0 gap** dopo il 2023-06 (primi ~27 giorni a cadenza 8h — la somma giornaliera degli stamp li
gestisce indifferentemente). Funding medio **+14.4%/anno BTC, +14.6% ETH**; std del funding
giornaliero ~5.5 bps.
- **Join causale** (il punto delicato): le barre 1d di `altlib.get` sono **open-labeled**
(datetime = 00:00 UTC del giorno D; il close della barra D è noto alle 00:00 di D+1). Il
feature-day D aggrega i SOLI stamp in **[D 00:00, D+24h)** — l'ultimo alle 23:00 — quindi tutto
è noto PRIMA della decisione al close della barra D; `eval_weights` shifta la posizione al
giorno D+1. Prefix-consistency check esplicito: **max diff 0.0** (nessun leak).
- **Valutazione su finestra TRONCATA** alla copertura funding, non sul frame prezzi 2018+: fuori
copertura il target sarebbe zero per costruzione e i giorni-zero (a) **gonfiano il T del
deflated-Sharpe** (anti-conservativo) e (b) diluiscono `cand_insample_sharpe` (il gate
`has_insample_edge` scatterebbe a vuoto). La logica di `study_family_honest` è replicata
ESATTAMENTE sui frame troncati coi primitivi altlib (selezione IN-SAMPLE-ONLY → gates
study_marginal → DSR sull'intera griglia). Cross-check `study_marginal` non-troncato in coda:
stessi verdetti (abs WEAK / marginal NEUTRAL / earns_slot False).
- ⚠️ **STORIA CORTA**: ~3.1 anni totali → in-sample pre-HOLDOUT ~1.6a (meno warmup z), hold-out
2025+ ~1.5a. Dichiarato: nessun numero qui ha il peso statistico di TP01 (7 anni).
## Metodo
Famiglia a griglia modesta, 1d, 50/50 BTC+ETH, vol-target 20% cap 2x (convenzione TP01), fee
0.10% RT + sweep 0.00-0.30%:
- **FADE**: z-score(funding daily, lb) ≥ thr → short; ≤ thr → long (fade dell'affollamento).
- **FOLLOW**: z ≥ thr → long; ≤ thr → short (sentiment momentum).
- **GATE**: trend long-flat TP01-like (sgn mom 30d+90d) ma FLAT quando z ≥ thr (de-risk crowding).
- **DIVERGE**: momentum prezzo 20d seguito se funding NON affollato (z ≤ thr), fatto se z ≥ thr.
Griglia: 4 forme × lb {7,14,30,60}g × thr {0.5,1.0,1.5} = **48 celle**. Selezione cella
**in-sample-only** (mai sul hold-out), deflated-Sharpe su tutte le 48, gates marginali
(`marginal_vs_tp01`), boundary-shift della finestra di aggregazione funding (0/3/6/9/12h),
`eval_weights_smallcap` a $600.
## Risultati
Best in-sample per forma: **fade 0.34, follow 0.81, gate 1.76, diverge 0.34** — il segnale
puro-funding è debole ovunque; solo la forma che CONTIENE il trend ha Sharpe.
**Cella scelta (in-sample): GATE lb=60 thr=1.5** — IS 1.76, FULL 1.16, HOLD 0.29.
| Gate | Esito |
|---|---|
| Deflated-Sharpe (48 celle) | **0.215** (null-max atteso 1.59) → **FAIL** (soglia 0.95) |
| Assoluto (frame troncati) | **WEAK** (minFull +0.97, ma minHold **+0.04** BTC); fee-survive fino a 0.30% RT |
| Marginale vs TP01 | **NEUTRAL**: corr **0.879** (hold 0.92), beta 0.77; uplift w25 hold **+0.001**; robust_oos=False (jackknife 0.074); multicut 2026 **0.423** |
| earns_slot / earns_slot_honest | **False / False** |
| Realism | prefix-diff 0.0 (causale); boundary-shift sign-stable (uplift spread 0.047); smallcap $600 haircut ~0.00 (eseguibile, irrilevante senza edge) |
**Controllo decisivo (lezione TP01-DVOL-overlay)** — lo stesso trend long-flat SENZA gate funding:
```
trend NUDO : IS 1.65 FULL 1.14 HOLD 0.37
trend+GATE : IS 1.76 FULL 1.16 HOLD 0.29 corr(gated,nudo)=0.928
delta del gate funding: FULL +0.013, HOLD 0.080
```
**tutto lo Sharpe della "vincitrice" è il trend**; il contributo del funding è ~zero in-sample
e **negativo sul hold-out**. Il gate è TP01 travestito.
**Miglior cella puro-funding** (la vera tesi del filone): FOLLOW lb=60 thr=0.5 — IS 0.81 ma
**FULL 0.28, HOLD 1.69**, marginale **DILUTES** (uplift w25 hold 0.778). L'in-sample 0.81 era
"long-il-toro-2023/24" travestito: z-alto di funding = rally già in corso; nel 2025-26 la stessa
regola è sistematicamente dalla parte sbagliata. FADE (shortare il crowding) perde sul toro e non
recupera abbastanza nel chop; DIVERGE negativa ovunque. NB: esistono celle gate con HOLD migliore
(es. gate 7/1.5 HOLD 0.96) — sceglierle sarebbe **selection-on-holdout**, il gate del 2026-06-29
esiste esattamente per questo.
## Perché fallisce (meccanismo)
1. Su asset MAJOR il funding è **quasi sempre positivo e segue il prezzo con lag**: lo z-score
alto coincide col momentum già espresso → FOLLOW è trend-beta ritardato (muore quando il regime
gira), FADE è shortare il toro. Non c'è l'anti-persistenza ("crowding → reversal") che la tesi
richiede — a 1d, su BTC/ETH, le liquidazioni-da-crowding sono già nel prezzo prima che lo
z-score giornaliero diventi estremo.
2. L'unico uso "funzionante" (gate di de-risk sul trend) è **ridondante**: TP01-like è già flat
quando serve. Stesso verdetto di macro-regime-gate (corr 0.989) e DVOL-overlay: la famiglia
"overlay prudenziale su TSMOM" è esaurita — eredita lo Sharpe del trend e non aggiunge nulla.
## Verdetto
**SCARTATO.** `earns_slot=False`, `earns_slot_honest=False` (DSR 0.215). Il funding time-series
non ha informazione direzionale propria su BTC/ETH a 1d; l'unica cella con Sharpe è trend
travestito con contributo funding OOS negativo. Niente forward-monitor: non c'è una componente
funding da monitorare. Con FC01 (carry cross-sectional) e il price-clock intraday, il filone
"funding come segnale" su dati certi è ora **chiuso su tre lati**.
## Lascito
- `scripts/research/r0701_funding_ts.py` riusabile: (a) loader funding→daily **causale** per barre
open-labeled (finestra [D, D+24h), gestione cadenza mista 8h/1h, flag validità copertura);
(b) pattern "**truncation-honest**" per dataset a copertura parziale — replica di
`study_family_honest` su finestra troncata per non gonfiare il T del DSR né diluire
`has_insample_edge` con anni di zeri (riusabile per ogni serie corta tipo DVOL/HL).
- I parquet `hlfund_*` restano certificati. Se mai si tornasse sul funding: gli estremi VERI
(squeeze) vivono sugli alt, ma è di nuovo cross-sectional → STAT-MODE a $600, soglia di prova
alta (e FC01 ha già mostrato la fragilità d'universo).
@@ -0,0 +1,174 @@
# 2026-07-01 — Pesi statici ri-ottimizzati + guardia-DD sul portafoglio a 4 sleeve
## Mandato
Migliorare il portafoglio ATTIVO (TP01 41.25 / XS01 18.75 / VRP01 15 / SKH01 25) SENZA nuove
strategie: (A) ri-ottimizzazione onesta dei pesi statici, (B) guardia-drawdown a livello
portafoglio (replica del soft-guard vincente del tail-hedge lab 2026-06-23), (C) combinazione.
NON meta-allocazione dinamica (già scartata, thread 3 del 2026-06-29).
Script: `scripts/research/r0701_portfolio_opt.py`. Solo ricerca: nessun file di src/ o live toccato,
i pesi sono PROPOSTI, non applicati.
## Baseline riprodotta
`run_portfolio.py` oggi: **FULL Sh 2.12 / HOLD 2.21 / DD full 7.8% / CAGR 23.3%** (vs 2.13/2.30
del diario Skyhook: i dati sono avanzati di una settimana, coerente). Matrice sleeve outer-join
2019-03-14 → 2026-07-01 (TP01/SKH01 dal 2019, VRP01 dal 2021-05, XS01 dal 2024-01), combine
identico a `portfolio.combined_daily` (pesi rinormalizzati per-riga sugli sleeve attivi).
## (A) Pesi statici — metodo
- Ottimizzazione SOLO in-sample (pre-cut), valutazione OOS (post-cut), multi-cut
{2024-01, 2024-07, 2025-01}. Sleeve con <120 giorni in-sample al cut (XS01 al 2024-01)
PINNED al peso corrente (l'ottimizzatore non ha dati per giudicarli).
- Criteri: MAXSH (max-Sharpe del combo simulato), RP (inverse-vol), ERC, MINVAR-R (min-var con
vincolo ritorno ≥ pesi correnti). Null: EW (25×4) e CURRENT. Vincoli 5%≤w≤60%, Σ=1.
- **Cap STRUTTURALI dichiarati** (prudenza, non statistica): **VRP01 ≤ 15%** (sleeve MODELLATO su
DVOL ATM, stress-f non catturato — "niente short-vol da modello in deploy"), **XS01 ≤ 25%**
(STAT-MODE, storia ~2.5 anni). Varianti sotto cap: MAXSH-STR (ottimizzato) e EW-STR
(EW proiettato sui cap, parameter-free → TP 30 / XS 25 / VRP 15 / SKH 30).
### Risultati (pesi ottimizzati pre-2025, valutati FULL e HOLD-OUT 2025-26)
| criterio | pesi TP/XS/VRP/SKH | FULL Sh | FULL DD | FULL CAGR | HOLD Sh | HOLD DD | HOLD CAGR | multi-cut ΔSh OOS | anni vinti |
|---|---|---|---|---|---|---|---|---|---|
| CURRENT | 41.2/18.8/15/25 | 2.12 | 7.8% | +23.3% | 2.21 | 3.5% | +16.0% | — | — |
| MAXSH | 27.6/17.5/**39.5**/15.4 | 2.17 | 6.3% | +21.8% | 2.27 | 2.8% | +12.7% | +0.24/+0.08/+0.06 | **1/8** |
| RP-invvol | 26.7/15.5/**41.6**/16.3 | 2.17 | 6.4% | +21.8% | 2.25 | 2.8% | +12.4% | +0.28/+0.07/+0.04 | — |
| ERC | 26.6/16.2/**41.6**/15.7 | 2.17 | 6.3% | +21.7% | 2.25 | 2.8% | +12.4% | +0.29/+0.07/+0.05 | — |
| MINVAR-R | 26.7/23.3/**29.6**/20.4 | 2.18 | 6.4% | +23.3% | 2.37 | 2.6% | +16.1% | +0.20/+0.10/+0.16 | 4/8 |
| MAXSH-STR | 38.6/25/15/21.4 | 2.14 | 7.5% | +23.4% | 2.28 | 3.3% | +16.8% | **0.00**/+0.03/+0.07 | 3/8 |
| EW | 25/25/25/25 | 2.14 | 7.0% | +24.5% | 2.39 | 2.8% | +18.1% | +0.16/+0.17/+0.18 | 6/8 |
| **EW-STR** | **30/25/15/30** | 2.10 | 8.5% | +25.2% | **2.35** | 3.2% | **+19.7%** | **+0.06/+0.13/+0.14** | **7/8** |
### Lettura onesta
1. **Gli OTTIMIZZATORI non aggiungono nulla — anzi overfittano.** Tutti (MAXSH/RP/ERC/MINVAR-R)
convergono sulla stessa mossa: scaricare TP01 e caricare **VRP01 al 30-42%** perché ha la vol
più bassa (7.7%/anno). Ma quella è la vol del MODELLO (premio BS su DVOL, coda di stress non
catturata): è esattamente il punto cieco tipo-CC01 ("Sharpe/vol implausibile → rischio
nascosto"). E per-anno MAXSH vince **1/8 anni** vs CURRENT — l'uplift multi-cut è smoothing di
vol modellata, non alpha di allocazione. **Dentro i cap** l'ottimizzatore (MAXSH-STR) converge
quasi sui pesi correnti (38.6/25/15/21.4) e NON è persistente (0.00 al cut 2024-01) →
**i pesi correnti sono già ~ottimi per ciò che il backtest può giudicare lecitamente**.
2. **L'unico segnale robusto è la DE-CONCENTRAZIONE parameter-free**: EW-STR (EW sotto i cap,
nessun parametro fittato) vince **7/8 anni** (unica perdita 2021 3.1pp), tutti i cut OOS
(ΔSh +0.06/+0.13/+0.14), HOLD Sh 2.21→2.35, HOLD CAGR +16.0→+19.7%. Classico "1/N batte
l'ottimizzazione" (DeMiguel). La sostanza: CURRENT dà il 41% al peggior Sharpe FULL del book
(TP01 1.30) e EW-STR sposta ~11pp da TP01 verso SKH01 (+5pp) e XS01 (+6.25pp).
3. **MA non è un free lunch risk-adjusted**: FULL Sh 2.12→**2.10** e FULL DD 7.8→**8.5%**
(più SKH01, che ha DD standalone 18%, pesa di più nei primi anni a 2 sleeve). L'uplift è un
TILT di ritorno verso gli sleeve research-grade con la storia più corta/caveat più pesanti
(SKH01 = research win, book 230m da verificare a deploy; XS01 = STAT-MODE non eseguibile a 2k).
E TP01 resta l'unico sleeve *deployed* live: il suo 41% nel report riflette una scelta di
prudenza/eseguibilità, non solo statistica.
### VERDETTO (A)
- **Ottimizzazione formale: NON MIGLIORA** (viola i cap strutturali o converge ai pesi correnti).
**Per il book reale i pesi correnti reggono.**
- **Candidato PROPOSTO (non applicato): EW-STR = TP01 30 / XS01 25 / VRP01 15 / SKH01 30** —
uplift OOS persistente e per-anno (7/8), dentro i cap, al costo di FULL DD +0.7pp e FULL Sh
0.02. È una decisione di risk-appetite (più ritorno atteso spostando peso su sleeve
research-grade), non un miglioramento dominante. Se si vuole adottare, farlo consapevoli che
aumenta la dipendenza da SKH01/XS01, e NON tocca il book Deribit eseguibile (TP75/SKH25).
### Caveat metodologici (A)
- Le 3 finestre multi-cut sono ANNIDATE (tutte contengono il 2025-26): non 3 conferme
indipendenti. Il test disgiunto vero è il per-anno (7/8 per EW-STR è il dato forte).
- EW-STR è stato costruito DOPO aver visto EW vincere (proiezione del null sui cap dichiarati):
costruzione principled e parameter-free, ma va detto — non era nella griglia iniziale.
- I pesi CURRENT stessi furono fissati (2026-06-23) conoscendo l'hold-out → il confronto
"in-sample-opt vs CURRENT su hold-out" è semmai sbilanciato A FAVORE di CURRENT; EW-STR vince
comunque.
## (B) Guardia-drawdown a livello portafoglio — metodo
Soft-guard causale sul combo 4-sleeve (pesi CURRENT): esposizione del giorno D decisa dal DD
dell'equity fino a **D1**; trigger/re-entry sul **NAV ombra** non-guardato (lezione stops_lab:
sull'equity congelata a expo=0 il DD non rientra mai); isteresi re-risk a 0.4·X come nel
tail-hedge lab. Griglia X∈{3,4,5,6}%, derisk∈{0,0.5}. Selezione cella IN-SAMPLE (max Calmar
pre-2025), verifica hold-out + multi-cut, **null de-levering** (expo costante c che pareggia il
MaxDD in-sample della guardia: Sharpe di c·r è invariante → la guardia vale solo se batte quello).
### Risultati
- Cella scelta in-sample: **X=5% / derisk=0.5** (IS Calmar 3.64 vs 3.24 baseline; IS DD 7.8→6.6%,
IS CAGR 25.3→23.9%, IS Sh 2.13→2.12). In-sample batte il null de-levering c=0.84 a pari DD
(CAGR 23.9% vs 21.0%) — il timing esiste in-sample.
- **MA OOS è INERTE**: a ogni cut la cella scelta non scatta MAI (ΔSh +0.00, ΔDD 0.0pp, ΔCAGR
0.0pp su tutti e 3 i cut) perché il DD OOS del 4-sleeve resta 3.5-4.8% < trigger 5%.
**La diversificazione a 4 sleeve fa già il lavoro della guardia** (il 2022 del book è +11.6%
con DD 3.6%: non c'è il grind da proteggere che aveva il combo TP01+GTAA del tail-hedge lab,
DD 8.4% / 2022 4.4%).
- Trigger più stretti che scattano davvero COSTANO: X=3%/d=0.5 → HOLD Sh 2.10 (< 2.21), CAGR
13.7% (< 16.0%); X=3-4%/d=0 whipsaw pieno (HOLD Sh 1.83-2.09; a X=4/d=0 il DD guardato IS
sale addirittura a 8.8% > 7.8% baseline — accumulo di perdite su cicli off/on, lo stesso
fenomeno visto in stops_lab con l'uscita totale).
### VERDETTO (B)
**NON MIGLIORA.** La guardia-DD che vinceva sul combo TP01+GTAA (DD 8.4%, 2022 4.4%) qui non ha
bersaglio: il 4-sleeve ha già DD ~3.5-4.8% OOS. Coerente col thread meta-allocazione 2026-06-29
(drawdown-control ridondante). Nota operativa: la cella X=5%/d=0.5 è *innocua* (non fa nulla
finché il DD non supera il 5%) e in-sample mostrava timing genuino sopra il null de-levering —
può valere come **circuit-breaker di emergenza sul live** (risk management, non alpha), ma non è
un miglioramento statistico e non la si adotta come tale.
## (C) Combinazione
(B) è inerte → niente da combinare. Per completezza: EW-STR + guard X=5%/d=0.5 → FULL Sh 2.08,
DD 6.7%, CAGR 23.7% | HOLD invariato 2.35/3.2%/19.7% (la guardia lima il DD 2021-2023 del tilt
a costo di 0.02 Sh FULL). Nessuna adozione proposta.
## Sintesi
| config | FULL Sh | FULL DD | FULL CAGR | HOLD Sh | HOLD DD | HOLD CAGR |
|---|---|---|---|---|---|---|
| **CURRENT (attivo)** | 2.12 | 7.8% | +23.3% | 2.21 | 3.5% | +16.0% |
| EW-STR (proposta A, non applicata) | 2.10 | 8.5% | +25.2% | 2.35 | 3.2% | +19.7% |
| CURRENT + guard 5%/0.5 (B) | 2.11 | 6.6% | +22.3% | 2.21 | 3.5% | +16.0% |
| EW-STR + guard (C) | 2.08 | 6.7% | +23.7% | 2.35 | 3.2% | +19.7% |
- **(A) NON MIGLIORA in senso forte** — i pesi correnti reggono; l'unico candidato onesto è il
tilt de-concentrante EW-STR (30/25/15/30), un trade-off di risk-appetite da decidere, non un
upgrade dominante. Gli ottimizzatori in-sample o violano i cap strutturali (VRP01 40%) o
riconvergono sui pesi correnti.
- **(B) NON MIGLIORA** — guardia inerte OOS sul 4-sleeve; utile al più come circuit-breaker.
- Nessuna modifica a `src/portfolio/sleeves.py` o al live. Test 160/160 verdi.
Script: `scripts/research/r0701_portfolio_opt.py` (~4s, vettoriale).
## Verifica avversariale (agente scettico)
Script: `scripts/research/r0701_portfolio_skeptic.py`. **VERDETTO: NON APPLICARE — CURRENT resta.**
I numeri dell'agente riproducono ESATTAMENTE (via `StrategyPortfolio.combined_daily`, path di
produzione: CURRENT 2.12/2.21, EW-STR 2.10/2.35, multi-cut +0.06/+0.13/+0.14, |diff|=0). Il claim
muore altrove: l'uplift è **selezione-sull'hold-out di 2° ordine**, non alpha di allocazione.
1. **L'uplift OOS vive TUTTO nel 2025-26 — la finestra che ha selezionato i beneficiari.**
Finestre OOS **DISGIUNTE** (i 3 cut del diario sono annidati): ΔSh EW-STR vs CURRENT =
**0.12** (2024H1) / +0.06 (2024H2) / **+0.14** (2025+). L'unica finestra OOS non toccata
dalla selezione hold-out è negativa. Sharpe standalone IS→HOLD per sleeve: TP01 1.49→**0.30**,
SKH01 1.42→**1.64**, XS01 1.22→**1.51**: EW-STR compra esattamente i due sleeve ammessi/affinati
(2026-06-23 / 2026-06-19) PERCHÉ forti sull'hold-out e vende quello che lì collassa. Meccanico.
2. **Pre-2025 (finestra non contaminata) EW-STR PERDE risk-adjusted**: ΔSh aggregato **0.05**,
Sharpe per-anno vinti **2/6** (2021 0.29, 2020 0.10, 2023/2024 negativi).
3. **"7/8 anni vinti" è un artefatto di metrica**: è RITORNO composto (un tilt a più vol/ritorno
li vince quasi per costruzione), non risk-adjusted. Su **Sharpe per-anno: 3/8**. E due dei 7
"vinti" (2023, 2024) hanno margine **+0.03pp** = tie. Bilancio materiale sul ritorno:
5 vinti / 1 perso (2021 3.1pp) / 2 pari.
4. **Plateau: liscio ma il gradiente è solo "meno TP01"**; a TP fisso, alzare SKH 25→30 è
piatto/negativo (min multi-cut a TP35: +0.07→+0.02). Scomposizione: il tilt **solo-SKH**
(+5pp, TP 36.25) da solo NON è persistente (multi-cut **0.00**/+0.05/+0.04); il tilt
**solo-XS** (TP35/XS25/VRP15/SKH25) è l'unico positivo su tutte le finestre disgiunte
(+0.05/+0.02/+0.11) — ma pre-2025 fa ΔSh 0.00 (edge ≈ zero fuori dal 2025-26) e carica lo
sleeve MENO eseguibile (STAT-MODE).
5. **Realismo**: con l'outer-join rinormalizzato EW-STR tiene SKH01 al **50% effettivo nel
2019-20 e 40% nel 2021-23** (book research 230m a metà portafoglio: da lì il FULL DD 8.5%).
Punto onesto A FAVORE: un haircut d'esecuzione a drag su SKH01(-20/30%) e SKH+XS non ribalta
il ranking hold-out (ΔSh resta +0.08..+0.13), ma i livelli assoluti crollano (HOLD Sh CURRENT
2.21→1.64 al 30% su entrambi) e il beneficio resta di CARTA: il book Deribit eseguibile
(TP75/SKH25) non è toccato dalla decisione.
6. **Forking paths quantificato**: ≥15 config valutate sull'hold-out (7 vettori pesi + 8 celle
guardia), EW-STR costruito dopo aver visto EW vincere. Su **500 tilt CASUALI cap-respecting**:
51% batte CURRENT sull'hold-out (mediana ΔSh +0.00), solo 11% sul FULL, 30% su tutti e 3 i cut.
EW-STR è al **94° percentile** dell'uplift hold-out fra i tilt casuali ≈ il **massimo atteso di
~15 tentativi** (k/(k+1)=93.8%): l'uplift osservato è indistinguibile dal "best of 15 tilt
casuali scelto sull'hold-out".
**Conclusione**: il tilt non è disonesto nei conti ma non è evidenza — è la stessa lezione del gate
SELECTION-ON-HOLDOUT applicata al livello dei PESI (2° ordine: gli sleeve stessi sono stati
selezionati su quell'hold-out). Unica direzione sopravvissuta: XS01 18.75→25 (solo-XS, positivo su
tutte le finestre disgiunte), MA edge ≈0 fuori dal 2025-26, sleeve STAT-MODE non eseguibile a $600,
e l'hold-out-strength di XS01 è a sua volta concentrata dal gate di dispersione nel regime 2025-26
→ da rivalutare SOLO con più storia forward, non ora. **CURRENT (41.25/18.75/15/25) resta.**
@@ -0,0 +1,132 @@
# 2026-07-01 — Ondata multi-agente a 6 filoni: 0 nuovi sleeve, pesi CURRENT confermati, 1 gate nuovo
**Goal utente:** "cerca con diversi agenti altre strategie di trading. Prova di tutto e arriva a
migliorare il portfolio presente. Lo scopo è sempre 50 euro days."
**Esito in una riga:** 6 filoni nuovi (scelti dopo scan dei ~65 diari per non ripetere strade morte)
+ 1 verifica avversariale → nessun candidato supera i gate onesti; il portafoglio a 4 sleeve
(41.25/18.75/15/25) **sopravvive a un attacco serio**, che è l'esito corretto per un book onesto.
Miglioramento concreto dell'ondata = metodologico: **gate `weights_tilt_null`** codificato (sotto).
## I 6 filoni (tutti su harness onesto: study_family_honest, marginal scorer, DSR≥0.95, smallcap $600)
| # | filone | verdetto | perché muore |
|---|---|---|---|
| 1 | **Funding time-series** BTC/ETH (posizionamento, non carry) — `r0701_funding_ts.py` | SCARTATO | FOLLOW = trend-beta ritardato (HOLD 1.69), FADE = shortare il toro; la cella gate è TP01 travestito (controllo senza funding = stessi numeri, corr 0.93, ΔHOLD 0.08); DSR 0.215. **Filone funding chiuso su 3 lati** (FC01 carry, price-clock, TS-signal). |
| 2 | **Breadth/internals alt** (51 HL) → BTC/ETH — `r0701_breadth_internals.py` | SCARTATO (rivisitabile) | Unico non-ridondante col trend (corr→TP01 0.40, lavora dove TP01 è attivo), assoluto PASS, marginal ADDS — ma jackknife 0.068 (uplift su UN mese) e DSR 0.433/104 celle. Con ~8 mesi di IS il 2024-toro non basta. **Rivisitare tra 1-2 anni di storia HL nativa.** |
| 3 | **Residual momentum XS** (β-hedged vs BTC, 19 major) — `r0701_xs_residmom.py` | REDUNDANT | Cross-section la residualizzazione è quasi un no-op (lo z-score di XS01 già rimuove il mercato): corr→XS01 0.54, HOLD 0.24, corr(IS,HOLD) tra le celle **0.37** (anti-predittivo = rumore). L'edge residuo-momentum vive nella coppia ETH/BTC (STATARB-RESID, resta in `paper_statarb`), non generalizza. |
| 4 | **Pesi + guardia-DD**`r0701_portfolio_opt.py` | vedi sotto | Unico candidato dell'ondata (EW-STR) → refutato dallo scettico. Guardia-DD X5%/d0.5: in-sample batte perfino il null de-levering, ma **OOS non scatta mai** (DD book 3.5-4.8% < trigger): la diversificazione fa già il lavoro. Utilizzabile solo come circuit-breaker di emergenza (risk mgmt, non alpha). |
| 5 | **Affinamento VRP01** (sizing IVRV, DVOL-mom, gate TP01) — `r0701_vrp_refine.py` | NON MIGLIORA | L'alpha è già tutto nel gate binario IV-rank; il gate TP01 è la trappola IS perfetta (schiva il 2022, ma taglia le settimane migliori dell'hold-out: multi-cut 0/5). **3° fallimento del filone "affinare VRP dentro il modello" → esaurito** finché cerbero-bite non cattura un crash reale (f di stress). |
| 6 | **Stagionalità cross-sectional** HL — `r0701_xs_seasonal.py` | SCARTATO (allo step statistico) | Nessuna persistenza split-half sopra il null permutato max-statistic (p 0.16-0.23); l'unica struttura è il canale-beta dell'effetto weekday di mercato (famiglia trackF, già morta). Turnover ~2×gross/die = fee-death comunque. |
## EW-STR: il candidato refutato (caso di scuola di selezione-sull'hold-out di 2° ORDINE)
Il filone 4 proponeva **EW-STR** (TP01 30 / XS01 25 / VRP01 15 / SKH01 30 = equal-weight proiettato
sui cap strutturali): HOLD Sh 2.21→2.35, multi-cut +0.06/+0.13/+0.14, "7/8 anni vinti" — dichiarando
onestamente i caveat. La verifica avversariale (`r0701_portfolio_skeptic.py`, addendum nel diario
pesi) lo uccide:
1. **Selezione di 2° ordine**: SKH01 fu ammesso (2026-06-23) *perché* alzava l'hold-out 2025-26;
XS01 fu affinato conoscendo l'hold-out. EW-STR vende lo sleeve che collassa OOS (TP01 IS 1.49→
HOLD 0.30) e compra i due selezionati su quell'OOS. Pre-2025: **ΔSh 0.05** (perde risk-adjusted).
2. **Su finestre OOS disgiunte**: 0.12 (2024H1) / +0.06 (2024H2) / +0.14 (2025+) — tutto l'uplift
vive nella finestra che ha selezionato gli sleeve. "7/8 anni" era sul ritorno composto; su
Sharpe è 3/8.
3. **Firma best-of-k**: su 500 tilt casuali cap-respecting, EW-STR siede al 94-100° percentile ≈
k/(k+1) con k≈15 config viste sull'hold-out → uplift indistinguibile dal *best-of-15 scelto
sull'hold-out*.
4. **Realismo**: in pesi effettivi (outer-join rinormalizzato) EW-STR = SKH01 al 40-50% del book
2019-23 (sleeve research a book 230m). Il book Deribit eseguibile (TP+SKH) non cambierebbe comunque.
Residuo onesto: il sub-tilt XS01 18.75→25 è positivo su tutte le finestre disgiunte ma edge≈0
pre-2025 e STAT-MODE → rivalutare solo con storia forward.
## GATE NUOVO codificato: `weights_tilt_null` (src/portfolio/portfolio.py)
La lezione è ora codice, come per marginal-scorer e study_family_honest:
- **`combine_outer(daily_cols, weights, lo, hi)`** — la combinazione outer-join/rinormalizzata di
`combined_daily` estratta come funzione su pesi arbitrari (riusabile per studi di tilt).
- **`weights_tilt_null(daily_cols, w_current, w_proposed, caps, floor, n, seed, k_seen)`** —
null di tilt casuali uniformi sul simplesso dentro floor/caps: riporta `delta_hold/full/insample`,
`frac_random_beat_hold`, `pctl_hold`, `bestofk_pctl=k/(k+1)` e `gate_pass`.
**Regola: un cambio-pesi si applica solo se (1) delta_insample ≥ 0 e (2) pctl_hold < firma
best-of-k** (necessario, non sufficiente: restano finestre disgiunte + realismo).
Sul caso reale EW-STR: delta_hold +0.139, delta_insample **0.054**, pctl **100°** vs best-of-15
93.75° → `gate_pass=False`. Test: `tests/test_weights_tilt_null.py` (5 test, sintetici,
deterministici; incluso lo sleeve "forte-solo-nell'hold-out" che DEVE fallire il gate).
## Lezione tecnica riusabile (dal filone 2)
`DatetimeIndex.view("int64")` su indici **tz-aware a risoluzione non-ns** (pandas 2.x) produce
timestamp in scala sbagliata → un `merge_asof` può broadcastare l'ultimo valore su tutta la storia
= **look-ahead che `causality_ok` non vede** (input fisso). Sintomo: decine di celle con Sharpe
identico. Fix: epoca esplicita in ms. Verificato: `altlib.py` non è affetto (grep pulito); dettagli
nel diario breadth.
## Onestà sul goal €50/giorno
Invariata (vedi CLAUDE.md): a capitale reale ~$600 il book onesto fa ~+€1.5/giorno atteso; la via
resta capitale + tempo + target-vol, non un tilt di pesi né leva. Questa ondata conferma che il
book attuale è vicino al massimo estraibile dai dati certificati disponibili oggi; le opzioni
reali di crescita restano (a) storia forward che promuova i lead (STATARB-RESID, breadth tra 1-2
anni), (b) capitale, (c) nuove fonti di dato (f di stress reale per VRP).
**File dell'ondata:** `scripts/research/r0701_{funding_ts,breadth_internals,xs_residmom,portfolio_opt,portfolio_skeptic,vrp_refine,xs_seasonal}.py`; diari `2026-07-01-{funding-ts-signal,alt-breadth-internals,xs-residual-momentum,portfolio-weights-ddguard,vrp-refinement,xs-seasonality}.md`; gate in `src/portfolio/portfolio.py` + `tests/test_weights_tilt_null.py`.
## ADDENDUM (stessa sera) — GTAA01 promosso a 5° SLEEVE: il miglioramento c'era, ma era in casa
Il secondo passaggio sull'archivio (non sui dati!) ha trovato il candidato che l'ondata di *ricerca*
non poteva trovare: **EQ-GTAA01** (`src/portfolio/gtaa.py` — trend difensivo equity 6-ETF, vt12%,
~30 anni di storia, netto fee IB) era stato validato il 2026-06-22 come *"primo miglioramento
STRUTTURALE del rischio-aggiustato trovato in tutta la ricerca post-reset"*, messo in paper
cross-venue (`paper_combo`, nel cron dal 2026-06-23) e **mai valutato come 5° sleeve del
portafoglio attivo** (il giorno dopo arrivò SKH01 e il filone si fermò).
### Valutazione onesta (`r0701_gtaa_5th_sleeve.py`) — perché GTAA passa dove EW-STR è morto
| gate | EW-STR (refutato) | +GTAA01 (passa) |
|---|---|---|
| uplift IN-SAMPLE (pre-2025) | **0.05** | **+0.09..+0.13** (2.134→2.23-2.26) |
| finestre OOS disgiunte | 0.12 / +0.06 / +0.14 | **+0.05 / +0.19 / +0.25** (tutte >0) |
| multi-cut (4 tagli) | solo annidate | **+0.21 / +0.21 / +0.22 / +0.25** |
| provenienza dell'edge | sleeve selezionati sull'hold-out crypto | validato su OOS equity 2015+, **indipendente** dall'hold-out crypto |
| corr al book | — | **+0.10** full, ~0.00 hold-out; is_hedge +0.30 (non-hedge) |
| plateau | gradiente generico anti-TP01 | **monotono su w 10-30%, ogni cella migliora IS/FULL/HOLD/DD** |
Convenzione di realismo cross-venue (nuova, cablata nello sleeve): nei giorni senza barra equity
(weekend/festivi US) il rendimento è **0.0** — capitale IB fermo, NON rinormalizzato sul crypto
(due conti reali non si travasano nel weekend). Numeri quasi identici alla versione outer-join
(differenze al 3° decimale) ma il modello è quello giusto. Attivazione nel book all'era crypto
(2019-03-14): senza troncatura l'outer-join farebbe partire il book nel 1996 con 23 anni di
solo-GTAA rinormalizzato al 100%.
### Decisione pesi
Cella IS-best = w=30% (bordo griglia), **ingresso @20%** per scelta strutturale dichiarata:
(a) cross-venue IB con paper operativo di soli 8 giorni — non diventa lo sleeve più grande del
book al day-one; (b) precedente: ogni sleeve nuovo è entrato ≤25% (SKH01 25%, VRP01 15%);
(c) costo CAGR (a 30%: 16.8% vs 18.8% a 20%) — e l'obiettivo €50/g vive di CAGR, non solo di
Sharpe. Tutte le celle 10-30% passano comunque ogni gate. Pesi nuovi: **TP01 33 / XS01 15 /
VRP01 12 / SKH01 20 / GTAA01 20** (i 4 preesistenti scalati ×0.80, rapporti conservati).
### Portafoglio 5-sleeve (run_portfolio, capitale 2k)
| | FULL Sh | FULL DD | FULL CAGR | HOLD Sh | HOLD DD | HOLD CAGR |
|---|---|---|---|---|---|---|
| 4-sleeve (baseline) | 2.12 | 7.8% | +23.3% | 2.21 | 3.5% | +16.0% |
| **5-sleeve (+GTAA01 20%)** | **2.24** | **6.2%** | +18.8% | **2.46** | **2.2%** | +14.6% |
Per-anno: tutti gli 8 anni positivi, 2022 +7.0% (era +11.6%: GTAA soffre il whipsaw 2022, unico
anno con dSh negativo 0.49 — dichiarato). Il trade-off è esplicito: 4.5pp di CAGR full per
+0.12/+0.25 di Sharpe e DD 7.8→6.2 / hold-out 3.5→2.2. A pesi research (XS/VRP/SKH modellati o
STAT-MODE) il CAGR era comunque di carta; lo Sharpe/DD del book è la metrica di verità.
### Cosa NON cambia
Il **book live Deribit** (`deribit_book_sleeves` TP01+SKH01 75/25, `book_execute`) è INTATTO —
GTAA è su IB, già tracciato forward da `paper_combo`. `paper_portfolio` da oggi traccia la
composizione a 5 (regime-break dichiarato qui). Test: `tests/test_gtaa_sleeve.py` (registry,
weekend-zero, attivazione, book live invariato) — suite 168/168.
### Lezione dell'addendum
Prima di una nuova ondata di *ricerca*, ri-leggere l'archivio dei **validati-ma-non-integrati**:
l'unico upgrade onesto del book in 3 ondate (104+5+6 filoni) era un edge già validato che
aspettava solo la valutazione da sleeve. La diversificazione strutturale (secondo mercato,
corr ~0.1) resta l'unica cosa che alza lo Sharpe del book senza nuovo alpha.
+98
View File
@@ -0,0 +1,98 @@
# 2026-07-01 — Affinamento VRP01 (sizing IVRV / filtro DVOL-momentum / gate TP01): NON MIGLIORA
**Script:** `scripts/research/r0701_vrp_refine.py` (solo ricerca: `src/` e `scripts/live/` non toccati).
**Esito: NON MIGLIORA — VRP01 baseline resta la config canonica.** La cella IS-best (gate TP01-skip)
è un falso positivo in-sample da manuale: IS Sharpe 2.07 ma multi-cut **0/5**, hold-out **0.14**
(vs 0.59 del baseline), DSR 0.71. Nessuna modifica a `sleeves._vrp_combo_returns`.
## Cosa testava (celle NUOVE, verificate non ripetute nei diari)
Stessa pipeline di `options_vrp_v2.py` (pricing BS su DVOL reale, payoff sul path certificato,
fee 12.5% del premio, f=1.0, tenor 7d, spread 0.28/0.10) — cambiati SOLO gate/sizing:
1. **Sizing sul gap IVRV** (carry atteso): size lineare `clip(vrp/scale,0,1)` (scale 8/12 pt) o
percentile espandente causale del VRP; in aggiunta o in sostituzione del gate binario IV-rank.
NB: il gate composito "IV-rank>0.30 AND IVRV>0" è **già il baseline** (`gate_vrp=True`).
2. **Filtro DVOL-momentum**: non vendere se `dvol[i]dvol[ik] > thr` (k∈{5,10}, thr∈{0, 5pt}).
(Diverso da `dvol_directional` 2026-06-29, dove il DVOL-mom era segnale direzionale sul perp.)
3. **Gate di regime da TP01**: skip o half-size quando TP01 è flat su entrambi gli asset (risk-off).
4. Croce completa: **105 celle**, tutte contate nel deflated-Sharpe.
NON ripetuto (già scartato): gestione attiva intra-trade (PT/SL/vol-stop/delta-exit,
`2026-06-20-vrp-active-management.md` → hold-to-expiry vince).
Metodo: selezione cella **in-sample (pre-2025)** con floor di attività IS ≥20%, hold-out 2025-26,
**multi-cut 5 tagli** (2023-01→2025-01, richiesti ≥4/5 uplift>0), `altlib.deflated_sharpe` su tutti
i 105 trial, effetto sul **portafoglio 4-sleeve** (TP01 41.25 / XS01 18.75 / VRP 15 / SKH01 25).
## Risultati (book 50/50 BTC+ETH, rendimenti settimanali)
Baseline riprodotto esattamente: **FULL Sh 1.09 / IS 1.26 / HOLD 0.59 / DD 12% / worst 7.4% / attivo 41%.**
| cella | IS Sh | FULL | HOLD | DD | worst | attivo |
|---|---|---|---|---|---|---|
| **BASELINE** bin+ivr30 | 1.26 | **1.09** | **0.59** | 12% | 7.4% | 41% |
| sizing lin 8pt (+ivr30) | 1.20 | 1.05 | 0.61 | 11% | 7.4% | 41% |
| sizing lin 12pt (+ivr30) | 1.12 | 0.98 | 0.54 | 11% | 7.4% | 41% |
| sizing rank (+ivr30) | 1.07 | 0.94 | 0.54 | 9% | 5.7% | 41% |
| sizing lin 8pt **al posto di** ivr | 0.89 | 0.58 | **0.38** | 21% | 7.4% | 86% |
| sizing rank al posto di ivr | 1.03 | 0.69 | **0.36** | 11% | 5.7% | 86% |
| mom k=5 thr=5pt | 1.24 | 1.02 | 0.37 | 9% | 6.5% | 34% |
| mom k=10 thr=5pt | 1.26 | 1.08 | 0.55 | 9% | 6.5% | 31% |
| mom k=5 thr=0 | 1.78 | 1.24 | 0.10 | 5% | 3.9% | 20% |
| mom k=10 thr=0 | 1.36 | 0.78 | **0.47** | 7% | 3.9% | 18% |
| tp01-skip | **2.05** | 1.43 | **0.14** | 7% | 4.7% | 27% |
| tp01-half | 1.72 | 1.34 | 0.27 | 7% | 4.7% | 41% |
| IS-best: lin8+tp01-skip | **2.07** | 1.43 | **0.14** | 6% | 4.2% | 27% |
**Multi-cut della IS-best vs baseline: uplift negativo in 5/5 tagli** (0.35 → 0.73, monotono
peggiorando verso il presente). **DSR** IS-best 0.709 (<0.95); baseline 0.472 dentro questa griglia
(contesto onesto: nemmeno il baseline è statisticamente distinguibile su 105 trial correlati — ma è
pre-committed, non selezionato qui). Celle che battono l'hold-out del baseline: **1/105** (lin8pt
tp-off, +0.02 — rumore; non selezionabile: sarebbe selection-on-holdout).
### Frequenza d'intervento dei gate (settimane-trade del baseline = 163)
- **TP01-skip: blocca il 32.5%** delle settimane tradabili (TP01 flat il 38% dei giorni della
finestra DVOL). NON è ridondante col baseline — lavora tanto — ma lavora **male** OOS.
- mom thr=5pt: blocca 24-32%; mom thr=0: blocca 60-64% (quasi metà del book).
### Portafoglio 4-sleeve (VRP @15%)
| VRP nello slot | FULL Sh | FULL DD | HOLD Sh | HOLD DD |
|---|---|---|---|---|
| **baseline** | **2.12** | 7.8% | **2.21** | 3.5% |
| IS-best (lin8+tp01-skip) | 2.11 | 7.8% | 2.12 | 3.5% |
Anche a livello portafoglio la variante **peggiora** l'hold-out (2.21→2.12) e non migliora nulla.
## Lettura (perché non migliora)
1. **L'alpha del VRP è già tutto nel gate IV-rank binario** ("vendi solo vol ricca"). Il sizing
proporzionale al gap IVRV è ridondante *dato* il gate (Δ ≈ ±0.05, dentro il rumore); usato al
posto del gate, riporta dentro le settimane di vol povera e distrugge l'hold-out (0.36/0.38).
Il carry atteso (IVRV) NON è un segnale di *intensità* utile oltre il suo segno+rank.
2. **Il gate TP01 è la trappola in-sample perfetta** (la lezione macro-gate al contrario): schiva il
2022 (6%→0%) gonfiando l'IS a 2.05, ma nel 2025-26 TP01 è flat proprio nei regimi di vol ricca
in cui la vendita gated di put **guadagna** — il gate taglia le settimane migliori dell'hold-out
(0.59→−0.14). Short-vol gated e trend sono complementari, non condizionabili l'uno sull'altro.
3. **Il DVOL-momentum non aggiunge protezione**: il crash-skip IV-rank>0.90 + il long wing dello
spread coprono già il run-up di vol; thr=0 è troppo aggressivo (blocca ~60%), thr=5pt è neutro
(mai meglio del baseline su hold-out).
## Onestà / caveat (invariati)
Premio MODELLATO su DVOL ATM (no skew), book 1d, f di stress reale non catturato → tutto questo
resta dentro il modello; il verdetto massimo possibile era "sleeve modellato migliorato", e non è
stato raggiunto. Il DSR sulla griglia è un limite *superiore* (celle correlate + ~20 config storiche
di options_vrp_lab/_v2 non contate).
## Azione
**Nessuna.** VRP01 resta com'è (`bin + gate_vrp + ivr30 + crash-skip 0.90`, hold-to-expiry).
Terzo tentativo di affinamento fallito (dopo active-management e — per il portafoglio — DVOL
overlay): il filone "migliorare VRP01 dentro il modello" è da considerarsi **esaurito**; il prossimo
passo utile resta quello noto: f di stress reale quando cerbero-bite cattura un crash + skew reale
sul long wing.
Script: `scripts/research/r0701_vrp_refine.py` (`--skip-portfolio` per la sola griglia).
@@ -0,0 +1,74 @@
# 2026-07-01 — Residual (idiosyncratic) momentum cross-sectional sui 19 major HL — SCARTATO/REDUNDANT
**Tesi.** STATARB-RESID (thread 4, 2026-06-29) ha mostrato che il momentum del residuo ETH−β·BTC
(β OLS rolling, **sgn=+1**: le dislocazioni continuano a 1d) passa quasi tutti i gate su 2 gambe,
fallendo solo il deflated-Sharpe (0.929<0.95). Ipotesi qui: portare lo **stesso meccanismo
cross-sectional** sui 19 major di XS01 — per ogni alt, residuo vs β·BTC (β OLS rolling B), momentum
del residuo (blend z-score [30,90] come XS01 o singolo L), long top-k / short bottom-k, vol-target
20% — sperando che la **breadth** (18 stream invece di 1) alzasse il DSR dove il 2-gambe falliva.
Script `scripts/research/r0701_xs_residmom.py` (riusa l'harness collaudato `xsec_v2_nonmom`:
load_matrix, xs_engine — uguaglianza verificata maxdiff 0 —, deflated_sharpe, StrategyPortfolio).
Distinzione dal già-testato: IREV (idio-**reversal**, sgn=1) era FALLITO nel filone C; IMOM di
xsec_v2 usava il mercato equal-weight come fattore, B=60 fisso, senza blend ed era solo riferimento.
Qui fattore = **BTC** (come STATARB-RESID, BTC escluso dal cross-section), B in griglia, blend
z-score, probe con gate di dispersione p30 (parità strutturale con XS01), **selezione in-sample-only**.
## Setup
- Universo: 19 major HL certificati (`data/raw/hl_*_1d.parquet`), 913 giorni [2024-01-01 → 2026-07-01],
barre vol=0 escluse. Fee 0.10% RT/gamba + sweep fino a 0.30%.
- Griglia (57 trial): β-window {60,90,120} × lookback {blend[30,90], 30, 90} × k {3,5} × H {5,10,20}
+ 3 probe gated (blend, k5, H10, gate dispersione p30). Cella scelta col solo Sharpe **pre-2025**;
hold-out 2025-01-01 bloccato. Causalità: prefix-check ok (max_tail_diff 0).
- Baseline (stessa finestra, sleeve attivi): XS01 FULL Sh **1.38** / HOLD **1.51** / DD 11%;
book 4-sleeve FULL 2.12 / HOLD 2.21.
## Esito — collasso OOS della cella in-sample e nessuna cella competitiva
Cella scelta in-sample: **B60 L30 k3 H20** (IS Sh 2.00):
```
FULL +0.67 | HOLD 0.24 | DD 35% | per-anno 2024 +54% / 2025 15% / 2026 +5%
corr→XS01 +0.54 | corr→TP01 0.09 | DSR 0.510 (57 trial) | fee-sweep ok (F+0.59 a 0.30%)
small-cap $600/min$5: haircut ≈ 0 (ma book multi-gamba → STAT-MODE comunque, come XS01)
```
Portafoglio (il bar del mandato):
```
BASE 4-sleeve FULL 2.12 DD 7.8% | HOLD 2.21 DD 3.5%
SOSTITUZIONE XS01 → cand FULL 2.01 (0.10) | HOLD 1.18 (1.03) ← distrugge l'hold-out
AGGIUNTA 5° sleeve @10/15% HOLD 0.31 / 0.53 ← diluisce
MARGINAL vs BOOK: corr +0.23, uplift@10% full 0.04 / hold 0.31, multi-cut 2025 0.31 / 2026 0.14
```
**Il verdetto non dipende dalla selezione** — aggregato delle 57 celle:
- FULL max **+0.94**, HOLD max **+0.82** (mediane +0.52/+0.33): *nessuna* cella si avvicina a XS01
(1.38/1.51), nemmeno cherry-pickando sull'hold-out.
- corr→XS01 in [+0.47, +0.71], mediana **+0.62**: è momentum XS01 travestito (la residualizzazione
vs β·BTC sposta poco: lo z-scoring cross-sectional di XS01 già rimuove implicitamente il mercato).
- Solo 4/57 celle passerebbero un gate "diversificatore" (|corrXS|<0.6, FULL>0.5, HOLD>0), tutte con
FULL ≤0.68 e IS incoerente.
- **corr(Sharpe in-sample, Sharpe hold-out) attraverso le celle = 0.37**: l'in-sample è
anti-predittivo dell'OOS su questa griglia — la firma del rumore, non di un edge con plateau.
## Perché la tesi è falsa (3 righe)
1. La breadth non ha alzato il DSR (0.51 ≪ 0.95) perché non c'è edge da deflazionare: il residuo
vs β·BTC sul cross-section degli alt NON eredita l'edge del 2-gambe ETH−β·BTC — quel lead vive
nella coppia specifica ETH/BTC (i due asset profondi/cointegrati), non nel long-tail degli alt.
2. Cross-sectional, la residualizzazione è quasi un no-op: demeaning z-score (XS01) ≈ togliere il
mercato → il candidato è una variante rumorosa di XS01 (corrXS mediana 0.62) con meno segnale.
3. In-sample = solo 2024 (~1 anno utile dopo il warmup): la selezione onesta atterra su una cella
2024-lucky che perde nel 2025-26 — l'ennesima conferma del gate selection-on-holdout.
## Verdetto: **SCARTATO/REDUNDANT.** Nessuno sleeve, nessun forward-monitor.
Coerente con il filone momentum-structure (2026-06-29): l'edge di XS01 sta nella sua struttura
specifica (blend + gate dispersione), e le sue varianti — incluso l'idio-momentum vs BTC — sono
REDUNDANT o peggio. Chiude anche il cerchio su STATARB-RESID: il meccanismo residuo-momentum resta
valido SOLO come coppia ETH/BTC (forward-monitor `paper_statarb`), non generalizza al cross-section.
Nessun impatto sul book live; config canonica invariata.
Script: `scripts/research/r0701_xs_residmom.py` (non committato, prefisso r0701_xs).
+69
View File
@@ -0,0 +1,69 @@
# 2026-07-01 — Stagionalità CROSS-SECTIONAL sull'universo Hyperliquid → SCARTATO
## Ipotesi
Effetti calendario **relativi tra i 19 alt major HL** (weekday tilt, turn-of-month,
pattern weekend→lunedì nel cross-section), long/short market-neutral. L'angolo è diverso
dal prior art già morto (trackF seasonality BTC/ETH = buy&hold travestito;
crypto_weekend_signal/overnight = look-ahead; open_drive = artefatto calendario ucciso da
`day_boundary_robust`): essendo il segnale **demeaned cross-section**, il buy&hold
travestito è strutturalmente escluso… *in prima battuta* (vedi diagnostica beta sotto).
## Metodo (test statistico PRIMA della strategia)
Script `scripts/research/r0701_xs_seasonal.py`. Dati `data/raw/hl_*_1d.parquet`, 19 major
XS01 (lista `src/portfolio/sleeves.XS_UNIVERSE`), **912 giorni** (2024-01-02 → 2026-07-01,
~2.5 anni), 0 barre vol=0. Ritorno relativo x[t,a] = r[t,a] media cross-section del
giorno. Per ogni bucket calendario: **tilt bucket-specifico** per asset = media di x nel
bucket tilt incondizionato dell'asset (isola il calendario dal drift relativo generico).
**Persistenza split-half**: Spearman rank-corr del vettore tilt (19 asset) H1 vs H2, per
bucket. **Null**: 2000 permutazioni delle etichette entro ciascuna metà → distribuzione del
**max-statistic** (controlla il multiple-testing sui bucket e il confound "alpha persistente
dell'asset"). Soglia severa p<0.05 sul max. Regola del mandato: senza persistenza →
**nessun backtest**.
## Numeri
| Test | Statistica | Null 95° pctl | p | Esito |
|---|---|---|---|---|
| [A] Weekday (7 bucket) | max rank-corr **+0.511** (Wed); Mon +0.38, Sun +0.37, Fri +0.04 | +0.604 | **0.159** | FAIL |
| [B] Weekend vs feriali | +0.268 | +0.428 | **0.178** | FAIL |
| [C] Turn-of-month (±2gg) | +0.221 | +0.451 | **0.226** | FAIL |
| [D] IC weekend→lunedì | FULL 0.053 (t=1.94); H1 0.006 (t=0.17) vs H2 0.100 (t=2.4) | — | non persiste | FAIL |
Con ~65 osservazioni per weekday per metà, lo std di una rank-corr su 19 asset è ~0.24 → il
max-su-7 sotto puro rumore arriva a ~0.60: il +0.51 reale è *dentro* il rumore.
## Diagnostica: perché tutte le rank-corr weekday sono positive?
Non è tilt idiosincratico, è il **canale-beta**: il mercato EW ha un pattern weekday di
*livello* che si ripete nelle due metà (Sun 42/30 bps, Sat +26/+25, Mon +35/+32) e la
dispersione di beta (0.53→1.26) lo proietta nel cross-section — rank-corr(tilt, beta):
**Sun 0.642**, Sat +0.325, feriali ~0. Cioè la poca "persistenza" visibile è l'effetto
weekday di MERCATO (dominio trackF, già scartato come buy&hold travestito) che rientra
dalla finestra via beta. Un eventuale L/S "weekday tilt" sarebbe stato in gran parte un
book short-beta-la-domenica — non un edge calendario cross-sectional.
## Note sui gate non raggiunti
- **day_boundary_robust** (obbligatorio per ogni effetto calendario): NON eseguibile sui
19 alt — i dati HL locali sono **solo 1d**, il confine giorno non è ri-tagliabile. Anche
con persistenza, il verdetto massimo sarebbe stato LEAD-forward *condizionato* a barre
orarie HL, mai sleeve. Con lo SCARTATO allo step 1 il punto è moot, ma resta il vincolo
per chiunque riapra il filone.
- **Fee**: mai arrivati al backtest; nota strutturale: un weekday-tilt L/S ribilancia ogni
giorno (weekday di domani ≠ oggi) → turnover ~2×gross/die, morte-per-fee quasi certa a
0.10% RT anche con edge lordo.
- **DSR**: non calcolato (nessuna cella backtestata — il branch strategia esiste nello
script ma non si attiva senza persistenza).
## Verdetto
**SCARTATO** allo step statistico, senza backtest. Tre motivi: (1) nessuna persistenza
split-half sopra il null permutato (p 0.160.23 su tutti i test, IC weekend→lunedì non
persiste tra le metà); (2) la sola struttura visibile è il canale-beta di un pattern
weekday di mercato — la stessa famiglia già scartata in trackF, non un effetto
cross-sectional; (3) ~2.5 anni × effetto calendario × turnover giornaliero = rumore +
morte-per-fee anche nello scenario migliore.
File: `scripts/research/r0701_xs_seasonal.py` (deterministico, seed 20260701, ~2 min).
@@ -0,0 +1,132 @@
# 2026-07-02 — Audit anchor timing-luck su XS01 e SKH01 (chiusura del pendente dell'ondata TIMING)
**Contesto.** L'ondata TIMING+CRT dello stesso giorno (`2026-07-02-timing-crt-wave.md`) ha stabilito
che l'hold-out di TP01 (0.31) è la **migliore delle 24 ancore daily possibili** (mediana 0.04,
P~0.86 di uno spike così per caso). Lo scettico ha flaggato l'audit come **pendente** sugli altri
due sleeve a ribilanciamento/griglia ancorata: **XS01** (fase del ciclo di ribilanciamento H=10
giorni) e **SKH01** (offset della griglia dual-TF 230m/690m, `origin='epoch'`). Questo diario
chiude entrambi. Due agenti indipendenti, metodologia identica allo scettico TP01
(`r0702_skeptic_offset.py`): ancore dichiarate **a priori**, parametri **identici** in ogni
fase/offset (zero tuning per-ancora), **sanity replica bit-exact** della sleeve canonica prima di
qualsiasi numero, block-bootstrap congiunto per P(spike).
**Script:** `scripts/research/r0702_anchor_xs01.py`, `scripts/research/r0702_anchor_skh01.py`.
Nessun file di produzione toccato dagli agenti (solo docstring/narrativa aggiornate a valle, qui).
---
## Verdetto in una riga
**Il finding TP01 si replica su TUTTI e tre gli sleeve ancorati — su SKH01 più forte che su TP01 —
e i numeri headline del book (HOLD 2.46) sono in parte best-of-anchors.** Ciò che sopravvive
de-luckato: XS01 resta un diversificatore ammissibile (ensemble di fase FULL 1.25 / HOLD 1.31 /
DD 11%); SKH01 resta ADDS (uplift del blend positivo a **tutte** le 23 fasi, corr ~0.08) ma i suoi
numeri headline e — cruciale — **il gate DD<30% che l'ha selezionata** non reggono alla fase
mediana. Stima onesta de-luckata del book 5-sleeve: **HOLD ~1.92.1, FULL ~2.02.2** (vs 2.46/2.24
dichiarati).
---
## XS01 — fase del ciclo di ribilanciamento H=10 (10 fasi)
Sanity: replica di `_xsec_returns` con parametro `phase`**max|Δ|=0.0 bit-exact** vs la canonica.
NB: la canonica sui dati di oggi fa FULL 1.367/HOLD 1.479/DD 10.8% (i dichiarati 1.50/1.71/11%
erano del 2026-06-19; deriva dati, confronto interno coerente).
| metrica | min | mediana | max | canonica (f0) | pctl f0 |
|---|---|---|---|---|---|
| Sh FULL | 0.41 | 1.21 | 1.64 | 1.37 | 85° |
| Sh HOLD | 0.15 | 1.17 | 1.71 | 1.48 | 65° |
| maxDD | 10.0% | 15.5% | 29.1% | 10.8% | **15°** |
- **Firma diversa da TP01: la fortuna NON è nell'hold-out** (65° pctl, non estremo) **ma nel
DD** (15° pctl: il "DD 11%" dichiarato è uno dei più bassi delle 10 fasi; la fase tipica fa
~15.5%, la peggiore 29%) e nel FULL (85°).
- **Bootstrap**: spike osservato +0.38 su hold-out; **P(una fase qualsiasi ≥ +0.38) = 0.910.94**
(block 10/20/40, B=4000) → la canonica è il massimo atteso di 10 stime correlate (corr mediana
fra fasi 0.71).
- **Ensemble 10 fasi** (lens di reporting onesta): **FULL 1.25 / HOLD 1.31 / DD 10.9%** — la
diversificazione di fase riporta il DD al livello canonico con Sharpe ≈ mediana.
- **Book 5-sleeve**: HOLD 2.44 (canonica) → 2.26 (fase mediana) → 1.75 (peggiore, marginalmente
PEGGIO del book senza XS01 = 1.77) → 2.35 (ensemble). **Eredità di fortuna ~+0.17 HOLD.**
FULL quasi insensibile (2.102.28).
- **Gate di ammissione a fase mediana**: FULL 1.08 / HOLD 1.10 / DD 20.7% — **i numeri dichiarati
non reggono** (Sharpe 0.3/0.6, DD raddoppia). **La decisione però regge**: nessuna fase
negativa, 8/10 con FULL≥1.0, book migliore a ogni fase tranne la peggiore (dove è neutro) →
slot da diversificatore @15% difendibile; cambia la NARRATIVA (banda/ensemble, non 1.50/1.71/11%).
- **Caveat**: storia ~2.5 anni (CI95 Sh HOLD canonica **[0.04, +2.72]** — nessuna stima puntuale
affidabile); dimensione **ora-del-giorno non testabile** (solo barre 1d HL: resta luck residua
10 fasi × 24 ore non certificabile); XS01 è STAT-MODE → impatto su reporting/gate, non sul book
live Deribit.
## SKH01-V2-DD — offset della griglia dual-TF 230m/690m (23 offset × 30m)
Sanity: offset 0 riproduce `_skyhook_returns()` **bit-exact** (max|Δ|=0.0 su 2666 giorni); maxDD
harness BTC 21.4%/ETH 27.4% = identici al diario di ammissione; riuso diretto di
`skyhook_entries`/`htf_features`/`merge_htf_to_ltf` con `resample(origin='epoch', offset=...)`,
confini 690 ⊂ 230 verificati a ogni offset.
| metrica (book 50/50) | min | mediana | max | off0 (canonico) | pctl off0 |
|---|---|---|---|---|---|
| Sh FULL | 0.78 | 1.05 | 1.48 | 1.46 | 93° |
| Sh HOLD | 0.44 | 0.93 | 1.64 | 1.64 | **98° (max)** |
| minFull (2 asset) | 0.35 | 0.67 | 1.01 | 0.99 | 93° |
| minHold | 0.10 | 0.39 | 1.25 | 1.25 | **98° (max)** |
| blend 0.75·TP01+0.25·SKH, HOLD | 0.49 | 0.72 | 1.16 | 1.16 | **98° (max)** |
- **È uno spike, non un plateau**: gli offset adiacenti ±30m crollano (book HOLD 1.64 → 0.88 a
off30). Firma identica all'ancora TP01, ma **più forte**: il canonico è al 9398° pctl di OGNI
metrica; minHold +1.26 e blend "0.31→1.17" sono il **massimo dei 23**.
- **Gate DD<30% — il criterio per cui V2-DD fu selezionata — FALLISCE in 15/23 offset**
(mediana DD: BTC 23.5%, ETH **29.2%** — pass per 0.8pt; peggiori 35.9%/42.1%). Il margine ETH
"già sottile" (27.4%) è in realtà **sotto la mediana di fase**: la proprietà DD<30% è in larga
parte fortuna di fase.
- **Ciò che regge de-luckato**: **uplift del blend positivo a TUTTE le 23 fasi** (min +0.18,
mediana +0.42, canonico +0.86) e corr→TP01 in [0.05, 0.11] a ogni fase → il verdetto
ADDS/diversificatore sopravvive, ridimensionato. Alla fase peggiore invece non regge
(minHold 0.10, DD fail).
- **Bootstrap**: spike blend +0.44; **P(un offset qualsiasi ≥ +0.44) ≈ 0.70** (block 10/20/40);
P(uplift≤0) = 0.030.04 → l'uplift è reale, l'ampiezza è best-of-23.
- **Book 5-sleeve**: HOLD 2.44 (off0 = max dei 23) → mediana **1.96** → ensemble 2.12; FULL 2.24 →
mediana 2.01. **Eredità di fortuna ~+0.5 HOLD** — molto più dei ~+0.10 dell'ancora TP01.
- **Rilevanza LIVE (SKH = 25% del book Deribit reale)**: il cron è orario, i confini 230m no →
ritardo uniforme {0..50} min (media 25). Re-sim del path reale (fill al close 5m del prossimo
run orario, exit SOFTWARE come da `book.py`): book 50/50 **FULL 1.46→1.19, HOLD 1.64→1.15,
DD 18.1%→24.6%**. La maggior parte del gap è l'assunzione fill-al-livello del backtest, non il
ritardo orario in sé: nei crash le barre 230m **gappano attraverso lo SL software** (short
sl2% modellato 2% → realizzato **11/23%**: ETH 2021-05-19, 2021-01-04, COVID 2020-03-13).
Il disaster-SL on-book 30% copre solo la coda estrema della posizione netta.
- **Caveat**: equity daily-step (lens Sharpe, come il canonico); l'ensemble di offset NON è
eseguibile live (gira una sola griglia) → serve solo come stima de-luckata; sim hourly senza
slippage/parziali.
## Book 5-sleeve — stima de-luckata congiunta (approssimata)
Ogni audit varia UN solo sleeve (gli altri restano canonici), quindi gli effetti non si sommano
esattamente; ordine di grandezza dell'eredità di fortuna sull'HOLD 2.46: TP01-ancora ~+0.10,
XS01-fase ~+0.17, SKH01-offset ~+0.5. **Stima onesta: HOLD ~1.92.1, FULL ~2.02.2, DD ~6%
(invariato)** — il book resta largamente positivo e diversificato a ogni combinazione testata,
ma il 2.46 è un massimo di ~24×10×23 configurazioni di ancora, non la stima centrale.
## Regole codificate in narrativa (CLAUDE.md aggiornato)
1. **I numeri headline di OGNI sleeve ancorato si citano con la banda d'ancora** (o come ensemble
di fase): vale già per TP01, ora anche per XS01 e SKH01 e per l'HOLD del book.
2. **Un gate di selezione (es. DD<30%) va verificato sulla banda di fase, non sull'ancora
canonica** — SKH01-V2-DD fu selezionata per una proprietà che tiene in 8/23 fasi.
3. Il candidato gate `anchor_luck_band()` in altlib sale di priorità: tre sleeve su tre ancorati
mostrano la stessa firma, e il deflated-Sharpe non conta questo multiple-testing.
## Follow-up (non eseguiti, da valutare)
- **Rivalutare il peso 25% di SKH01 nel book live Deribit**: l'aspettativa onesta della gamba SKH
è ≈ fase-mediana + path orario (blend HOLD ~0.72, non 1.17) con gap-through-stop reale nei
crash. L'uplift resta positivo a ogni fase → non c'è motivo di rimuoverla, ma il sizing fu
deciso su numeri best-of-23.
- Cadenza cron a 230m (o trigger sui confini di barra) per chiudere il gap di path orario.
- `anchor_luck_band()` in `altlib.py` come gate standard per candidati ancorati.
- Audit ora-del-giorno di XS01 quando esisterà un feed HL intraday certificato.
**Stato:** XS01/SKH01/pesi/book live INVARIATI (nessun cambio operativo da questo audit — è un
audit di reporting e di gate, e ogni cambio pesi dovrà passare `weights_tilt_null` +
selection-on-holdout). Test suite 168 verdi. Script audit committati.
@@ -0,0 +1,168 @@
# 2026-07-02 — Ondata "video claims": Elliott (3 filoni), Albimarini (2), capital scaling 2-5k
**Contesto.** Su richiesta: meccanizzare e testare le claim falsificabili di 4 video didattici
italiani (3 sulle onde di Elliott, 1 ricostruzione della "strategia Albimarini" — double diagonal
a credito su SPX), più l'audit dei muri di scala visto l'annuncio che il conto live verrà portato
a **2.000-5.000 $**. Sei agenti indipendenti, harness altlib, fee 0.10% RT, hold-out 2025-26 mai
usato per selezionare, banda d'ancora obbligatoria (regola dello stesso giorno). Nessun PASS →
nessuno scettico necessario. Nessun file di produzione toccato.
**Scripts:** `scripts/research/r0702_ell_{rangecycle,fibconfluence,channel}.py`,
`r0702_alb_{structure,claims}.py`, `r0702_capital_scaling.py`.
---
## Verdetto in una riga
**Elliott 3/3 SCARTATO** (range-cycle = rumore 0/24 Bonferroni; canale = Donchian travestito che
non batte il Donchian; Fibonacci = effetto posizione, non numeri magici). **Albimarini 2/2
SCARTATO** (la diagonale non domina nemmeno nel modello ed è fee-negativa su Deribit; il track
record dichiarato è consistente con zero skill al 20-45%, e va in rovina in ogni finestra storica
con una coda). **Capital scaling: l'unico vincolo vero a 2-5k è il cap $300/asset** — da alzare a
equity/2 al momento del deposito; tutto il resto si scioglie da solo o resta fuori comunque.
---
## ELL-A — "range-cycle" (onda 1 compressa → onda 3 ampia): RUMORE
Claim di Frost&Prechter/Larry Williams meccanizzato senza conteggio soggettivo: 2 definizioni di
segmento (flip TSMOM, zigzag k·ATR causale), impulso iniziale (N∈{3,5,10} barre, range/ATR
pre-segmento) vs ampiezza del seguito (claim A) e troncatura dell'ultimo terzo (claim B).
BTC/ETH 1d+1w, Spearman con null permutato (2000), Bonferroni m=24.
- **0/24 celle significative** (miglior p raw: A 0.061, B 0.058; Bonferroni 1.00 ovunque, FULL e
pre-2025). 7-9/12 celle col segno "giusto" = moneta su celle correlate.
- **Nessuna cella weekly regge a tutte e 7 le ancore** (p 0.02-0.05 di singole ancore = il
timing-luck d'ancora che da oggi non crediamo più; alcune celle flippano segno tra ancore).
- **Artefatto previsto e smascherato**: normalizzando col range POST-impulso la correlazione
diventa negativa per pura meccanica del denominatore — chi "conferma" il claim così misura
l'artefatto.
- Coerente con le famiglie di compressione già fallite nello sweep 104 (BRK08 NR7, BRK10
BB-squeeze, CMB05, VOL12). Campione strutturalmente piccolo (mediana 78 segmenti daily, ~30
weekly). Strategizzazione correttamente non eseguita (statistica prima della strategia).
⚠️ **LEZIONE PANDAS (gemella di `view("int64")` del 2026-07-01):** `resample("7D",
origin=...)` in pandas 2.x **ignora silenziosamente `origin`** ("D" non è Tick-like, solo un
RuntimeWarning) → tutte le ancore weekly uscivano identiche e la banda d'ancora sarebbe stata una
banda finta di larghezza zero. Serve **`"168h"`**. Da ricordare per ogni futura banda d'ancora
settimanale.
## ELL-B — Confluenza di Fibonacci: EFFETTO POSIZIONE, non numeri magici
Zigzag causale non-repainting (livelli usabili solo dalla conferma del pivot, causality_ok
max_tail_diff=0.0), tocco fresh intrabar, reazione ATR-normalizzata a 5/20 barre, ~24k/14k tocchi
IS a 1h. **Tre null in scala di durezza**: (A) rapporti uniformi casuali, (B) ri-sorteggiati per
swing, **(C) location-matched** (Fib ± jitter 2-8%: "0.618 è speciale vs 0.58/0.66?").
- Vs null A/B i Fib sembrano buoni (pctl 0.82-1.00) — **vs null C crollano a 0.39-0.68 = puro
caso**. L'apparente vantaggio è interamente l'effetto di *posizione* (i rapporti Fib cadono in
zone mediamente decenti del range), non dei numeri di Fibonacci.
- **Confluenza** (2 griglie entro 0.25·ATR): FAIL 4/4 celle — non reagisce più delle confluenze
di rapporti casuali. Break-rate al tocco ~46-50% (moneta); su 1h i Fib veri vengono bucati più
spesso del placebo.
- In assoluto comunque nulla da tradare: +2.6/+5.6 bps a 5 barre (fee = 10 bps), negativo a 20
barre e su 1d. Strategizzazione correttamente saltata da gate a priori.
- **Pattern di test riusabile**: il null location-matched è IL test giusto per ogni claim su
"livelli speciali" (Fib, pivot, round numbers) — separa la qualità della posizione dal numero.
## ELL-C — Tecnica del canale (Ftaonline): DONCHIAN TRAVESTITO
Implementazione onesta completa (zigzag causale, vincolo onda-2>origine, canale 0→min-2 con
parallela dal max-1, entry al close della barra fuori, target 1.618×, stop=invalidazione,
speculare short, 27 celle TF×k×varianti).
- **family_honest boccia**: cella scelta in-sample (1h k4 long, IS 1.40) → hold-out **0.87**;
DSR 0.685 < 0.95; earns_slot=False. Marginale vs TP01: uplift positivo solo 2020-21 =
beta-trend del toro (corr 0.35).
- **Il Donchian banale a pari geometria/frequenza eguaglia o batte il canale a ogni TF**
(corr 0.43-0.53): vincoli d'onda + 1.618 non aggiungono nulla. Il segnale-2 ("onda 5") è
quasi inerte (+0.00-0.07).
- **Target 1.618 = geometria, non magia**: toccato con la frequenza di distanze identiche
piazzate a caso (5/6 celle p>0.18). Claim discriminante "in canale = correttivo":
direzionalmente sensata, mai significativa (p 0.08-0.45); l'uscita dal canale è momentum da
breakout, già in casa.
- **Anchor-luck di nuovo**: la miglior cella 4h fa hold 1.54 all'ancora 00:00, la migliore delle
4 (banda [0.35, 1.54]) — quarta conferma della firma nello stesso giorno.
## ALB-A — Double diagonal "Albimarini" su BTC/ETH: NON DOMINA, niente LEAD
Portata su Deribit (che ha le scadenze giornaliere per la long T+1) col motore DVOL di VRP01
(riprodotto esatto: 1.09/0.59/11.8%), strike scalati in vol (2σ/5g ≈ il "9% su SPY"), gate
IV-rank canonico non riottimizzato, 2021-26 con LUNA/FTX/2022, banda skew f∈{0.6,0.8,1.0,1.3}.
- **Il claim strutturale del corso è falsificato**: gated, l'iron condor stessa-scadenza batte la
diagonale a ogni f (1.05 vs 0.95 a f=1.0), Δ negativo ogni anno. La long T+1 è **assicurazione
di coda quantificata** (+12/+33 bps nei 5% peggiori vs ~1 bps di costo medio), non dominanza.
- **Senza gate tutte le strutture perdono** a f≤1.0 → terza conferma indipendente: nel VRP
l'alpha è il filtro di regime, non la vendita di premio. VRP01 resta superiore su tutta la
banda f (CAGR 8.3% vs 1.4%).
- **Il meccanismo dell'illusione riprodotto in vitro**: celle z≥2.5 = 0 perdite su 142 trade,
Sharpe 5.9-∞ (il punto cieco CC01 in forma opzioni); la best in-sample (7.88) crolla a 0.51
in hold-out. Seconda occorrenza del pattern "0-perdite = Sharpe implausibile" in una settimana
**si rafforza il caso per il gate `implausible_sharpe` in altlib** (raccomandato dal filone
CC01, ora con 2 casi d'uso).
## ALB-B — Audit dei numeri dichiarati (28 trade, 82%, PF 5.16, "420% annuo"): ZERO SKILL
SPY 1d 1996-2026 (parquet già in repo dal filone GTAA) + BTC/ETH certificati; MC 200k; replay
claim-anchored calibrato per riprodurre esattamente il video.
- **L'82% è incoerente col "deep OTM" in entrambe le letture**: strike a 9% → win strutturale
99.5% (P(|move 4td|>9%) = 0.53%, fat-tail 88× la normale); 82% letterale → strike a 2.63% ≈
1.2σ, non deep. In entrambi i casi win-rate = delta venduto.
- **P(track record del video senza edge) = 20-45%**; il **78.6%** di tutte le finestre 6-mesi
1996-2026 lo avrebbe prodotto (lettura deep). Il PF ~5.1 esce per costruzione quando la coda
non è campionata.
- **Replay attraverso le code reali**: rovina nel 1998/2002/2020 col sizing 1→4 dichiarato;
perfino regalando +20% di premio, 1 contratto fisso fa CAGR +4.1% con maxDD 95%. La stessa
semestrale del video annualizza a +73-77%, non 420%. Su BTC/ETH a EV=0: +12%/DD68% e
+0%/DD88%.
- **La diagonale lascia passare il 12-40%** della perdita naked in un 10% overnight (dipende dal
vol-spike). Su Deribit la double diagonal è **fee-negativa a qualsiasi size** (fee 8 gambe =
194-221% del theta raccolto a questi strike): il capitale sposta solo il muro di margine.
- Che cosa distingue VRP01 (sopravvissuto allo stesso tipo di audit): defined-risk per
costruzione, gate IV-rank che ribalta l'hold-out, sizing fisso — l'opposto esatto su tutti e
tre gli assi.
## Capital scaling 600 → 2000/3500/5000 (r0702_capital_scaling.py)
| capitale | TP01 haircut Sh | book investibile % (cap $300) | K=2 exec-turn % | statarb haircut | spread ETH conc. | XS01 exec-turn % |
|---|---|---|---|---|---|---|
| 600 | +0.010 | 100.0% | 90.5 | 0.004 | 0 | 56.9 |
| 2000 | 0.002 | 85.9% | 95.7 | 0.000 | 3 | 87.4 |
| 3500 | 0.002 | 63.7% | 97.5 | 0.000 | 5 | 89.3 |
| 5000 | 0.002 | **48.9%** | 98.2 | 0.000 | 7 | 90.8 |
- **Il vincolo dominante è UNO: `max_notional_per_asset_usd`=300.** A 5k il book girerebbe a
metà del target (cap binding nel 39-46% delle barre). **Proposta config (da applicare AL
deposito): cap = equity/2** → $1000 a 2k, $1750 a 3.5k, $2500 a 5k. `min_order_usd`=5 va
LASCIATO (il fee drag risale solo al tetto noto ~0.4%/anno; l'isteresi artificiale costerebbe
più in lag — lezione ondata timing).
- Min-order/haircut TP01 ≈ 0 a ogni capitale (conferma indipendente del "74% ordini" a 600 →
39-43% saltati a 5k, tutti micro). Statarb: haircut 0 da 2k (il muro era l'edge, non la scala).
- Tranching K=2: matematicamente regge a 5k (98.2% turnover-tranche), ma il blocco vero resta il
feed intraday fuori path certificato + beneficio solo di varianza → **non cablare**.
- Opzioni: il muro d'ingresso ETH cade a ~2.6k (3-7 spread concorrenti a 2-5k, fee solo 5-6% del
credito grazie al cap 12.5%; rettifica vs ALB-A: margine spread ETH oggi $66-76). BTC granulare
da ~$4.7k. **La regola "niente short-vol da modello" non decade col capitale.**
- XS01: soglia ~20k confermata (a 5k il 9%+ del turnover non esegue). CC01: il capitale non è
mai stato il muro (fuori per ragioni strutturali).
- **Aspettativa onesta**: col CAGR de-luckato del book live (10-15%, audit SKH01): **2k ≈
€0.55-0.82/giorno; 5k ≈ €1.37-2.05/giorno**. Il salto di capitale cambia cosa è eseguibile,
non l'ordine di grandezza del ritorno (€50/g ≈ 130k, invariato).
## Lezioni
1. **Il null giusto smonta il livello "speciale"**: location-matched (ELL-B) per i livelli,
Donchian-equivalente (ELL-C) per i pattern, EV=0-calibrato (ALB-B) per i track record. In
tutti e tre i casi il claim sopravviveva ai null ingenui e moriva su quello giusto.
2. **`resample("7D", origin=...)` ignora origin in pandas 2.x** → usare `"168h"` per le bande
d'ancora settimanali.
3. Secondo caso "0-perdite = Sharpe implausibile" (celle deep-OTM di ALB-A, dopo CC01) → il gate
`implausible_sharpe` in altlib sale in coda ai lavori insieme ad `anchor_luck_band`.
4. L'anchor-luck è comparso spontaneamente anche in questa ondata (celle weekly ELL-A, 4h ELL-C)
— la regola della banda d'ancora sta già pagando.
**Stato:** nessun nuovo sleeve, nessun forward-monitor aggiunto, book live INVARIATO. Un'azione
operativa pende sul FUTURO deposito: alzare `max_notional_per_asset_usd` a equity/2 (decisione
utente al momento del funding). Test suite verde. 6 script committati.
+186
View File
@@ -0,0 +1,186 @@
# 2026-07-02 — Ondata timing + CRT (8 filoni multi-agente + scettico): 0 nuovi sleeve, 1 finding strutturale (anchor timing-luck di TP01)
**Obiettivo (goal utente):** "cerca su Deribit altre strategie profittevoli magari con timing
differenti oltre a quelle già valutate". Prima ondata interamente dedicata al TIMING: dopo che le
ondate precedenti hanno coperto segnali (104 famiglie alt-sweep), universi (HL cross-sectional),
opzioni (VRP/gamma) e pesi (EW-STR/weights_tilt_null), qui si attacca la dimensione rimasta: *quando*
si campiona, si decide e si esegue. Su richiesta utente, seconda tranche dedicata alla **CRT (Candle
Range Theory)**, il pattern sweep-and-reclaim a 3 candele di scuola ICT/Wyckoff.
Inventario preventivo per non rifare lavoro: SEA01-09 coprivano già hour-of-day, day-of-week,
weekend, turn-of-month, sessioni; l'onda intraday 2026-06-21 il sub-daily (con il lead prevday in
forward-monitor); `tp01_lowfreq` i TF 4h/12h/1d. Angoli NON coperti individuati e testati: clock a
eventi, calendario scadenze Deribit, ancora di ribilanciamento, clock più lenti del daily, velocità
del segnale regime-condizionata — più i 3 tagli CRT (base, multi-TF, contesto).
**Esito: 7 filoni FAIL + 1 finding strutturale confermato dallo scettico (timing-luck dell'ancora
di TP01). Nessun nuovo sleeve. Nessuna modifica al book live. Il soffitto ~1.3 direzionale
BTC/ETH resta intatto anche cambiando il clock.**
---
## Filone 1 — Event-clock bars (tempo-informazione): FAIL
`scripts/research/r0702_eventclock.py`. Volume/vol/range bars da 5m certificato (soglie causali
EWMA-90g shift(1), barre medie 4h/12h/24h), 5 strategie (TSMOM multi-orizzonte, Donchian 10/30d,
EWMA-cross), 45 celle event + 15 controlli wall-clock = 60 trial.
- Null decisivo (stesso segnale, stessa frequenza, wall-clock): event batte wall su ENTRAMBE le
finestre solo in **4/45 coppie (9%)** — rumore. Pattern incoerenti (EWMA event vince IS 9/9 ma
perde HOLD 9/9; Donchian-30d l'esatto opposto = selection-on-holdout in agguato).
- Cella scelta in-sample (volume-bars 24h, DONCH-10d): IS 1.45 → **HOLD 0.46** (2025 7.4%,
2026 18.1%). Marginal NEUTRAL (corr 0.74 a TP01 = trend travestito), earns_slot_honest=False.
- Executability comunque assente: in alta attività le barre "24h" chiudono in 3.6-4.6h (p5) → il
cron orario le eseguirebbe in ritardo; i clock 4h richiedono monitoraggio sub-orario.
**Lezione: campionare a tempo-informazione non normalizza nulla di monetizzabile sul feed
certificato; il clock non è la dimensione dove vive l'edge.**
## Filone 2 — Calendario scadenze Deribit: FAIL (0/24 celle)
`scripts/research/r0702_expiry_calendar.py`. Griglia dichiarata a priori: 4 finestre × 3 tipi expiry
(weekly ven 08:00 UTC / monthly ultimo ven / quarterly) × 2 asset, Bonferroni |t|≥3.08; 3 null
(placebo weekday, anchor-shift ±2/4h, permutation 500 calendari).
- Nessuna cella passa Bonferroni (max |t| 2.69). Il post-expiry drift monthly (+0.61/+0.77%) ha il
segno della teoria ma: non batte il placebo giovedì, permutation pctl 84-95 (non estremo), si
INVERTE sul quarterly (dove l'OI massimo dovrebbe amplificarlo) ed è guidato dal 2019 → rumore.
- Unica cella robusta ai null: weekly [-24,0) negativa (gio→ven), ma è indistinguibile dal
day-of-week (famiglia SEA già morta) e netta fee fa Sharpe ~0.08 (52 eventi/anno × 0.10% RT).
- Best-in-sample tradabile: IS +0.90 → **HOLD 0.52**; DSR 0.230 su 24 trial.
- Nota tecnica: colpito ESATTAMENTE il pitfall pandas 2.x documentato (epoca in secondi da
`date_range` su tz-aware → matching vuoto); fix con epoca ms esplicita. La lezione 2026-07-01
ha pagato.
## Filone 3 — Anchor timing-luck di TP01 + tranching: FINDING (verificato dallo scettico)
`scripts/research/r0702_tp01_offset.py` + scettico indipendente `r0702_skeptic_offset.py`
(ricostruzione bit-exact con codice diverso, zero riuso; h=0 riproduce `tp01_baseline_daily`
esattamente; vol-target ricalcolata per ancora; nessun look-ahead — verificato con troncamenti).
**Claim 1 CONFERMATO: l'hold-out 2025-26 "Sharpe 0.31" di TP01 è in larga parte fortuna
dell'ancora 00:00 UTC.** La stessa strategia CANONICAL alle altre 23 ancore orarie: HOLD mediano
**0.04**, banda **[0.13, +0.30]** — e il massimo è proprio h=0 (98° pctl; in-sample era al 10°:
sfortunato lì, fortunato qui). Spike, non plateau (h=23/h=1 fanno 0.13/0.04). Bootstrap dello
scettico: P(una qualsiasi ancora mostri uno spike ≥ così) = **0.86** — è il massimo atteso di 24
stime correlate, non un'anomalia; best-anchor per finestra annuale ruota a caso (16→23→21→12→5→0,
Spearman ≈ 0, nessuna seasonality d'ancora). Formulazione corretta (NON "il vero hold-out è 0.07",
che ha CI95 [1.2,+1.4] su 547 giorni): **l'hold-out 2025-26 non risolve l'edge di RITORNO di TP01**
(ritorno totale mediano ancore ≈ 0%); ciò che regge A OGNI ancora è il claim DIFENSIVO
(DD 6.7-10.1% vs ~60% B&H). Che è da sempre il vero valore dichiarato di TP01.
**Claim 2 (tranching multi-ancora) RIDIMENSIONATO:** K=4 ≡ esattamente EW di 4 book ancorati
(diff 1.4e-17), turnover identico (~8.3/y), haircut $600 ≈ 0. MA il "miglioramento" IS 1.49→1.56 è
per ~90% *tornare alla media delle ancore* (h=0 era sfortunato in-sample): vs ancora tipica
+0.005 mediano, P(K4≤h0)=0.18 n.s.; il taglio DD strutturale è ~0.5pt (non 2.8: la mediana delle
singole è già 12.6%). Ciò che regge: la compressione della VARIANZA DELLA STIMA (HOLD
[0.12,+0.30]→[0.01,+0.13] a K=4) → **lens di reporting, non alpha**.
**Impatto a valle (quantificato dallo scettico):**
- Blend SKH: HOLD 1.16 (h=0) → 0.97 mediana ancore, ma l'UPLIFT a mediana è +0.93 > +0.86
dichiarato → **il verdetto ADDS di SKH01 era conservativo, regge**.
- Book 5-sleeve: HOLD 2.44 → 2.34 mediana (min 2.22), FULL 2.24→2.22 → eredita **~+0.10** di
fortuna d'ancora (non +0.25: il peso di TP01 diluisce). Nessuna decisione (GTAA/SKH/pesi) cambia.
- NON toccati: tutti i FULL (h=0 al 31° pctl = normale), plateau, deflated-Sharpe, fee-sweep,
causalità, validazione GTAA (equity OOS), gate weights_tilt_null (relativo).
**Raccomandazione operativa (sottoscritta dallo scettico): cambio di narrativa e di standard di
reporting, NESSUN cambio del book live oggi.** (1) I numeri hold-out di TP01 si citano d'ora in poi
come banda d'ancora (mediana ~0.04, [0.13,+0.30]) con valore = taglio DD; (2) valutazione
anchor-agnostic (media 24 ancore) come lens di reporting per i futuri hold-out; (3) NO deploy
K=2/K=4 a $600: guadagno ≈ 0, e a $225/asset di quota TP01 i delta per-ancora (~$1-2) sono sotto il
min-order $5 → degenererebbe comunque in K=1; inoltre le ancore intraday richiederebbero un feed
fresco fuori dal path certificato (staleness ×4 finestre di guasto). **Rivalutare K=2 (0,12) a
capitale ≥ ~5-10k.** (4) ⚠️ Audit analogo RACCOMANDATO su XS01 (rebalance 10g ancorato = spazio di
luck 10g×24h, potenzialmente peggiore) e SKH01 (fase griglia 230m/690m) — TP01 è oggi l'unico
sleeve de-luckato.
## Filone 4 — Clock lenti + banded rebalancing: FAIL (negativo utile)
`scripts/research/r0702_slow_clock.py`. Fatto a monte che chiude il filone: il fee drag di TP01 a
1d è **~0.40%/anno ≈ 0.03 Sharpe** (8 turnover/y × 0.10% RT) — il tetto di QUALSIASI risparmio.
- Clock N∈{2,3,5,7}g: degrado monotono dell'ensemble di fase (HOLD 0.34→0.11 da N=2 a N=7); lo
spread TRA fasi esplode a N≥5 (HOLD 0.19…+0.37 a N=7) = timing luck pura, coerente col filone 3.
- Bande di isteresi {2.5,5,10,20}%: tagliano il 77-94% degli ORDINI ma quasi zero TURNOVER (gli
ordini di TP01 sono micro-aggiustamenti del vol-target). Cella best-IS (band 20%): hold-out
0.13 vs 0.30 baseline, e il "guadagno" IS è effetto-segnale (posizioni stantie fortunate), non
effetto-costo → fitting. Non-monotonia sulla griglia = firma di rumore.
- **Finding utile per il live: a $600 il vincolo min-order $5 È GIÀ la banda ottimale** (ordini
427→111/y a costo Sharpe ~0, banda implicita 1.67%): cattura ~100% del risparmio catturabile.
Nessun cambio al book, a nessun capitale testato (600/2k/10k).
## Filone 5 — Velocità del trend regime-condizionata: FAIL
`scripts/research/r0702_regime_speed.py`. Pesi tra gli orizzonti TSMOM 30/90/180g condizionati al
percentile espandente di vol (realized e DVOL), 16 celle, sanity = riproduzione esatta del canonico.
- Cella best-IS (alta-vol→lento, linear, rv): FULL +0.06 ma **HOLD BTC 0.31**, 50/50 +0.005 →
dominanza fallita; multi-cut a segno instabile (+0.18/0.08/+0.00).
- Null decisivo (300 pesi statici Dirichlet): la cella sta al pctl 0.71-0.72, sotto il p90 —
un peso statico casuale la batte spesso. Meccanismo smascherato: corr(peso-30d, Sharpe) = +0.93 →
le celle "regime" vincono in-sample perché tengono il tilt-30d la maggior parte dei giorni =
**tilt statico travestito da regime**, la stessa trappola di EW-STR. E il tilt statico verso il
30d NON regge su BTC hold-out (0.15). RV e DVOL indistinguibili come misura di regime (coerente
con l'esito overlay DVOL 2026-06-26). Pesi canonici 1/3-1/3-1/3 confermati.
## Filoni 6-8 — CRT "Candle Range Theory" (base / multi-TF / contesto): FAIL 3/3
Il pattern sweep-and-reclaim a 3 candele (C1 range forte; C2 rompe un estremo ma chiude dentro =
"manipolazione"; C3 ingresso contro il breakout, stop dietro lo sweep, target all'estremo opposto),
meccanizzato onestamente in tre tagli. Overlap dichiarato: MRV01-11 e MIC07 non coprivano questa
meccanica; ora è coperta.
**6. Base single-TF** (`r0702_crt_base.py`, 864 trial su 1h/4h/12h/1d, motore trade-level
conservativo SL-first cross-checkato con l'harness): **DSR 0.000** (il null best-of-grid atteso è
Sharpe 2.27, ottenuto 0.74); cella best-IS (4h long color-rule) IS 0.90 → HOLD 0.07 con 2026 a
WR 0%; anchor-shift +1/+2h flippa l'hold-out a 1.0 (artifact-risk); lo **short su sweep dell'alto
(la narrativa smart-money canonica) perde perfino in-sample (0.59)**. Autopsia: l'expectancy IS
veniva dal time-exit in trend (beta del toro ETH 2021-23), non dal target strutturale. Dettaglio
informativo: CRT batte nettamente sia il fade incondizionato (IS 0.49) sia il breakout-confermato
(IS 0.31) → il close-back-inside FILTRA davvero tossicità, ma "meno tossico del fade morto" non è
un edge.
**7. Multi-timeframe** (`r0702_crt_mtf.py`, 4h→15m e 1h→5m, ~10k trade): expectancy netta negativa
OVUNQUE (FULL e HOLD, entrambi gli asset); il MTF alza il R:R medio da ~3 a ~10-20 ma il WR collassa
da ~36% a 9-16% → "migliora" solo perdendo meno. **Refutazione strutturale: il ritest è informazione
negativa** — pattern CON ritest 40 bps, SENZA +52 bps (non tradabile: condiziona sul futuro):
aspettare il ritest per entrare seleziona sistematicamente i pattern peggiori; i buoni scappano
subito e il metodo non li prende mai. A fee ZERO l'edge lordo è ~0 (non è morte per fee: non c'è).
Stop 0.1-0.35% ineseguibili col cron orario (26-75% dei segnali già invalidati all'esecuzione).
**8. Contesto** (`r0702_crt_context.py`, 22 trial: livelli prevday/Donchian/prevweek × equal-H/L ×
FVG × sessioni): baseline incondizionata morta (8/8 celle HOLD<0); FVG semmai peggiora; sessione
EU consistentemente negativa; unica cella IS-positiva (sweep in Asia su livello prevday) uccisa 4
volte (DSR 0.001, anchor-flip a 2/4h con la firma di open_drive — la sessione "Asia" inizia dove
il livello prevday viene ricreato —, solo-ETH, morta a 0.20% fee). **Sottoprodotto prezioso: sugli
STESSI livelli prior-day, FOLLOW batte FADE ogni singolo anno 2019-2026** (follow IS/HOLD
+1.22/+1.25 vs fade 0.66/1.46, corr 0.19/0.27) → conferma indipendente e rafforzativa del lead
prevday-breakout in forward-monitor (paper_prevday).
**Verdetto CRT: concetto Wyckoff riverniciato che, spogliato della discrezionalità, non contiene
edge su BTC/ETH Deribit certificati. La direzione giusta sui livelli affollati resta il FOLLOW
(breakout), non il fade — coerente con SKH01 (breakout) vivo e mean-reversion morta.**
---
## Lezioni codificabili
1. **Il timing-luck dell'ancora è una dimensione di multiple-testing NON coperta dai gate
esistenti** (deflated-Sharpe conta i trial, non le ancore implicite). Nuova regola di reporting:
ogni metrica hold-out di una strategia a ribilanciamento ancorato si cita con la banda d'ancora
(o la media anchor-agnostic). Candidato gate futuro: `anchor_luck_band()` in altlib. Audit
pendente: XS01 (10g), SKH01 (fase 230m/690m).
2. **La famiglia day_boundary_robust / anchor-shift continua a uccidere** (CRT base, CRT-Asia,
6/24 celle expiry): ogni effetto legato a etichettatura di barre VA spostato d'ancora prima di
crederci. Confermata la regola 2026-06-21.
3. **Il fee drag di TP01 (~0.4%/anno) non è un problema da risolvere** — chiude a priori il filone
"esecuzione più furba" a questo turnover; il min-order small-cap è già la banda ottimale.
4. Il pitfall pandas tz-aware/epoca (2026-07-01) è stato evitato/gestito 2 volte su 9 agenti grazie
alla documentazione in CLAUDE.md — il costo di documentare i bug paga.
## Stato finale
- 0 nuovi sleeve; portafoglio e book live INVARIATI (5-sleeve 33/15/12/20/20; book Deribit
TP01+SKH01 75/25, flat da armamento — il segnale resta risk-off).
- Narrativa TP01 aggiornata (CLAUDE.md + docstring): hold-out = banda d'ancora, valore = difesa DD.
- Script: `scripts/research/r0702_{eventclock,expiry_calendar,tp01_offset,slow_clock,regime_speed,
crt_base,crt_mtf,crt_context,skeptic_offset}.py`. Test suite: invariata, verde.
+111
View File
@@ -0,0 +1,111 @@
# 2026-07-03 — Frontiera rischio/rendimento del book: quanto caldo correre a 2k-5k
**Contesto.** Dopo la diagnosi strategica ("€50/g è un problema di capitale e di frontiera, non di
alpha; hai costruito una macchina difensiva a DD 6% ma hai capitale piccolo e obiettivo di
crescita"), goal: **misurare** (non cercare segnali) la frontiera CAGR/DD/P-rovina in funzione del
target-vol, pesata per confidenza per-sleeve, a €2k e €5k — per decidere quanto caldo girare il book.
Workflow: 3 filoni (curva / onestà-della-coda / eseguibile+Kelly), refuter fat-tail su ciascuno,
scettico sintetizzatore. 7 agenti, 0 errori. Sanity bit-exact di entrambi i book prima di ogni numero.
**Scripts:** `scripts/research/r0703_frontier_{curve,tail,exec}.py`. Nessun file di produzione
toccato, nessun commit dagli agenti, `config/live.json` NON modificato (cap solo proposto).
---
## Verdetto in una riga
**La tesi "corri più caldo" era in gran parte un MIRAGGIO DI REGIME.** Il "~6% attuale" non è un
target scelto: è la vol *realizzata* in regime risk-off (TP01 spesso flat 0.0x → il conto è flat
*by design*). A lambda=1 il book LIVE a 2 sleeve gira **già a ~11% vol / 9.4% DD**. Quindi "saltare
da 6% a 10%" NON è aggiungere leva — è solo assumere che il book non sia risk-off. **Il numero
onesto è: gira alla vol NATIVA (~10%, banda 8-11%), non levare.** Guadagno reale vs il 6% risk-off:
**+€0.2/g @2k, +€0.5/g @5k** — reale ma modesto, comprato con un DD plausibile di ~€500 su €2k. €50/g
resta ~130k, invariato.
---
## I numeri (frontiera fidata, non full-Sharpe)
Sanity (deriva nulla): 5-sleeve FULL Sh **2.238** / HOLD 2.452 / DD 6.17% / vol nativa 7.84%;
2-sleeve live FULL Sh **1.776** / HOLD 1.162 / DD 9.42% / vol nativa 10.96%.
**Scale-invarianza confermata da tutti e 3 i refuter:** il capitale NON cambia la matematica del
target-vol (le tabelle sono in %), cambia solo l'ESEGUIBILITÀ → **stesso % a 2k e 5k.**
### Book LIVE 2-sleeve (TP01+SKH01) — l'unico eseguibile <20k
- **Target-vol raccomandato: ~10%, banda [8%, 11%], lambda ≈ 0.9.** Sopra la vol nativa non si va.
- €/giorno al punto fidato (haircut): CAGR full-sample 12.9% → €0.71@2k / €1.77@5k; ma **HOLD-onesto**
(de-luck) CAGR ~4.5% → **€0.25@2k / €0.62@5k**. Il lato-reward headline è ~3× l'onesto (HOLD≪FULL).
- **Stima centrale onesta: €0.3-0.7/g @2k, €0.8-1.8/g @5k.**
### Book PIENO 5-sleeve — ASPIRAZIONALE, non gira <20k
Frontiera fidata regge ~12-15% sotto tail estremo, ~20% sotto tail mite — ma XS01 serve ~20k e VRP01
è modellato → rilevante solo per il tracking di `paper_combo`, non per una decisione di deploy a 2-5k.
---
## I quattro insegnamenti strutturali
### 1. La rovina-50% è la metrica SBAGLIATA (trappola esposta dal curve-refuter)
P(rovina-50%|5y) resta <1% fino a ~20-22% di target-vol su ogni book — i book sono troppo lisci/
diversificati per bruciare metà capitale entro la distribuzione campionaria. **La risposta letterale
"max CAGR a P(rovina)<1%" direbbe "gira al 22%" — ed è un suicidio**: lì P(DD>30%|5y) ≈ 20-25%. Il
vincolo che MORDE è **P(DD>30%), super-lineare** (raddoppia ~ogni 2.5 punti di vol). E la rovina-50%
non è nemmeno robusta ad alta vol (block-15 vs block-20 danno 7.1% vs 0.9% a tv30%) → altro motivo
per stare bassi.
### 2. Il muro fat-tail ONESTO è ~12%, più basso della carta (~15%)
Tre ragioni che il modello sottostima: **(a) gap-through-stop SKH già osservato reale** (sl2%
modellato → 11/23% realizzato — la coda vera NON è nei rendimenti modellati; l'iniezione dei
finder usava lo *clean-stop* → ~2× troppo mite); **(b) il 2-sleeve è 4× più crash-sensibile del
5-sleeve** (+14.5pt vs +3.5pt di P(DD>30) all'iniezione, diversificazione sottile); **(c)
vol-targeting a lambda costante lagga nello spike** → sei più levato *entrando* nel crash.
**LIVE 2-sleeve: non superare ~12%; mai 15-20%** (triplica il DD-in-euro senza margine di coda).
### 3. Aggressività differenziata-per-confidenza (TP01 più caldo di VRP) — REFUTATA
La mia proposta era intuitiva ma **sbagliata, e i numeri lo dicono netto**: differenziare la vol per
confidenza PEGGIORA la frontiera (5s Sharpe 2.24→2.11, 2s 1.78→1.69) perché **taglia la
diversificazione** di VRP/XS (corr uniforme-vs-differenziato 0.98-0.99). **Regola corretta: la bassa
fiducia sull'EDGE si esprime DE-MEANando lo sleeve in aspettativa (= la frontiera haircut), NON
riducendone l'esposizione/vol.** La confidenza vive nell'haircut della media, non nella leva. Tutti
gli sleeve alla stessa leva.
### 4. La diversificazione LIMA la coda sinistra in-sample (sorpresa onesta)
Per il 5-sleeve ben diversificato il block-bootstrap dà P(DD>30) SOTTO il Gaussiano iso-vol (30%:
10.6% reale vs 21.1% gauss) — la coda in-sample è benigna. Il segnale fat-tail vive in due posti:
l'**iniezione di crash sintetico** (il campione non contiene il crash peggiore di ogni sleeve) e
il **book live sottile** (2 gambe, drift haircut) dove il bootstrap SUPERA il Gaussiano. Cioè: la
frontiera è affidabile finché il futuro somiglia al passato campionato, e fragile esattamente dove
le storie sono corte (VRP mai stressato reale, XS 2.5y, nessun 2018/pre-2018).
---
## Azione concreta (proposta, NON applicata)
1. **Nessun cambio di leva sul codice.** Il book gira già ≈ al punto fidato: LASCIARE `target_vol=20%`
di TP01 (canonico, la vol nativa del book emerge a ~8-11%). Non c'è una leva da girare su.
2. **⚠️ L'UNICO cambio che conta: `config/live.json` `max_notional_per_asset_usd` da $300 a
equity/2** ($1000@2k / $1750@3.5k / $2500@5k). Senza, il cap $300 tappa la vol raggiungibile a
13%@2k / 8%@3.5k / **6%@5k****throttling paradossale: più capitale = book più freddo**, forzato
sotto il punto fidato. Da applicare AL deposito. (config NON toccato ora.)
3. `min_order_usd=5`: LASCIARE (banda d'isteresi gratuita). Tranching K=2: NON cablare. Vol
differenziata: NON implementare (Q3).
---
## Brutalità sui limiti
- **Storie corte = il difetto strutturale.** TP01/SKH dal 2019 (no 2018), VRP dal 2021, XS **2.5
anni** (no 2022). Il block-bootstrap non può campionare un crash mai visto; l'iniezione sintetica
è l'unico proxy, e quella dei finder era ~2× troppo mite.
- **VRP01 è MODELLATO** (f-di-stress mai catturato su un crash reale) → l'haircut 50% è stima, non
misura; resta STAT-MODE anche a 5k (regola: niente short-vol da modello in deploy).
- **HOLD ≪ FULL sul book live** (1.78 vs 1.16) → il lato-reward headline è in gran parte artefatto
full-sample; citare i €/g su base HOLD-onesta.
- **€50/g NON è risolto e non lo sarà da questo.** Il warm-up compra ~€0.2/g@2k. La via resta
**capitale + tempo**; la regola "niente leva alta come base" è rispettata (la raccomandazione è
"gira alla vol nativa", non "corri caldo").
**Numero unico da portare a casa:** book LIVE a **~10% target-vol (lambda ≈ 0.9, banda 8-11%)**,
uguale a 2k e 5k, con **cap → equity/2** come unica azione config; muro invalicabile a **~12%**;
guadagno reale vs il 6% risk-off ~**+€0.2/g@2k / +€0.5/g@5k** — reale ma modesto.
+47
View File
@@ -0,0 +1,47 @@
# 2026-07-03 — Cap notional per-asset DINAMICO (= equity/2): operazionalizza la decisione frontier
**Contesto.** La frontiera del 2026-07-03 (`docs/diary/2026-07-03-book-frontier.md`) aveva identificato
**una sola** azione config con impatto reale: portare `max_notional_per_asset_usd` da $300 fisso a
**equity/2**, perché il cap fisso strozza il book man mano che si deposita (paradosso: più capitale =
book più freddo — a $5k il cap $300 fa girare il libro al ~49% del target). Il diario la lasciava
"da applicare AL deposito". Qui la **operazionalizzo in codice** rendendo il cap dinamico, così è
sempre corretta e non richiede un edit manuale al deposito.
## Cosa è cambiato
- **`src/live/book.py``_cap()`**: se in config c'è `max_notional_per_asset_frac` (opt-in), il cap
per-asset diventa **`equity × frac`** (0.5 → equity/2). Senza la chiave → comportamento vecchio
(cap fisso `max_notional_per_asset_usd`). Il call site in `book_report()` passa
`equity`, `real_equity`, `eq_fallback` a `_cap()`.
- **`config/live.json`**: aggiunto `max_notional_per_asset_frac: 0.5` (+ nota). `max_notional_per_asset_usd`
resta come **cap fisso di fallback**.
- **`tests/test_book_live.py`**: +4 test (scaling con equity fidata, fallback su eq_fallback/real=None/
equity 0, no-frac, integrazione online). Suite: **172 passed**.
## Il guardrail di sicurezza (il punto delicato)
Il cap dinamico si usa **SOLO con equity reale fidata** (letta dal conto). Se l'equity reale non è
leggibile — `eq_fallback` attivo, `real_equity=None`, offline, o equity ≤ 0 — si **torna al cap fisso
$300**. Motivo: in fallback `equity` è il paper-cap ($2000 ipotetico); calcolare `equity/2 = $1000` su
un conto di importo reale **ignoto** sizerebbe troppo. Preserva esattamente la protezione downside che
il test `test_book_execute_eq_fallback_warns_but_proceeds` verificava (l'hard-cap $/asset protegge
quando E è ignota). Regola: **equity/2 solo quando ci fidiamo di E; altrimenti $300 fisso.**
## Verifica
- **Live dry-run reale** (nessun `--execute`, nessun ordine): `cap/asset **$299**` = $598.06/2 →
**INERTE** oggi (≡ vecchio $300). Book flat, HOLD.
- Offline / `equity_override`: cap resta **$300 fisso** (nessuna equity reale da fidarsi) → il test
di parità pre-esistente regge invariato.
- A $5.000 di equity il cap diventerebbe automaticamente **$2.500** (equity/2), rimuovendo il
throttling che la frontiera aveva quantificato.
## Impatto e limiti
- **Già attivo**: il cron orario (`cron_book.sh`) esegue dal working tree → il prossimo run legge già
`frac=0.5`. Nessun deploy separato. **Inerte a $600**, si "accende" da sé quando l'equity cresce.
- **NON avvicina €50/g**: la frontiera lo aveva già detto — è una miglioria marginale (+€0.2/g @2k,
+€0.5/g @5k), il cui unico scopo è non lasciare capitale futuro strozzato. €50/g resta un problema
di **capitale + tempo** (~130k @ CAGR onesto), non di questo cap.
- Nessun cambio di **leva** (TP01 `target_vol=20%` invariato, la vol nativa ~10% emerge da sola —
coerente col verdetto frontier "gira alla vol nativa, non levare").
@@ -0,0 +1,156 @@
# 2026-07-03 — STATO COMPLETO DEL PROGETTO (snapshot)
Foto d'insieme dopo le ondate di ricerca del 1-3 luglio 2026 (timing/CRT, anchor-audit,
video-claims Elliott/Albimarini, capital-scaling, migliora-e-proteggi VRP01). Serve come punto di
riferimento unico: *dove siamo, cosa gira, cosa è provato, cosa resta aperto.*
---
## 1. In una frase
Progetto post-reset v2.0.0: su dati Deribit mainnet certificati (solo BTC/ETH) abbiamo costruito un
**portafoglio di 5 strategie diversificate** (research Sharpe ~2.2, DD ~6%), di cui **2 sono
eseguite live su Deribit** in un book nettato in software. Il conto reale è **~$598, flat** perché
il segnale trend è risk-off. Il valore delle strategie è **difensivo** (taglio del drawdown), non
generazione di ritorno: il target €50/giorno resta lontano (serve ~130k di capitale). L'onestà
metodologica è il vero asset accumulato: ~10 gate anti-illusione codificati, decine di edge
falsificati.
---
## 2. Il book LIVE (soldi reali)
- **Conto:** Deribit mainnet, USDC linear, **equity reale $598.06** (NON i €2000 nominali del paper).
- **Cosa gira:** `deribit_book_sleeves` = **TP01 (0.75) + SKH01 (0.25)** nettati in software su un
solo conto; UN ordine con segno per asset (BTC, ETH). `config/live.json`
**`execution_enabled=true`** → esecuzione ARMATA e reale.
- **Cadenza:** cron ORARIO `scripts/cron_book.sh``scripts/live/book_execute.py` (SKH01 decide su
griglia 230m; exit software, latenza fino a fine barra).
- **Guardrail:** cap **$300 notional/asset**, min order $5, **disaster-SL on-book 30%** sulla
posizione netta, alert Telegram su esecuzione/errori, gate fail-safe su posizione/equity non
leggibili (non opera a cieco).
- **Stato corrente (ultimo cron 2026-07-03 07:00Z):** BTC e ETH **flat, HOLD a target** — il target
TSMOM è risk-off (trend 0.0x) e SKH01 è flat (nessun breakout) → **zero ordini reali mai eseguiti**
da quando è armato (2026-06-23): il conto è flat *by design*, non per un errore.
- **NON nel book live:** XS01, VRP01, GTAA01 (research/paper/STAT-MODE).
## 3. Il portafoglio RESEARCH (5 sleeve) — `src/portfolio/sleeves.active_sleeves`
| Sleeve | Peso | Meccanismo | Dati | Stato |
|---|---|---|---|---|
| **TP01** | 33% | TSMOM difensivo trend BTC/ETH 1d, long-flat, vol-target 20% | 2019→ | **Deploy pieno** (nel book live) |
| **SKH01** | 20% | Dual-TF regime+breakout BTC/ETH, L/S, exit %-asimmetrici | 2019→ | Research → nel book live |
| **GTAA01** | 20% | Trend difensivo equity 6-ETF (IB), ~30 anni storia | 1996→ | Paper (paper_combo) |
| **VRP01** | 12% | Options short-vol (put credit spread + gate IV-rank) | 2021→ | LEAD modellato (STAT-MODE) |
| **XS01** | 15% | Cross-sectional momentum 19 alt Hyperliquid | 2024→ | STAT-MODE (serve ~20k) |
- **Combinato (research, ancore canoniche):** FULL Sharpe **2.24**, HOLD-OUT **2.46**, DD full **6.2%**.
- **⚠️ Stima DE-LUCKATA onesta** (dopo gli anchor-audit, vedi §5): **HOLD ~1.9-2.1, FULL ~2.0-2.2,
DD ~6%**. Il 2.46 è un massimo di configurazioni d'ancora, non la stima centrale.
- Sleeve a date d'inizio diverse → outer-join con pesi rinormalizzati (`combine_outer`).
- Report: `scripts/portfolio/run_portfolio.py`. Il book live (TP01+SKH01 75/25) è un sottoinsieme.
## 4. Paper trader / forward-monitor attivi (nessun soldo reale)
- **paper_trend** — TP01 1d, capitale nominale 2000, forward-only.
- **paper_combo** — book 5-sleeve completo (incl. GTAA/VRP/XS) dal 2026-06-22.
- **paper_statarb** — STATARB-RESID (ETH−β·BTC residual momentum, W=45/sgn=+1 congelati), doppio
libro MODELED/REAL-$600. LEAD eseguibile a $600 sotto soglia solo sull'edge (DSR 0.929).
- **paper_prevday** — FOLLOW prior-day levels (3 trade registrati); confermato indipendentemente da
più ondate (FOLLOW > FADE ogni anno 2019-26).
---
## 5. Finding strutturale del blocco 1-3 luglio: ANCHOR TIMING-LUCK (audit COMPLETO 4/4)
Le strategie a ribilanciamento/griglia ancorata hanno un'ancora "canonica" che è spesso il
**migliore** di molte configurazioni equivalenti (giorno/ora/offset) — un multiple-testing che il
deflated-Sharpe NON conta. Audit eseguito su tutti e 4 gli sleeve ancorati:
| Sleeve | Spazio d'ancora | Firma | Conseguenza |
|---|---|---|---|
| **TP01** | 24 ore (barra daily) | canonica = migliore (P=0.86) | hold-out 0.31 non risolve l'edge di ritorno; regge solo il taglio DD |
| **XS01** | 10 fasi (ciclo 10g) | canonica al 15° pctl di DD | numeri headline conservativi sul DD, non sull'hold-out |
| **SKH01** | 23 offset (griglia 230/690m) | canonica = 93-98° pctl (peggiore firma) | gate DD<30% fallisce in 15/23 offset; ~+0.5 HOLD di fortuna sul book |
| **VRP01** | 7 giorni (ciclo settimanale) | **canonica = PEGGIORE** (7° pctl) | **numeri CONSERVATIVI**, non gonfiati — unico sleeve senza luck |
**Regola codificata:** i numeri hold-out di strategie ancorate si citano **con banda d'ancora**.
Candidato gate futuro: `anchor_luck_band()` in altlib. Diari: `2026-07-02-timing-crt-wave.md`,
`2026-07-02-anchor-audit-xs01-skh01.md`, `2026-07-03-vrp-improve-dd.md`.
---
## 6. Cosa è PROVATO e MORTO (per non ri-testarlo)
- **Soffitto BTC/ETH-direzionale ~1.3** confermato da ogni ondata; superato solo dal cross-sectional
(XS01) e dalla diversificazione multi-sleeve.
- **Sweep 104 famiglie** (2026-06-20): 1 sola sopravvissuta, comunque non deployabile.
- **Opzioni long-vol** (gamma scalping): specchio del VRP, perde ogni anno/variante/frequenza.
- **Cash-and-carry (CC01):** premio reale ma Sharpe artefatto (manca il 2022, procyclico) → STAT-MODE.
- **Timing/clock alternativi** (event-clock, expiry calendar, clock lenti, regime-speed): 0 edge.
- **CRT "Candle Range Theory"** (3/3 FAIL): DSR 0.000, expectancy negativa anche a fee zero, il
ritest è informazione negativa; sui livelli prior-day FOLLOW > FADE.
- **Elliott (3/3 FAIL):** range-cycle = rumore; Fibonacci = effetto posizione non numeri magici;
canale = Donchian travestito.
- **Albimarini double-diagonal (2/2 FAIL):** non domina il condor, fee-negativa su Deribit, track
record consistente con zero skill (P=20-45%), rovina nei replay con code reali.
- **VRP01 miglioramenti (0/7 filoni):** struttura, overlay-DD, gate nuovi (4° fallimento), sizing,
gate SPX (confound di modello) — **VRP01 non migliorabile; la protezione DD si compra con la size.**
## 7. Regole/gate anti-illusione codificati (l'asset metodologico)
- **Certificazione dati** obbligatoria (solo Deribit mainnet, BTC/ETH; alt esclusi).
- **`marginal_vs_tp01` / `study_marginal`** (earns_slot) — Sharpe MARGINALE, non assoluto.
- **`study_family_honest` / `select_cell_insample` / `deflated_sharpe≥0.95`** — anti selection-on-holdout.
- **`day_boundary_robust`** — effetti calendario che si invertono spostando il confine = artefatto.
- **`eval_weights_smallcap`** — Sharpe haircut reale a capitale piccolo (sub-min-order = finzione).
- **`weights_tilt_null`** — ogni cambio pesi vs null dei tilt casuali cap-respecting.
- **Banda d'ancora** (nuova, luglio) — per ogni costrutto ancorato.
- **Candidati in coda:** `anchor_luck_band` (multiple-testing d'ancora); `implausible_sharpe`
(0-perdite / Sharpe implausibile — 3 occorrenze: CC01, ALB-A, griglia struttura VRP).
- **Lezioni pandas:** mai `DatetimeIndex.view("int64")` su tz-aware; `resample("7D", origin=)`
ignora origin (usare `"168h"`); un gate che si correla con un errore di modello è indistinguibile
da alpha finché non correggi il modello.
---
## 8. Onestà sui numeri e sul target
- **€50/giorno da €1.000-2.000 NON è raggiungibile** in 1-2 anni: serve ~130k di capitale o un DD da
rovina. La leva non è la scorciatoia (5x raddoppia il DD). La via è target-vol + capitale + tempo.
- Aspettativa onesta col CAGR de-luckato del book (10-15%): **~€0.6-0.8/giorno a 2k, ~€1.4-2/giorno
a 5k**. Il salto di capitale cambia *cosa è eseguibile*, non l'ordine di grandezza del ritorno.
- Il valore reale di TP01/del book è il **taglio del drawdown ~6× vs buy&hold**, non l'alpha.
## 9. Capitale in arrivo 2-5k — cosa cambia (audit r0702_capital_scaling)
- **Unico vincolo binding: il cap `max_notional_per_asset_usd=300`.** A 5k il book live girerebbe al
~49% del target. **Azione pendente sul deposito: alzare il cap a equity/2** ($1000/$1750/$2500 a
2k/3.5k/5k). `min_order_usd=5` da lasciare.
- Tranching K=2: matematicamente regge a 5k ma serve feed intraday fuori path certificato → non cablare.
- Opzioni ETH eseguibili da ~2.6k (spread), ma **la regola "niente short-vol da modello in deploy"
non decade col capitale**. XS01 resta fuori fino a ~20k. CC01 fuori per struttura.
- ⚠️ Disambiguazione unità: il "12%" come peso book (~0.014 Kelly) ≠ "12%" come margine/equity
(~0.27 Kelly) — **fattore 19x**.
## 10. Aperto / prossimi passi
1. **Al deposito 2-5k:** alzare il cap $/asset (proposta pronta, `config/live.json` non ancora toccato).
2. **Forward-monitor da maturare:** paper_statarb (edge sotto soglia DSR), paper_prevday (FOLLOW),
paper_combo (book completo). Se la finestra forward conferma STATARB-RESID → deployabile a 2 gambe.
3. **Gate da codificare:** `anchor_luck_band`, `implausible_sharpe`.
4. **Rivisite temporizzate:** term-structure DVOL (logger dal 2026-06-26, rivalutare a 6-12 mesi);
breadth/internals HL (1-2 anni di storia nativa); tranching a ≥5-10k; VRP stress-f su un crash reale.
5. **Ricerca strategie nuove:** il soffitto direzionale ~1.3 è saturo; i margini restano in meccanismi
ORTOGONALI (cross-sectional, relative-value, options gated) e nella diversificazione, non in nuovi
segnali direzionali BTC/ETH.
---
## 11. Stato tecnico
- **Versione:** 2.0.0 (semver in `VERSION`). **Test:** 168 verdi (28 file). **Diari:** 76.
- **Ultimi commit:** `26f8d27` (migliora+proteggi VRP01), `76120b5` (video-claims + capital-scaling),
`a74cc69` (anchor-audit XS01/SKH01), `e6657fc` (GTAA01 5° sleeve).
- **Working tree pulito, tutto pushato.** Book live sano e invariato da tutta la ricerca (research
isolata: nessun agente tocca src/config/live).
+167
View File
@@ -0,0 +1,167 @@
# 2026-07-03 — Ondata "migliora e proteggi VRP01 dai DD" (7 filoni + verifica a 2 lenti + scettico incrociato)
**Contesto.** Dopo la chiusura del dossier Albimarini (3 backtest indipendenti convergenti: premio
piccolo e reale, code non campionate, numeri del corso spiegabili al 100% dalla struttura del
payoff), goal esplicito: **migliorare la strategia short-vol** — la famiglia Albimarini → il nostro
**VRP01**, l'unica forma sopravvissuta agli audit — **e proteggerla dai drawdown**, con
orchestrazione a decine di agenti. Workflow deterministico: 7 filoni di ricerca in parallelo, 2
refuter avversariali (lente selection-bias + lente de-levering) su ogni miglioramento proposto,
scettico incrociato finale sui sopravvissuti. **26 agenti, 0 errori.**
**Scripts:** `scripts/research/r0703_vrpimp_{structgrid,ddoverlay,sizing,newgates,anchor,spxgate,stresslab}.py`.
Nessun file di produzione toccato, nessun commit dagli agenti. Motore riusato: `r0702_alb_structure.py`
(DVOL, riproduce VRP01 bit-exact: baseline bridge max|diff|=0.00e+00 su 266 settimane).
---
## Verdetto in una riga
**VRP01 non è migliorabile oltre lo status quo, e la protezione DD si compra SOLO con la size.**
Zero nuovi sleeve, zero overlay che reggono, zero gate nuovi, zero cambio di sizing. I due unici
"sopravvissuti" alla verifica **non propongono alcun cambiamento** (una conferma dello status quo +
una lente di misura). Il candidato più luccicante dell'ondata — un gate term-structure VIX su SPX
con ΔSharpe +0.90 e DSR 0.992 — è stato smontato dallo scettico come **confound di modello al
100%**. Deliverable reale = **audit anchor-luck di VRP01 CHIUSO** (ultimo sleeve ancorato): la fase
canonica è all'estremo **conservativo** della banda, quindi i numeri di ammissione reggono e da ora
si citano con banda.
---
## I 7 filoni
### 1. Griglia di struttura (288 celle) — NESSUNA batte VRP01
6 strutture (vertical put/call, condor, 3 diagonali) × distanza {1,1.5,2,2.5}σ × ali {0.5,1,2}σ ×
tenor {3,5,7,10}g, gate IV-rank canonico sempre attivo. La cella scelta col **solo in-sample**
(DIAG-PUT z=1.0 3g, ShIS 2.28) crolla in hold-out a **+0.19** vs 0.86 del bridge stesso-motore;
DSR 0.000/0.004 su 288 trial; multi-cut negativo a 3-4 cut su 4; banda d'ancora che non tiene
nemmeno il segno (ShH [0.21,+0.64]). **Metà griglia (150/288) è il pattern "0-perdite = Sharpe
implausibile"** (celle z≥2 lunghe, 0 perdite su ~97 trade, ShH fasulli 4-6.5) — **terza occorrenza
dopo CC01 e ALB-A**. Quarta conferma indipendente: nel VRP l'alpha sta nel gate di regime + nella
zona ~δ-0.28 dove la coda è campionata, non nella geometria.
### 2. Overlay di protezione DD (14 celle) — 4/4 REFUTED (2 lenti ciascuno)
(a) exit intra-settimana su spike DVOL, (b) stop-loss MTM, (c) ala di coda comprata (broken-wing),
(d) cooldown post-perdita. **Nessuno batte il null del de-levering** a pari maxDD su tutta la banda
f; nessuno passa multi-cut (max 1/4) né DSR (0.70-0.88, tutti <0.95). Esempio decisivo: SL MTM 3x fa
DD 7.9%/worst 5.7%, ma VRP01 × 0.66 (semplice riduzione di size) fa lo **stesso DD a Sharpe
invariato e worst-week migliore (4.9%)**. Meccanismo confermato: i trigger di spike scattano solo
2-3 volte in 5 anni **perché il gate IV-rank/crash-skip evita già gli ingressi vicino alle
esplosioni di vol** — la protezione crash vive nel gate d'ingresso, non serve un overlay a valle.
Coerente con TP01×DVOL (2026-06-26): "per meno DD la leva è la size, non un overlay".
### 3. Sizing anti-rovina — CONFERMA (12% ≈ quarter-Kelly), 1 candidato REFUTED
Il sizing non crea alpha (Sharpe del flusso invariante ~0.95 a ogni frazione). Frontiera onesta
CAGR-DD-P(rovina) mappata su 92 trade gated ETH 2021-26 (pooled banda-f + coda sintetica full-loss):
Kelly onesto q*=44% → il **12% del book = 0.27 Kelly, già in zona quarter-Kelly anti-rovina**
(P(rovina-50%|5y) 0.0-0.1%, P(DD>30%) 9-18%, CAGR med 13.5-17% a 2k/5k). Salire al 25% → P(DD>30%)
> 92%; Albimarini 1→4 → P(rovina) 53-55%. **Nessun cambio raccomandato.** Il candidato anti-streak
(N=2, size 12%→3% dopo 2 vittorie, l'opposto di Albimarini) era il più luccicante mai visto sullo
sleeve (FULL CAGR +19.4%/DD 6.3%/Sh 2.08, random-null 0.996, DSR 0.999) ma **auto-refutato come
artefatto di selezione**: plateau assente (solo N=2 vince, N=3/5 collassano), P(loss|streak) non
monotona, delever-null perde in 2/7 ancore — tutto l'effetto sono ~6 perdite su 15 trade a
streak==2 (binomtest p=0.033, CI contiene la base). Istruttivo: mostra come un DSR 0.999 possa
convivere con l'assenza di meccanismo.
### 4. Gate nuovi — 4° FALLIMENTO su 4 (barra alta)
(a) term-structure DVOL **non testabile oggi** (storia vol_term = 7 giorni, logger forward dal
2026-06-26 → rivalutare a 6-12 mesi); (b) vol-of-vol, (c) RV-acceleration, (d) combinazioni-AND. Il
candidato IS-best (vol-of-vol pctl>0.80) passa DSR 0.960 e il de-levering all'ancora di default ma
la **banda d'ancora lo smaschera** (mediana uplift FULL 0.07 su 7 ancore, uplift concentrato in UNA
finestra 2021-22 di 5 settimane, hold-out uplift 0.00). Bonus strutturale: i veti RV-acceleration
bloccano settimane **profittevoli** (+0.93/+1.25% vs +0.6% tenute) — dopo il gate IV-rank, la vol
che accelera è dove il premio venduto è più ricco. Conferma il verdetto 2026-07-01: l'alpha è tutto
nel binario IV-rank>0.30.
### 5. Audit anchor-luck VRP01 — CHIUSO: primo sleeve SENZA firma di luck
VRP01 è l'ultimo sleeve ancorato dopo TP01/XS01/SKH01. Ciclo settimanale → 7 ancore (giorno di
apertura). Replica bit-exact della sleeve (max|diff|=0.0). Le 7 fasi con parametri identici:
| metrica | canonica (fase-0) | mediana 7 fasi | banda | pctl canonica |
|---|---|---|---|---|
| Sh FULL | 1.09 | 1.32 | [1.09, 1.83] | **7° (peggiore)** |
| Sh HOLD | 0.59 | 0.59 | [0.03, 1.11] | 50° (mediana) |
| maxDD | 11.8% | 7.2% | [5.7, 11.8%] | **93° (peggiore)** |
**Firma OPPOSTA a TP01/XS01/SKH01**: lo spike bootstrap è NEGATIVO (g0 HOLD 0.06, FULL 0.21,
P(g0≤0) 0.54/0.74) → niente da de-luckare. La fase canonica ha beccato le settimane crash 2022
**peggio** di ogni altra (unico anno-fase negativo, 5.8%). **I numeri di ammissione FULL 1.10 /
HOLD 0.60 / DD 12% sono quindi CONSERVATIVI, non gonfiati** — il timore di "protezione fittizia" è
refutato: il DD 12% è il caso peggiore della banda, non quello fortunato. Impatto della fase sul
book 5-sleeve ≤ 0.04 Sh (banda ShFULL 2.23-2.27, ShHOLD 2.35-2.48, DD 6.2-6.3%). **Con questo
l'audit anchor-luck è completo su tutti gli sleeve ancorati (4/4).**
### 6. Gate di regime sulla diagonale SPX (l'esperimento mancante) — REFUTED, con confound istruttivo
L'esperimento che mancava ai 3 backtest Albimarini: il gate di regime sulla diagonale SPX (VIX +
VXV da FRED, motore BS sintetico con skew log-lineare). **Domanda secca: il gate IV-rank ribalta gli
anni di coda su SPX come su crypto? NO.** Il gate VIX-rank canonico *abbassa* lo Sharpe (1.36→1.19),
non ribalta nessun anno di coda, peggiora il 2018, muore sul de-levering (ΔSh 0.17). Meccanismo:
su SPX il VRP è già positivo l'**84% dei giorni** (vs ~58% delle settimane crypto) → il filtro di
rank non ha lavoro discriminante; su equity IV-rank alto = crisi, non vol ricca.
Il candidato **term-structure VIX/VXV<1 (contango)** sembrava reale — Sh 1.18→2.08, DD 3.5→1.3%,
ΔSh **+0.90** a pari DD, multicut 3/3, flippa il 2020, DSR 0.992, plateau su c∈[0.93,1.05], jackknife
robusto — **e passa la lente selection-bias pulito**. Ma la lente de-levering lo affonda:
**l'intero uplift è un confound di modello, quantificato al 100%.** La variabile del gate (VIX/VXV>1)
coincide 1:1 con la variabile dell'errore di pricing (tenor 6g prezzato a VIX-30g). Il refuter ha
riprezzato con σ(6g)=VIX·(VIX/VXV)^α term-structure-consistent (α=1.42 = estrapolazione log-lineare
zero-parametri della pendenza osservata 30g→93g) → l'edge sparisce. **Lezione: un gate che si
correla con un errore di modello è indistinguibile da alpha finché non correggi il modello** — vale
per ogni futuro test su strutture prezzate BS-flat.
### 7. Stress lab di coda — fisica dello strumento, nessun cambio
La protezione di coda del VRP01 viene per ~metà dall'**ala far-OTM** (nel replay COVID taglia ~90%
della perdita naked) e ~metà dal **gate canonico** (sulle 10 peggiori finestre 14g taglia la perdita
cumulata del 44-71% saltando i re-entry a IV-rank>0.90). L'ala T+1 "Albimarini" è assicurazione solo
contro i gap **medi** (15/20%, dove atterra ATM con un giorno di time value: +150bps) e **NON**
contro i gap profondi (k(30%)=0.98 → il de-levering la batte), con valore interamente dipendente
dal vol-spike (banda f/mult da 324 a +263bps). Worst-case onesto a sizing 12%: piccolo in
convenzione book (−€12/sett a 2k, −€31 a 5k alla cella 30%) ma **è il margine intero** se il 12%
fosse deployato fisicamente come margine (−€164..227).
---
## Scettico incrociato — verdetto e disambiguazione critica
I 2 sopravvissuti (sizing-conferma, anchor-ensemble) usano leve diverse (posizione sulla frontiera
vs varianza della stima), ma lo scettico ha trovato **tre sovrapposizioni che i refuter singoli non
potevano vedere**:
1. **Stessa dipendenza dal modello f** — entrambi flippano segno allo stesso punto (f=0.6-0.8 →
negativo). Due sopravvissuti = **un solo grado di libertà di rischio-modello** (il caveat "premio
MODELLATO su DVOL ATM" resta il collo di bottiglia dell'intera famiglia).
2. **⚠️ CONFLITTO DI UNITÀ sul "12%"** (il punto più pericoloso per la narrativa): il **12% di PESO
del book** (convenzione pnl/Ks di `sleeves.py`) = ~**0.6% margine/equity ≈ 0.014 Kelly**, mentre
il "FISSO 12%" del filone sizing = **12% margine/equity ≈ 0.27 Kelly****fattore 19x**. Entrambe
corrette internamente, ma non vanno confuse: worst-week 12.2% del conto (convenzione margine) vs
0.64% (convenzione peso book).
3. **L'ensemble-7-fasi è ridondante con il tranching TP01** (matematica di diversificazione: corr fra
fasi ρ=0.355, boost teorico ×1.50 vs osservato ×1.53, residuo alpha ≈ 0) → **non promuovere a LEAD
autonomo**; la coda strutturale è invariata (worst = 7 tranche a full-loss simultaneo), il DD 4.7%
è campionario, non un cap.
**Effetto congiunto sul book 5-sleeve: ZERO** (entrambi propongono nessun cambio; controfattuale
|ΔSh| ≤ 0.04). Il book live Deribit (TP01+SKH01) non contiene VRP01 → impatto operativo nullo.
---
## Cosa entra nella narrativa (una sola voce, status = misura research)
- **Audit anchor-luck VRP01 CHIUSO** → i numeri di ammissione reggono e si citano con banda
(ShFULL [1.09,1.83], ShHOLD [0.03,1.11], DD [5.7,11.8%]); l'edge OOS resta f-dipendente.
Con questo l'audit anchor è completo su 4/4 sleeve ancorati.
- **Sizing (conferma, con disambiguazione unità obbligatoria):** 12% deploy ≈ 0.27 Kelly onesto,
anti-rovina; NON confondere col 12% di peso book (0.014 Kelly, 19x).
- **VRP01 canonico resta lo sleeve giusto, INVARIATO** — non migliorabile per struttura, gate,
overlay o sizing; la protezione DD si compra con la size.
## Regole/candidati rafforzati
- **`implausible_sharpe` gate in altlib**: 3ª occorrenza del pattern "0-perdite = Sharpe
implausibile" (griglia struttura, dopo CC01 e ALB-A) → priorità alzata.
- **Nuova regola metodologica**: un gate che si correla con un errore di modello (term-structure vs
BS-flat) è indistinguibile da alpha finché non si corregge il modello — riprezzare
term-structure-consistent prima di credere a qualsiasi gate vol su strutture BS-flat.
- **Conferma (4ª): l'alpha del VRP è il gate IV-rank binario**, non struttura/sizing/overlay/gate
aggiuntivi.
**Stato:** book live INVARIATO, nessun nuovo sleeve, nessun forward-monitor. Test suite verde. 7
script committati.
@@ -0,0 +1,109 @@
# 2026-07-07 — Video-claim "CRT top-down multi-TF, 74% win rate": SCARTATO (il 74% è un knob, non un edge)
**Richiesta utente:** analizzare e testare una strategia da video, metodo ICT/SMC top-down
multi-timeframe con claim **74% win rate**:
1. **H1** — setup CRT: candela di displacement forte, poi candela che prende liquidità (spike oltre
il range di C1) ma richiude dentro → falso breakout → fade/reversal.
2. **M15** — struttura: swing (U a 3 candele) + imbalance che diventa inverse-imbalance (FVG mitigato).
3. **M5** — conferma: displacement direzionale + zona di protezione (order block / imbalance).
4. **M1** — entry: attende la correzione, entra con SL dietro la zona di protezione.
Uscita: **TP1 a fine zona CRT (RR ~1.52), chiude 7080% lì → resto a break-even → runner 2030%**
verso la "liquidità successiva" (previous daily high/low). Due esempi mostrati (gold, nasdaq), entrambi
vincenti. Metà finale del video = vendita academy → lead magnet.
La valutazione critica dell'utente ("occhio Milito") aveva già isolato le red flag giuste (74% non
dimostrato, cherry-picking di 2 esempi, concetti discrezionali non falsificabili, RR basso + WR alto =
fragile, funnel commerciale). Questo diario **meccanizza e falsifica** la parte testabile.
## Inventario preventivo (non rifare lavoro)
Il setup H1 CRT è **già stato meccanizzato e scartato 3 volte** nell'onda 2026-07-02:
- `r0702_crt_base` (864 trial, 1h/4h/12h/1d): **DSR 0.000**; short "smart-money" negativo perfino IS.
- `r0702_crt_mtf` (4h→15m, 1h→5m, ~10k trade): **expectancy netta negativa OVUNQUE**; refutazione
strutturale = **"il ritest è informazione negativa"** (pattern CON ritest 40bps, SENZA +52bps).
- `r0702_crt_context` (FVG/sessioni/livelli): FVG semmai peggiora; **FADE < FOLLOW ogni anno 2019-26**.
**Angolo NUOVO non coperto** = la **gestione d'uscita (parziale+BE+runner)** e il **claim 74% WR**.
È lì che ho concentrato il test: `scripts/research/r0707_crt_topdown.py` (non tocca src/config/live;
nessun file scritto). Riusa l'harness certificato (dati/atr/sharpe/DSR di `altlib`).
## Disegno
- Detection CRT C1-C2 su **H1** (causale, nota alla chiusura di C2). Direzione = fade dello sweep.
- Entry sul TF basso (**5m/15m**, proxy di M5/M1 — ⚠️ **M1 non è nel feed certificato**): ritest della
zona violata + close-back attraverso il livello ("displacement di conferma"), **SL = estremo dello
swing basso = zona di protezione**.
- Tre schemi d'uscita sugli **stessi ingressi**: `fix1.5` (full, TP 1.5R), `fix2.0` (full, TP 2.0R),
`managed` (75% a 1.5R → resto 25% a BE, runner target = prev-daily high/low o estremo opposto C1).
- Gate progetto: hold-out 2025-01-01, griglia (k, s, d, tf, scheme) con **selezione cella solo
in-sample** + **DSR su tutti i trial**, **fee sweep** 0/0.10/0.20% RT, executability $600.
- Metrica invariante = **expectancy in R netto fee** (non il win-rate).
## Esito — il 74% è un artefatto della distanza del target, non un edge
**1) Win-rate reale (fade, tutti gli schemi, pooled BTC+ETH):**
| schema | WR mediana | expectancy R (netto 10bps) |
|---|---|---|
| fix1.5 | **35.8%** | 2.38 |
| fix2.0 | 31.3% | 2.34 |
| managed | **35.8%** | 2.17 |
Il WR a RR 1.5 è **~35%**, cioè **SOTTO** il null gambler's-ruin di un random walk senza edge
(P(+1.5R prima di 1R) = 1/(1+1.5) = **40%**). Il setup tocca 1.5R **meno spesso di una moneta**
conferma indipendente che *il ritest è informazione negativa*. Lo schema `managed` **non gonfia** il
WR sopra `fix1.5` (per costruzione: "vinci" solo se raggiungi il parziale a 1.5R, che è la stessa
condizione di `fix1.5`). **In nessuna cella si avvicina al 74%.**
**2) Il win-rate È un knob — sweep del target parziale `rr1` (managed, 5m, cella tipica):**
| rr1 | WR reale | null 1/(1+rr1) | expR (fee 10bps) | expR (fee 0) |
|------|----------|----------------|------------------|--------------|
| 0.50 | 51.4% | 66.7% | **2.54** | +0.11 |
| 0.75 | 46.9% | 57.1% | 2.51 | +0.14 |
| 1.00 | 43.2% | 50.0% | 2.47 | +0.17 |
| 1.50 | 36.3% | 40.0% | 2.45 | +0.19 |
| 2.00 | 31.8% | 33.3% | 2.42 | +0.23 |
Avvicinando il target il WR sale (esattamente come previsto dalla formula gambler's-ruin): **un "74%"
si fabbrica scegliendo un parziale vicino** (~0.35R), NON perché il metodo indovina la direzione. Ma
l'**expectancy R è costante e negativa a ogni rr1**: il WR alto non porta soldi. NB anche a WR massimo
il setup resta *sotto* il null teorico ad ogni rr1 → è pure peggio di un random walk nel raggiungere
target vicini.
**3) Gate statistici (cella scelta in-sample = 15m, k1.5, s0.1, d0.15, fix2.0):**
- **DSR = 0.000** su 48 trial (null max-Sharpe atteso 4.35). FAIL.
- **Fee sweep:** a **0 bps** expR = 0.10 e Sharpe book 0.63 → **non è morte-per-fee: l'edge lordo
non esiste** (il residuo lordo marginalmente positivo su 5m è la beta di trend dei time-exit, la
stessa autopsia del CRT base). A 10bps expR 1.26; a 20bps 2.43. Stop stretti (0.130.24%) →
la fee 0.10% pesa 0.752.6 R per trade → qualunque micro-edge lordo è polverizzato.
- **Hold-out 2025-26:** WR 32%, expR 1.56 (peggio dell'IS). Nessuna reggenza fuori campione.
**4) Executability $600:** SL sul TF basso = 0.13% (5m) / 0.24% (15m). Lo schema parziale+BE+runner
richiede **34 ordini per trade**, alcuni **sotto il min-order $5** a nozionale $1200 → non eseguibile
pulito al capitale reale.
## Verdetto
**SCARTATO.** Il claim "74% win rate" è **coerente con ZERO edge**: è la scelta di un parziale vicino
(gambler's ruin), non capacità direzionale. Smontato lo schema d'uscita, resta il setup H1 CRT che
questo progetto ha già triplo-refutato (DSR 0.000, ritest = informazione negativa, fade < follow).
Sul feed certificato BTC/ETH il metodo ha **win-rate reale ~3037% e expectancy R negativa a ogni
schema, fee, finestra e asset**; lordo di fee non c'è edge; a $600 non è nemmeno eseguibile pulito.
La parte *utile* del video è il framework di lettura (CRT + imbalance + parziali), non il numero — come
aveva già concluso la valutazione dell'utente. Da trattare come lettura del mercato, non come sistema.
## Lezione codificabile (candidata)
**Il win-rate di uno schema parziale+BE non è un parametro di merito: è ~P(tocca il primo target prima
dello stop) = 1/(1+rr1) per un processo senza drift.** Ogni claim "WR X%" da schema SMC va convertito
in **expectancy R netto fee** prima di crederci; il WR alto si compra con un target vicino a costo di
un'expectancy identica (o peggiore). Prossimo giro di gate: un helper `winrate_is_a_knob()` che, dato
un book a schema parziale, riporta expectancy-R vs WR al variare del target (rende esplicito l'artefatto).
## File
- `scripts/research/r0707_crt_topdown.py` — il test (griglia + 74%-check + knob-sweep + DSR + fee + exec).
- Prior: `r0702_crt_{base,mtf,context}.py`, diario `2026-07-02-timing-crt-wave.md`.
- Nessuna modifica a src/, config/, scripts/live/, tests/. Book live e pesi INVARIATI.
@@ -0,0 +1,108 @@
# 2026-07-09 — Incident infra: "BOOK LIVE conto offline" = cert Traefik di default (non un problema del conto)
**Tipo:** incident operativo (infra VPS), non ricerca. Nessun edge, nessun cambio a strategie/pesi/config
di trading. Documentato qui perché ha **bloccato la lettura del conto del book live** e ha prodotto
l'alert Telegram `⚠️ BOOK LIVE — conto offline`.
## Sintomo
Alert dal `cron_book` orario (`scripts/live/book_execute.py --execute`):
```
⚠️ BOOK LIVE — conto offline
nota: salto l'esecuzione, non opero a cieco
```
Nel log (`logs/cron_book.log`) le run recenti mostravano `conto non leggibile (offline) -> stop, non
eseguo a cieco`. 10 run offline su 382 totali → **regressione recente**, non uno stato storico.
## Diagnosi (catena completa)
Il book legge il conto Deribit mainnet in sola lettura via **Cerbero MCP** (`DeribitRead`,
`src/live/deribit.py``https://cerbero-mcp.tielogic.xyz`). `book_report` marca `online=False` quando
`DeribitRead.mark_price(BTC)` lancia. Riproduzione diretta:
```
mark_price BTC: FAIL -> SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] self-signed certificate
```
Il proxy presentava il **cert self-signed di default di Traefik** (`CN = TRAEFIK DEFAULT CERT`,
`notBefore Jul 9 19:55 2026`) al posto del vero Let's Encrypt. `curl -k` → HTTP 401 (backend
`cerbero-mcp` healthy, routing OK): **solo la presentazione del cert TLS era rotta**. `requests`
verifica il cert → fallisce → `online=False` → il book salta l'esecuzione (comportamento di sicurezza
**corretto**: non opera a cieco).
**Causa a monte** (log di avvio Traefik, 11:37:16Z, container `traefik-traefik-1`):
```
ERR The ACME resolve is skipped from the resolvers list
error="unable to get ACME account: permissions 660 for /acme.json are too open, please use 600"
resolver=mytlschallenge
→ (a cascata) Router uses a nonexistent certificate resolver certificateResolver=mytlschallenge
routerName=cerbero-mcp@docker [+ ~14 altri router: git, vault, portfolio, budget, cerbero-bite, ...]
```
Sequenza:
1. Immagine `traefik:latest` + **Watchtower** (`com.centurylinklabs.watchtower.enable=true`) →
auto-upgrade a **Traefik 3.7.7** con restart alle 11:37 di oggi.
2. Traefik 3.x **rifiuta** `acme.json` con permessi più larghi di `600`; il file era `660`
(`-rw-rw---- root:adriano`) → **resolver `mytlschallenge` scartato**.
3. Tutti i ~15 router che lo referenziano → "nonexistent certificate resolver" → Traefik serve il
**cert di default self-signed** a ogni host HTTPS del VPS (non solo cerbero-mcp).
4. I cert veri erano **già dentro `acme.json`** (14 domini, incl. `cerbero-mcp.tielogic.xyz`) → nessuna
ri-emissione necessaria, **zero rischio rate-limit** Let's Encrypt.
## Impatto
- **VPS-wide:** ogni servizio HTTPS dietro Traefik serviva un cert invalido (warning browser, fallimento
di ogni client che verifica il TLS). Non solo il trading.
- **Trading:** **nessun trade perso.** Target del book **flat** (TP01/SKH01 risk-off) + conto reale
~$598 (non finanziato al livello nominale): anche online il book avrebbe fatto HOLD. Il doppio gate
di sicurezza ha lavorato come previsto.
## Fix
**Immediato** (eseguito dall'utente):
```bash
sudo chmod 600 /opt/docker/traefik/acme.json
docker restart traefik-traefik-1
```
Il resolver ricarica i cert già presenti in `acme.json` e li ripresenta subito.
**Durevole** (pin dell'immagine, `/opt/docker/traefik/docker-compose.yml`):
```yaml
- image: "traefik" # = traefik:latest → Watchtower salta ai major (causa dell'incident)
+ image: "traefik:3.7" # Watchtower resta su 3.7.x: patch sì, salto a 3.8+ breaking no
```
Applicato con `docker compose up -d` (container ricreato su `traefik:3.7`, 20:05:05Z).
## Verifica (end-to-end, post-fix)
| Check | Risultato |
|---|---|
| `acme.json` perms | `600` |
| Cert `cerbero-mcp.tielogic.xyz` | issuer **Let's Encrypt** (fino 2026-09-27) |
| Traefik log | nessun `ACME resolve is skipped` / `too open` |
| Container image | `traefik:3.7` (running) |
| `DeribitRead.mark_price` | BTC 63.193 / ETH 1.746 |
| `book_report.online` | **True** · `eq_basis=mainnet USDC` · `real_equity=$598.06` · `pos_error=None` |
## Lezioni
- **`traefik:latest` + Watchtower = auto-upgrade non deterministico.** Un bump di major (qui il giro
di vite sui permessi di `acme.json`) diventa un'interruzione TLS di tutto il VPS senza intervento
umano. Pinnare la minor (`3.7`) rende i restart prevedibili pur ricevendo le patch.
- **Traefik 3.x pretende `acme.json` a `600`** (non solo warning: **scarta il resolver**). Se il file
è group/other-readable, tutti i router cadono sul cert di default.
- **Il gate `online` del book ha fatto il suo lavoro:** un problema *infra di lettura* non ha prodotto
ordini a cieco. L'alert "conto offline" va letto prima come possibile problema di **connettività/cert
al Cerbero MCP**, non del conto Deribit.
- **Runbook rapido** per "BOOK LIVE conto offline":
1. `python -c "from src.live.deribit import DeribitRead; DeribitRead().mark_price('BTC-PERPETUAL')"`
→ se `SSLError`/`CERTIFICATE_VERIFY_FAILED` è il cert del proxy, non il conto.
2. `openssl s_client -connect cerbero-mcp.tielogic.xyz:443 -servername cerbero-mcp.tielogic.xyz | openssl x509 -noout -issuer`
→ se `TRAEFIK DEFAULT CERT`, Traefik non serve il cert reale.
3. `docker logs traefik-traefik-1 | grep -iE "ACME resolve is skipped|too open|nonexistent"`
→ conferma resolver scartato; controlla `stat -c %a /opt/docker/traefik/acme.json` (deve essere `600`).
Nessun file di trading toccato; `config/live.json`, sleeve e pesi **invariati**.
+109
View File
@@ -0,0 +1,109 @@
"""EVALUATOR STANDARD per i segnali della ricerca multi-agente (Fase frattale, v2.0.0).
Ogni agente scrive SOLO una funzione `signal(df, asset, tf) -> np.ndarray` (posizione per barra
in [-1,1], decisa entro close[i]) in un file. Questo evaluator la valuta in modo UNIFORME e ONESTO
sull'harness research_lab, e — cruciale — esegue un GUARD ANTI-LOOK-AHEAD automatico: ricalcola il
segnale su prefissi del df e verifica che pos[i] non dipenda da barre future (leak>0 = sospetto).
uv run python scripts/analysis/eval_signal.py <signal_file.py> <BTC|ETH> <5m|15m|1h> [--holdout]
Stampa una riga "RESULT_JSON:{...}" con tutte le metriche (gli agenti riportano quei campi esatti).
"""
from __future__ import annotations
import sys
import json
import importlib.util
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from scripts.analysis.research_lab import backtest, buy_hold, mc_pvalue, load_tf, ts, _net_series, VAL_START, HOLDOUT_START
def load_signal(path):
spec = importlib.util.spec_from_file_location("usig", path)
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
if not hasattr(m, "signal"):
raise AttributeError("il file non definisce signal(df, asset, tf)")
return m.signal
def causality_guard(signal, df, asset, tf, k=12):
"""Ricalcola il segnale su prefissi df[:i+1] e confronta pos[i] col run completo.
Se differiscono -> il segnale usa dati FUTURI (look-ahead). Ritorna #violazioni (0 = pulito)."""
full = np.asarray(signal(df, asset, tf), float)
n = len(df)
if len(full) != n:
return -1
rng = np.random.default_rng(0)
idx = rng.integers(int(n * 0.6), n - 1, size=k)
bad = 0
for i in idx:
try:
p = np.asarray(signal(df.iloc[:i + 1].copy(), asset, tf), float)
except Exception:
bad += 1; continue
if len(p) != i + 1 or not np.isclose(np.nan_to_num(p[i]), np.nan_to_num(full[i]), atol=1e-6):
bad += 1
return bad
def main():
args = sys.argv[1:]
holdout = "--holdout" in args
args = [a for a in args if a != "--holdout"]
sigfile, asset, tf = args[0], args[1].upper(), args[2]
res = {"asset": asset, "tf": tf, "sigfile": sigfile}
try:
signal = load_signal(sigfile)
df = load_tf(asset, tf)
pos = np.asarray(signal(df, asset, tf), float)
res["n"] = int(len(df))
res["len_ok"] = bool(len(pos) == len(df))
if not res["len_ok"]:
res["error"] = f"len(pos)={len(pos)} != len(df)={len(df)}"
print("RESULT_JSON:" + json.dumps(res)); return
res["finite"] = bool(np.isfinite(np.nan_to_num(pos, nan=0.0)).all())
res["leak"] = int(causality_guard(signal, df, asset, tf))
full = backtest(df, pos, tf)
oos = backtest(df, pos, tf, lo=VAL_START, hi=HOLDOUT_START)
bh = buy_hold(df, tf)
_, p, _, _ = mc_pvalue(df, pos, tf, n=250)
res.update(
implemented=True,
full_sharpe=round(full.sharpe, 3), full_ret=round(full.ret, 3), full_dd=round(full.maxdd, 3),
oos_sharpe=round(oos.sharpe, 3), bh_sharpe=round(bh.sharpe, 3),
gross_sharpe=round(backtest(df, pos, tf, fee_rt=0.0).sharpe, 3),
fee02_sharpe=round(backtest(df, pos, tf, fee_rt=0.002).sharpe, 3),
turnover=round(full.ntrades, 1), exposure=round(full.exposure, 3),
null_p=round(p, 4),
beats_bh=bool(full.sharpe > bh.sharpe and oos.sharpe > 0),
)
# breadth per-anno (pre-hold-out): % anni positivi, anni rossi consecutivi
net, _, _, _ = _net_series(df, pos)
s = pd.Series(net, index=ts(df))
s = s[s.index < pd.Timestamp(HOLDOUT_START, tz="UTC")]
yr = {int(y): float((1 + g).prod() - 1) for y, g in s.groupby(s.index.year)}
vals = list(yr.values())
max_consec_red = 0; cur = 0
for v in vals:
cur = cur + 1 if v < 0 else 0
max_consec_red = max(max_consec_red, cur)
res["per_year_preho"] = {y: round(v, 3) for y, v in yr.items()}
res["pct_years_pos"] = round(sum(v > 0 for v in vals) / len(vals), 2) if vals else 0.0
res["max_consec_red_years"] = int(max_consec_red)
if holdout:
ho = backtest(df, pos, tf, lo=HOLDOUT_START)
res["holdout_sharpe"] = round(ho.sharpe, 3)
res["holdout_ret"] = round(ho.ret, 3)
res["holdout_dd"] = round(ho.maxdd, 3)
except Exception as e:
res["implemented"] = False
res["error"] = f"{type(e).__name__}: {str(e)[:200]}"
print("RESULT_JSON:" + json.dumps(res))
if __name__ == "__main__":
main()
+132
View File
@@ -0,0 +1,132 @@
"""FETCH + CERTIFY universo Hyperliquid (Cerbero MCP MAINNET) — espansione cross-sectional.
Hyperliquid (via cerbero-mcp mainnet) offre ~230 perp liquidi, ma storia nativa REALE solo dal
2024 (pre-2024 = backfill, volume 0). Qui scarico un set liquido a 1d (2024+), e CERTIFICO ogni
asset come BTC/ETH: cross-venue vs Binance (realismo) + flat-bar + VOLUME (liquidita'). Scrivo SOLO
i puliti in data/raw/hl_<sym>_1d.parquet (namespace dedicato, NON mischiato col Deribit BTC/ETH).
Disciplina: Cerbero ci ha gia' bruciato (testnet) -> niente fiducia, solo certificazione.
CORREZIONE estrazione (2026-06-20, "analisi fatte"): il floor START=2024-01-01 NON basta. Cerbero
restituisce BACKFILL SINTETICO (volume==0, ma prezzi copiati da un venue di riferimento -> matchano
Binance e NON sono flat) per il periodo PRIMA che l'asset quotasse davvero su Hyperliquid. Cosi'
asset listati a meta'/fine 2024+ passavano cross-venue+flat ed erano certificati PULITO pur essendo
in gran parte sintetici (es. AXS 83% backfill: trading reale solo da 2026-01; ALGO/SAND 37%). E' lo
stesso errore v2.0.0 (edge su un book che non c'era). Fix: (1) il VOLUME e' il rivelatore di backfill
-> si TAGLIA il run iniziale di barre a volume 0 e si tiene solo la serie NATIVA; (2) gate su storia
nativa minima (>= MIN_NATIVE_DAYS reali) -> scarta chi e' troppo corto dopo il taglio; (3) gate su
volume-0 INTERNO (gap di liquidita') oltre il taglio iniziale; (4) cross-venue/flat ricalcolati SOLO
sulle barre reali; (5) i parquet degli asset scartati vengono RIMOSSI (disco == set certificato).
uv run python scripts/analysis/fetch_hyperliquid.py
"""
from __future__ import annotations
import sys, time
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np, pandas as pd, requests, ccxt
RAW = PROJECT_ROOT / "data" / "raw"
START = "2024-01-01"; END = pd.Timestamp.now("UTC").strftime("%Y-%m-%d") # dinamico (refresh giornaliero)
MIN_NATIVE_DAYS = 365 # storia NATIVA reale minima (post-taglio backfill) per entrare nell'universo
INTERIOR_VOL0_MAX = 5.0 # % max di barre a volume 0 DOPO il taglio iniziale (gap di liquidita' interni)
# UNIVERSO ESTESO: alt liquidi noti su Hyperliquid (mappa Binance auto = SYM/USDT). Il gate di
# certificazione (cross-venue + liquidita' + flat) scarta i non-conformi. k-prefissi esclusi
# (scaling 1000x complica il cross-venue). MATIC morto escluso.
SYMS = ["BTC","ETH","SOL","BNB","XRP","DOGE","AVAX","LINK","LTC","ADA","ARB","OP","SUI","APT",
"INJ","TIA","SEI","NEAR","AAVE","ATOM","DYDX","APE","CRV","LDO","STX","GMX","SNX","BCH",
"COMP","MKR","WLD","UNI","TRX","FIL","RUNE","ENA","ORDI","JUP","WIF","PYTH","FET","AR",
"ETC","ALGO","GALA","SAND","AXS","DOT","FXS","BLUR","JTO","PENDLE","ONDO","TAO"]
BINANCE = {s: f"{s}/USDT" for s in SYMS}
def _h():
env={}
for ln in open(PROJECT_ROOT/".env.mainnet"):
ln=ln.strip()
if ln and not ln.startswith("#") and "=" in ln: k,v=ln.split("=",1); env[k]=v.strip()
return {"Authorization":f"Bearer {env['CERBERO_TOKEN']}","X-Bot-Tag":env.get('CERBERO_BOT_TAG','fetch'),"Content-Type":"application/json"}
def fetch_hl(sym, H, interval="1d"):
r=requests.post("https://cerbero-mcp.tielogic.xyz/mcp/tools/get_historical",
headers=H, json={"exchange":"hyperliquid","instrument":sym,"interval":interval,
"start_date":START,"end_date":END}, timeout=60)
c=r.json().get("candles",[])
if not c: return pd.DataFrame()
df=pd.DataFrame(c)[["timestamp","open","high","low","close","volume"]]
return df.drop_duplicates("timestamp").sort_values("timestamp").reset_index(drop=True)
def binance_daily(sym_b, start_ms, end_ms):
ex=ccxt.binance({"enableRateLimit":True})
out={}; since=start_ms
while since<=end_ms:
try: r=ex.fetch_ohlcv(sym_b,"1d",since=since,limit=500)
except Exception: break
r=[x for x in r if x[0]>=since]
if not r: break
for x in r:
if start_ms<=x[0]<=end_ms and x[4]: out[int(x[0])]=float(x[4])
nxt=int(r[-1][0])+86400000
if nxt<=since: break
since=nxt
return pd.Series(out)
def trim_backfill(df):
"""Taglia il run INIZIALE di barre a volume 0 (= backfill sintetico pre-quotazione su HL).
Ritorna (serie_nativa, n_barre_tagliate). Il volume e' il rivelatore: il backfill copia i
prezzi da un venue di riferimento (non flat, matcha Binance) ma ha volume 0."""
vol = df["volume"].to_numpy()
lead = int(np.argmax(vol > 0)) if (vol > 0).any() else len(df)
return df.iloc[lead:].reset_index(drop=True), lead
def main():
H=_h()
print("="*100); print(" FETCH + CERTIFY Hyperliquid 1d (Cerbero mainnet) — cross-venue + flat + VOLUME (no backfill)"); print("="*100)
print(f" {'sym':<6}{'reali':>6}{'bfill':>6}{'start_reale':>13}{'flat%':>7}{'vol0%':>7}{'med_bps':>9}{'>1%':>7}{'verdetto':>14}")
certified=[]
for s in SYMS:
path = RAW/f"hl_{s.lower()}_1d.parquet"
raw=fetch_hl(s,H)
if raw.empty:
print(f" {s:<6} vuoto"); path.unlink(missing_ok=True); continue
# --- CORREZIONE: taglia il backfill sintetico (volume 0 iniziale), tieni la serie nativa ---
df, n_bfill = trim_backfill(raw)
if df.empty:
print(f" {s:<6} tutto backfill (vol0) -> scarta"); path.unlink(missing_ok=True); continue
ts=pd.to_datetime(df["timestamp"],unit="ms",utc=True)
flat=((df.open==df.high)&(df.high==df.low)&(df.low==df.close)).mean()*100
vol0=(df["volume"].to_numpy()==0).mean()*100 # gap di liquidita' INTERNI (post-taglio)
# cross-venue vs Binance USDT (daily close) — SOLO sulle barre reali
ref=binance_daily(BINANCE[s], int(df["timestamp"].iloc[0]), int(df["timestamp"].iloc[-1]))
a=df.set_index("timestamp")["close"]
m=pd.concat([a.rename("a"),ref.rename("b")],axis=1,join="inner").dropna()
if len(m)>5:
bps=(m["a"]-m["b"]).abs()/m["b"]*1e4
med=bps.median(); g1=(bps>100).mean()*100
else: med=g1=float("nan")
# gate "delistato/migrato": l'ultima barra dev'essere recente (entro ~21g da END),
# altrimenti l'asset tronca l'universo cross-sectional (es. MKR fermo a 2025-09, FXS 2026-01).
recent = (pd.Timestamp(END, tz="UTC") - ts.iloc[-1]) <= pd.Timedelta("21D")
# gate storia NATIVA: dopo il taglio dev'esserci abbastanza vita reale (es. AXS quotato 2026-01 -> scarta)
native_days = (ts.iloc[-1] - ts.iloc[0]).days
enough = native_days >= MIN_NATIVE_DAYS
clean = (not np.isnan(med)) and med<60 and g1<3 and flat<5 and vol0<INTERIOR_VOL0_MAX and recent and enough
if clean: v="PULITO"
elif not enough: v=f"corto<{MIN_NATIVE_DAYS}g"
else: v="scarta"
print(f" {s:<6}{len(df):>6}{n_bfill:>6}{str(ts.iloc[0].date()):>13}{flat:>6.1f}%{vol0:>6.1f}%{med:>9.1f}{g1:>6.1f}%{v:>14}")
if clean:
df.to_parquet(path, index=False); certified.append(s)
else:
path.unlink(missing_ok=True) # disco == set certificato (niente parquet contaminati a riposo)
print(f"\n CERTIFICATI ({len(certified)}): {certified}")
print(" Scritti in data/raw/hl_<sym>_1d.parquet (namespace dedicato, SERIE NATIVA senza backfill).")
if __name__=="__main__":
main()
+121
View File
@@ -0,0 +1,121 @@
"""ANALISI OPTIONS per BTC/ETH — onesta sui dati REALI disponibili (cerbero-bite mainnet).
Dati: Old/data/options (chain per-strike + dvol + market_snapshots). Finestra ~2026-05-01→06-11
(~6 settimane, REGIME UNICO calmo). NON si può validare OOS un edge su opzioni qui; si possono
MISURARE i livelli reali (VRP, premi put, skew, liquidità) e ragionare sull'USO delle opzioni
per il book BTC/ETH certificato. cerbero-bite è ancora vivo -> la fonte continua ad accumulare.
uv run python scripts/analysis/options_analysis.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
OPT = PROJECT_ROOT / "Old" / "data" / "options"
def load(name):
return pd.read_parquet(OPT / name)
def market_snapshots_analysis():
print("=" * 90)
print(" (1) MARKET SNAPSHOTS — VRP, DVOL, funding, dealer-gamma (livelli reali)")
print("=" * 90)
ms = load("market_snapshots.parquet")
t = pd.to_datetime(ms["timestamp"], utc=True, errors="coerce")
print(f" copertura: {t.min()} -> {t.max()} ({len(ms)} righe)")
for a in ("BTC", "ETH"):
d = ms[ms["asset"] == a].dropna(subset=["iv_minus_rv"])
if len(d) == 0:
print(f" {a}: nessun dato"); continue
vrp = d["iv_minus_rv"].astype(float)
dvol = d["dvol"].astype(float)
rv = d["realized_vol_30d"].astype(float)
fund = d["funding_perp_annualized"].astype(float) if "funding_perp_annualized" in d else pd.Series([np.nan])
gam = d["dealer_net_gamma"].astype(float) if "dealer_net_gamma" in d else pd.Series([np.nan])
print(f"\n {a} (n={len(d)})")
print(f" VRP (IV-RV): media {vrp.mean():+.1f} mediana {vrp.median():+.1f} "
f">0 nel {100*(vrp>0).mean():.0f}% del tempo [IV-RV in punti di vol annua]")
print(f" DVOL: media {dvol.mean():.1f} range [{dvol.min():.1f}, {dvol.max():.1f}]")
print(f" Realized30d: media {rv.mean():.1f}")
print(f" Funding perp: media {fund.mean():+.1f}% annuo")
if gam.notna().any():
print(f" Dealer net-γ: >0 nel {100*(gam>0).mean():.0f}% del tempo (>0 = dealer long gamma = mean-rev)")
def chain_analysis(asset):
print("\n" + "=" * 90)
print(f" (2) CHAIN {asset} — premi put protettivi, skew, liquidità (livelli reali)")
print("=" * 90)
ch = load(f"{asset.lower()}_chain.parquet")
for col in ("strike", "bid", "ask", "mid", "iv", "delta", "gamma"):
if col in ch:
ch[col] = pd.to_numeric(ch[col], errors="coerce")
ch["option_type"] = ch["option_type"].astype(str)
dv = load("dvol_history.parquet")
dv = dv[dv["asset"] == asset][["timestamp", "spot"]].copy()
dv["spot"] = pd.to_numeric(dv["spot"], errors="coerce")
# timestamp -> datetime UTC nativo (sono datetime64[tz], NON ms int: to_numeric li romperebbe)
ch["t"] = pd.to_datetime(ch["timestamp"], utc=True, errors="coerce")
dv["t"] = pd.to_datetime(dv["timestamp"], utc=True, errors="coerce")
ch = ch.dropna(subset=["t"]).sort_values("t").reset_index(drop=True)
dv = dv.dropna(subset=["t", "spot"]).sort_values("t").reset_index(drop=True)
# spot causale per timestamp della chain (merge_asof nearest, tolleranza 1h)
ch = pd.merge_asof(ch, dv[["t", "spot"]], on="t", direction="nearest",
tolerance=pd.Timedelta("1h"))
ch = ch.dropna(subset=["spot", "mid", "strike"])
# days-to-expiry
exp = pd.to_datetime(ch["expiry"], utc=True, errors="coerce")
ch["dte"] = (exp - ch["t"]).dt.total_seconds() / 86_400.0
ch = ch[(ch["dte"] > 0.5) & (ch["dte"] < 90)]
ch["money"] = ch["strike"] / ch["spot"]
ch["prem_pct"] = ch["mid"] * 100 # mid è in COIN (frazione del sottostante) -> %-del-notional
# NB: iv è GIÀ in percento (35.94 = 35.94%, coerente col DVOL ~40) -> non riscalare
ch["spread_pct"] = (ch["ask"] - ch["bid"]) / ch["mid"].replace(0, np.nan) * 100
puts = ch[ch["option_type"].str.lower().str.startswith("p")]
calls = ch[ch["option_type"].str.lower().str.startswith("c")]
def band(df, mlo, mhi, dlo, dhi):
s = df[(df["money"] >= mlo) & (df["money"] <= mhi) & (df["dte"] >= dlo) & (df["dte"] <= dhi)]
return s
print(" PUT protettive — premio reale (mid/spot) e liquidità per tenor/moneyness:")
print(f" {'tenor':<10s}{'moneyness':<14s}{'premio%':>9s}{'/mese%':>9s}{'spread%':>9s}{'n':>7s}{'strike?':>9s}")
for dlo, dhi, tn in [(5, 12, "settim."), (18, 45, "mensile")]:
for mlo, mhi, ml in [(0.97, 1.03, "ATM"), (0.88, 0.93, "~10% OTM"), (0.83, 0.88, "~15% OTM")]:
s = band(puts, mlo, mhi, dlo, dhi)
if len(s) == 0:
print(f" {tn:<10s}{ml:<14s}{'':>9s}{'':>9s}{'':>9s}{0:>7d}{'NO':>9s}")
continue
prem = s["prem_pct"].median()
permonth = prem * 30.0 / s["dte"].median()
print(f" {tn:<10s}{ml:<14s}{prem:>8.2f}%{permonth:>8.2f}%{s['spread_pct'].median():>8.1f}%"
f"{len(s):>7d}{'SI':>9s}")
# skew: IV put 10% OTM vs IV call 10% OTM (stesso tenor mensile)
pv = band(puts, 0.88, 0.93, 12, 50)["iv"].median()
cv = band(calls, 1.07, 1.12, 12, 50)["iv"].median()
atmv = band(ch, 0.98, 1.02, 12, 50)["iv"].median()
if pd.notna(pv) and pd.notna(cv):
print(f" SKEW: IV put 10%OTM {pv:.0f}% vs call 10%OTM {cv:.0f}% vs ATM {atmv:.0f}%"
f" -> skew put {pv-cv:+.0f} pt vol (>0 = put care = paura del crash prezzata)")
def main():
market_snapshots_analysis()
for a in ("BTC", "ETH"):
chain_analysis(a)
print("\n" + "=" * 90)
print(" NB: finestra ~6 settimane, REGIME UNICO calmo -> livelli REALI misurabili, ma NESSUN")
print(" edge su opzioni è validabile OOS qui. Vedi commento finale.")
print("=" * 90)
if __name__ == "__main__":
main()
+158
View File
@@ -0,0 +1,158 @@
"""FASE 1 — triage dei 2 superstiti su BTC/ETH, sull'harness onesto (research_lab).
Sul feed pulito solo SH01 (shape-ML) e frammenti HONEST mostravano segnale residuo. Delle
HONEST solo DIP (dip-reversion) è testabile su BTC/ETH (TR01/ROT02 richiedono alt esclusi).
Qui ri-implemento DIP e SH01-shape-ML come SERIE DI POSIZIONE e li passo ai gate onesti
(FULL/OOS-VAL, vs buy&hold, null p-value, sweep fee, griglia). Hold-out 2025+ resta BLOCCATO.
uv run python scripts/analysis/phase1_survivors.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from src.data.downloader import load_data
from scripts.analysis.research_lab import (
backtest, buy_hold, mc_pvalue, report, VAL_START, HOLDOUT_START, FEE_RT,
)
# ----------------------------- DIP reversion (long-only) -----------------------------
def dip_signal(df, n=50, k=2.0, z_exit=0.0, max_bars=72):
"""Long-only: entra (pos=1) quando lo z-score causale del prezzo vs MA(n) <= -k (dip),
esce quando z>=z_exit o dopo max_bars. Decisione a close[i] (z[i] usa close[i]), guadagna
close[i]->close[i+1]. Niente fill su estremi di candela."""
c = df["close"].values.astype(float)
s = pd.Series(c)
ma = s.rolling(n).mean().values
sd = s.rolling(n).std().values
z = np.where(sd > 0, (c - ma) / sd, np.nan)
pos = np.zeros(len(c))
inpos = False
held = 0
for i in range(len(c)):
if not inpos:
if not np.isnan(z[i]) and z[i] <= -k:
inpos, held = True, 0
pos[i] = 1.0
else:
held += 1
if (not np.isnan(z[i]) and z[i] >= z_exit) or held >= max_bars:
inpos = False # esce al close[i]: pos[i]=0
else:
pos[i] = 1.0
return pos
# ----------------------------- SH01 shape-ML (walk-forward) -----------------------------
def _shape_features(df, W):
"""~12 feature di FORMA causali per barra, dalla finestra che termina a i (usa solo <=i)."""
o = df["open"].values.astype(float); h = df["high"].values.astype(float)
l = df["low"].values.astype(float); c = df["close"].values.astype(float)
s = pd.Series(c)
ret1 = s.pct_change()
rng = (h - l) / np.where(c > 0, c, np.nan)
body = (c - o) / np.where(h - l > 0, h - l, np.nan)
up_sh = (h - np.maximum(o, c)) / np.where(h - l > 0, h - l, np.nan)
dn_sh = (np.minimum(o, c) - l) / np.where(h - l > 0, h - l, np.nan)
# RSI(14)
d = s.diff()
gain = d.clip(lower=0).rolling(14).mean()
loss = (-d.clip(upper=0)).rolling(14).mean()
rsi = 100 - 100 / (1 + gain / loss.replace(0, np.nan))
hi_w = pd.Series(h).rolling(W).max(); lo_w = pd.Series(l).rolling(W).min()
feat = {
"mom_w": s / s.shift(W) - 1.0, # rendimento sulla finestra
"mom_half": s / s.shift(W // 2) - 1.0, # accelerazione
"vol_w": ret1.rolling(W).std(),
"rsi": rsi / 100.0,
"ma_dist": (c - s.rolling(W).mean()) / s.rolling(W).std(),
"pos_in_range": (c - lo_w) / (hi_w - lo_w).replace(0, np.nan), # dove sta il close nel range W
"range": pd.Series(rng).rolling(3).mean(),
"body": pd.Series(body).rolling(3).mean(),
"up_shadow": pd.Series(up_sh).rolling(3).mean(),
"dn_shadow": pd.Series(dn_sh).rolling(3).mean(),
"ret1": ret1,
"skew_w": ret1.rolling(W).skew(),
}
X = pd.DataFrame(feat).values
return X
def shape_ml_signal(df, W=24, H=12, th=0.55, refit=750, warmup=3000, long_short=True):
"""LogisticRegression walk-forward sulla forma. Label = segno del rendimento a H barre.
Al tempo di decisione i si allena SOLO su campioni j con esito già realizzato (j+H <= i):
strettamente causale, nessun leak. Rifit ogni `refit` barre (velocità). pos = +1 se
P(up)>th, -1 se P(up)<1-th (long_short), altrimenti 0."""
c = df["close"].values.astype(float)
n = len(c)
X = _shape_features(df, W)
fwd = np.full(n, np.nan)
fwd[:n - H] = c[H:] / c[:n - H] - 1.0
y = (fwd > 0).astype(float)
valid = ~np.isnan(X).any(axis=1)
pos = np.zeros(n)
model = scaler = None
start = max(warmup, W + H + 200)
for i in range(start, n):
if model is None or (i - start) % refit == 0:
# campioni di training: feature valide E label realizzata entro i (j+H <= i)
tr = np.where(valid & (np.arange(n) + H <= i) & (np.arange(n) >= W))[0]
tr = tr[tr < i - H]
if len(tr) >= 500 and len(np.unique(y[tr])) == 2:
scaler = StandardScaler().fit(X[tr])
model = LogisticRegression(max_iter=200, C=1.0).fit(scaler.transform(X[tr]), y[tr])
if model is not None and valid[i]:
p_up = float(model.predict_proba(scaler.transform(X[i:i + 1]))[0, 1])
pos[i] = 1.0 if p_up > th else (-1.0 if (long_short and p_up < 1 - th) else 0.0)
return pos
# ----------------------------------- run -----------------------------------
def main():
TF = "1h"
print("=" * 90)
print(f" FASE 1 — triage superstiti su BTC/ETH {TF} | netto fee 0.10% RT | hold-out {HOLDOUT_START}+ BLOCCATO")
print("=" * 90)
data = {a: load_data(a, TF) for a in ("BTC", "ETH")}
# ---------- DIP: griglia robustezza (plateau?) ----------
print("\n" + "#" * 90)
print(" DIP reversion (long-only) — griglia FULL Sharpe (plateau = robusto, picco = overfit)")
print("#" * 90)
GRID = [(n, k) for n in (30, 50, 100) for k in (1.5, 2.0, 2.5)]
for a in ("BTC", "ETH"):
df = data[a]
print(f"\n {a}: " + " ".join(
f"n{n}k{k}{backtest(df, dip_signal(df, n=n, k=k), TF).sharpe:>5.2f}" for n, k in GRID))
# report onesto sulla config centrale
for a in ("BTC", "ETH"):
report(f"DIP {a} (n50 k2.0)", data[a], dip_signal(data[a], n=50, k=2.0), TF)
# ---------- SH01 shape-ML: config record + paio di varianti ----------
print("\n" + "#" * 90)
print(" SH01 shape-ML (walk-forward LogReg) — long/short")
print("#" * 90)
for a in ("BTC", "ETH"):
df = data[a]
pos = shape_ml_signal(df, W=24, H=12, th=0.55, long_short=True)
report(f"SH-ML {a} (W24 H12 th.55 L/S)", df, pos, TF)
# variante long-only (meno fee)
pos_lo = shape_ml_signal(df, W=24, H=12, th=0.55, long_short=False)
report(f"SH-ML {a} (W24 H12 th.55 LONG-only)", df, pos_lo, TF)
print("\n" + "=" * 90)
print(" VERDETTO: un edge è REALE solo se FULL e OOS-VAL Sharpe > 0, regge il sweep fee,")
print(" e BATTE il null (p<0.05). Altrimenti = rumore, si chiude.")
print("=" * 90)
if __name__ == "__main__":
main()
+221
View File
@@ -0,0 +1,221 @@
"""FASE 2 — esplorazione larga per famiglie su BTC/ETH, harness onesto (research_lab).
Famiglie (serie di posizione, causali, netto fee, vs buy&hold + null p-value):
TSMOM (momentum) | REVERSAL | MA-cross | DONCHIAN breakout | VOL-TARGET overlay |
LEAD-LAG BTC<->ETH | HURST-gated momentum. Multi-TF dove sensato (1h + 15m).
La barra DA BATTERE è il buy&hold (Sharpe ~0.8 su BTC/ETH): una strategia di timing vale solo
se fa MEGLIO net-fee. Per ogni famiglia: scan griglia (FULL Sharpe), poi report onesto sulla
config migliore. Selezionare il best-di-griglia GONFIA -> i gate veri sono OOS-VAL + null p<0.05.
uv run python scripts/analysis/phase2_families.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from src.data.downloader import load_data
from scripts.analysis.research_lab import (
backtest, buy_hold, mc_pvalue, window_mask, ts, VAL_START, HOLDOUT_START, BARS_PER_YEAR,
)
# --------------------------------- famiglie ---------------------------------
def tsmom(df, L, mode="ls"):
c = pd.Series(df["close"].values.astype(float))
pos = np.sign(np.nan_to_num((c / c.shift(L) - 1).values))
return np.maximum(pos, 0) if mode == "lo" else pos
def reversal(df, L, mode="ls"):
c = pd.Series(df["close"].values.astype(float))
pos = -np.sign(np.nan_to_num((c / c.shift(L) - 1).values))
return np.maximum(pos, 0) if mode == "lo" else pos
def ma_cross(df, fast, slow, mode="ls"):
c = pd.Series(df["close"].values.astype(float))
ef = c.ewm(span=fast, adjust=False).mean()
es = c.ewm(span=slow, adjust=False).mean()
pos = np.sign((ef - es).values)
return np.maximum(pos, 0) if mode == "lo" else pos
def donchian(df, L, mode="ls"):
h = pd.Series(df["high"].values.astype(float)).rolling(L).max().shift(1).values
l = pd.Series(df["low"].values.astype(float)).rolling(L).min().shift(1).values
c = df["close"].values.astype(float)
pos = np.zeros(len(c)); cur = 0
for i in range(len(c)):
if not np.isnan(h[i]) and c[i] > h[i]:
cur = 1
elif not np.isnan(l[i]) and c[i] < l[i]:
cur = -1 if mode == "ls" else 0
pos[i] = cur
return pos
def vol_target(df, tf, target=0.6, L=72):
"""Overlay SEMPRE-LONG con esposizione scalata dalla vol realizzata (target vol annua)."""
c = pd.Series(df["close"].values.astype(float))
rv_ann = c.pct_change().rolling(L).std().values * np.sqrt(BARS_PER_YEAR[tf])
pos = np.clip(np.nan_to_num(target / np.where(rv_ann > 0, rv_ann, np.nan), nan=0.0), 0, 1)
return pos
def rolling_hurst(c, W=120, step=6, lags=(2, 4, 8, 16, 32)):
logc = np.log(c); n = len(c); H = np.full(n, np.nan)
lg = np.log(lags)
for i in range(W, n, step):
seg = logc[i - W:i]
tau = [np.std(seg[lag:] - seg[:-lag]) for lag in lags]
if min(tau) > 0:
H[i] = np.polyfit(lg, np.log(tau), 1)[0]
return pd.Series(H).ffill().fillna(0.5).values
def hurst_mom(df, L=48, W=120, mode="ls"):
H = rolling_hurst(df["close"].values.astype(float), W)
return np.where(H > 0.5, tsmom(df, L, mode), 0.0)
def leadlag_df(target_df, other_df, L):
"""Costruisce un df col close del TARGET e la posizione = segno del rendimento a L barre
dell'ALTRO asset (allineato per timestamp). Ritorna (df_merged, pos)."""
a = target_df[["timestamp", "open", "high", "low", "close"]]
b = other_df[["timestamp", "close"]].rename(columns={"close": "other"})
m = a.merge(b, on="timestamp", how="inner").reset_index(drop=True)
o = pd.Series(m["other"].values.astype(float))
pos = np.sign(np.nan_to_num((o / o.shift(L) - 1).values))
return m, pos
# --------------------------------- reporting ---------------------------------
ROWS = []
def summarize(family, asset, tf, df, pos, mc_n=300):
full = backtest(df, pos, tf)
oos = backtest(df, pos, tf, lo=VAL_START, hi=HOLDOUT_START)
bh = buy_hold(df, tf)
gross = backtest(df, pos, tf, fee_rt=0.0).sharpe
_, p, _, _ = mc_pvalue(df, pos, tf, n=mc_n)
beats_bh = full.sharpe > bh.sharpe and oos.sharpe > 0
real = (full.sharpe > 0 and oos.sharpe > 0 and not np.isnan(p) and p < 0.05)
verdict = "★EDGE?" if (real and beats_bh) else ("real?" if real else "rumore")
ROWS.append(dict(fam=family, asset=asset, tf=tf, full=full.sharpe, oos=oos.sharpe,
gross=gross, bh=bh.sharpe, p=p, trd=full.ntrades, verdict=verdict))
print(f" {family:<16s} {asset} {tf:<3s} | FULL {full.sharpe:>5.2f} OOS {oos.sharpe:>5.2f} "
f"gross {gross:>5.2f} | B&H {bh.sharpe:>4.2f} | p {p:>.3f} | trd/y {full.ntrades:>6.0f} | {verdict}")
def scan_best(family, asset, tf, df, fn, grid, label_fn):
"""Scansiona la griglia (FULL Sharpe), stampa la riga compatta, ritorna la pos migliore."""
best = None
line = []
for params in grid:
pos = fn(df, *params)
s = backtest(df, pos, tf).sharpe
line.append(f"{label_fn(params)}={s:>4.1f}")
if best is None or s > best[0]:
best = (s, params, pos)
print(f" {asset} {tf} grid: " + " ".join(line))
return best[2], best[1]
def main():
print("=" * 100)
print(" FASE 2 — esplorazione famiglie BTC/ETH | netto fee 0.10% RT | barra = buy&hold | hold-out bloccato")
print("=" * 100)
D1 = {a: load_data(a, "1h") for a in ("BTC", "ETH")}
D15 = {a: load_data(a, "15m") for a in ("BTC", "ETH")}
def block(title):
print("\n" + "#" * 100 + f"\n {title}\n" + "#" * 100)
# ---- TSMOM (momentum) 1h + 15m, L/S e long-only ----
block("TSMOM (momentum)")
Ls = [(12,), (24,), (48,), (96,), (192,)]
for a in ("BTC", "ETH"):
pos, p = scan_best("TSMOM-LS", a, "1h", D1[a], lambda d, L: tsmom(d, L, "ls"), Ls, lambda x: f"L{x[0]}")
summarize("TSMOM-LS", a, "1h", D1[a], pos)
pos, p = scan_best("TSMOM-LO", a, "1h", D1[a], lambda d, L: tsmom(d, L, "lo"), Ls, lambda x: f"L{x[0]}")
summarize("TSMOM-LO", a, "1h", D1[a], pos)
pos, p = scan_best("TSMOM-LS", a, "15m", D15[a], lambda d, L: tsmom(d, L, "ls"), [(48,),(96,),(192,),(384,)], lambda x: f"L{x[0]}")
summarize("TSMOM-LS", a, "15m", D15[a], pos)
# ---- REVERSAL 1h + 15m ----
block("REVERSAL (mean-reversion breve)")
Lr = [(1,), (3,), (6,), (12,), (24,)]
for a in ("BTC", "ETH"):
pos, p = scan_best("REV-LS", a, "1h", D1[a], lambda d, L: reversal(d, L, "ls"), Lr, lambda x: f"L{x[0]}")
summarize("REV-LS", a, "1h", D1[a], pos)
pos, p = scan_best("REV-LS", a, "15m", D15[a], lambda d, L: reversal(d, L, "ls"), Lr, lambda x: f"L{x[0]}")
summarize("REV-LS", a, "15m", D15[a], pos)
# ---- MA cross ----
block("MA-CROSS (trend)")
g = [(12, 48), (24, 96), (48, 192), (24, 200)]
for a in ("BTC", "ETH"):
pos, p = scan_best("MAX-LS", a, "1h", D1[a], lambda d, f, s: ma_cross(d, f, s, "ls"), g, lambda x: f"{x[0]}/{x[1]}")
summarize("MAX-LS", a, "1h", D1[a], pos)
pos, p = scan_best("MAX-LO", a, "1h", D1[a], lambda d, f, s: ma_cross(d, f, s, "lo"), g, lambda x: f"{x[0]}/{x[1]}")
summarize("MAX-LO", a, "1h", D1[a], pos)
# ---- Donchian breakout ----
block("DONCHIAN breakout")
Ld = [(24,), (48,), (96,), (192,)]
for a in ("BTC", "ETH"):
pos, p = scan_best("DONCH-LS", a, "1h", D1[a], lambda d, L: donchian(d, L, "ls"), Ld, lambda x: f"L{x[0]}")
summarize("DONCH-LS", a, "1h", D1[a], pos)
pos, p = scan_best("DONCH-LO", a, "1h", D1[a], lambda d, L: donchian(d, L, "lo"), Ld, lambda x: f"L{x[0]}")
summarize("DONCH-LO", a, "1h", D1[a], pos)
# ---- Vol-target overlay (vs buy&hold) ----
block("VOL-TARGET overlay (sempre-long scalato) — riduce la vol/DD del buy&hold?")
for a in ("BTC", "ETH"):
pos, p = scan_best("VOLTGT", a, "1h", D1[a], lambda d, t: vol_target(d, "1h", t, 72),
[(0.4,), (0.6,), (0.8,), (1.0,)], lambda x: f"t{x[0]}")
summarize("VOLTGT", a, "1h", D1[a], pos)
# ---- Hurst-gated momentum ----
block("HURST-gated momentum (momentum solo in regime trending H>0.5)")
for a in ("BTC", "ETH"):
pos, p = scan_best("HURST-MOM", a, "1h", D1[a], lambda d, L: hurst_mom(d, L, 120, "ls"),
[(24,), (48,), (96,)], lambda x: f"L{x[0]}")
summarize("HURST-MOM", a, "1h", D1[a], pos)
# ---- Lead-lag BTC<->ETH ----
block("LEAD-LAG BTC<->ETH (posiziona un asset col rendimento passato dell'altro)")
for tgt, oth in (("ETH", "BTC"), ("BTC", "ETH")):
Ll = [1, 3, 6, 12, 24]
best = None; line = []
for L in Ll:
m, pos = leadlag_df(D1[tgt], D1[oth], L)
s = backtest(m, pos, "1h").sharpe
line.append(f"L{L}={s:>4.1f}")
if best is None or s > best[0]:
best = (s, L, m, pos)
print(f" {oth}->{tgt} 1h grid: " + " ".join(line))
_, L, m, pos = best
summarize(f"LL {oth}>{tgt}", tgt, "1h", m, pos)
# ---- classifica finale ----
print("\n" + "=" * 100)
print(" CLASSIFICA — net-fee FULL Sharpe (★EDGE? = batte B&H, OOS>0 e null p<0.05)")
print("=" * 100)
for r in sorted(ROWS, key=lambda r: -r["full"]):
print(f" {r['fam']:<16s} {r['asset']} {r['tf']:<3s} | FULL {r['full']:>5.2f} | OOS {r['oos']:>5.2f} | "
f"B&H {r['bh']:>4.2f} | p {r['p']:>.3f} | {r['verdict']}")
edges = [r for r in ROWS if r["verdict"] == "★EDGE?"]
print(f"\n Candidati che battono il buy&hold net-fee + OOS>0 + null p<0.05: {len(edges)}")
for r in edges:
print(f" -> {r['fam']} {r['asset']} {r['tf']}: FULL {r['full']:.2f} OOS {r['oos']:.2f} p {r['p']:.3f}")
if __name__ == "__main__":
main()
+152
View File
@@ -0,0 +1,152 @@
"""FASE 3 — conferma avversariale del SOLO candidato reale: trend-following long-only (MA-cross).
Protocollo onesto:
1. SELEZIONE config SOLO sul pre-hold-out (< 2025-01-01). Niente sbirciate al hold-out.
2. HOLD-OUT 2025-26 sbloccato UNA volta (la prova del nove, mai usato in ricerca).
3. Breakdown PER ANNO vs buy&hold: il trend-LO deve "schivare" i bear (2018/2022).
4. STRESS: fee 2x, lag di esecuzione (1 barra), slippage.
5. DEFLATED SHARPE (Bailey & López de Prado): lo Sharpe regge alla correzione per multiple-testing?
uv run python scripts/analysis/phase3_confirm.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from scipy.stats import norm, skew, kurtosis
from src.data.downloader import load_data
from scripts.analysis.research_lab import (
backtest, buy_hold, window_mask, ts, _net_series, HOLDOUT_START, BARS_PER_YEAR,
)
from scripts.analysis.phase2_families import ma_cross
GRID = [(12, 48), (24, 96), (48, 192), (24, 200), (96, 288)] # MA-cross griglia (fast/slow)
REPR = (24, 96) # config rappresentativa PRE-COMMITTATA
TF = "1h"
def lag(pos, k=1):
"""Esecuzione in ritardo di k barre (agisci k barre dopo la decisione)."""
return np.concatenate([np.zeros(k), pos[:-k]])
def per_year(df, pos, tf):
c = df["close"].values.astype(float)
net, _, fwd, _ = _net_series(df, pos)
yrs = ts(df).dt.year.values
out = {}
for y in sorted(set(yrs)):
m = yrs == y
if m.sum() < 2:
continue
strat = float(np.prod(1 + net[m]) - 1) * 100
bh = float(np.prod(1 + fwd[m]) - 1) * 100
expo = float(np.mean(np.abs(pos[m])))
out[y] = (strat, bh, expo)
return out
def deflated_sharpe(net, sr_trials_perbar, N):
"""DSR: prob. che il vero Sharpe > la soglia attesa-massima sotto N trial (multiple testing).
Tutto in Sharpe PER BARRA. >0.95 = significativo dopo correzione."""
sr = net.mean() / net.std()
T = len(net)
g3 = float(skew(net)); g4 = float(kurtosis(net, fisher=False))
var_sr = float(np.var(sr_trials_perbar, ddof=1)) if len(sr_trials_perbar) > 1 else 0.0
ge = 0.5772156649
z1 = norm.ppf(1 - 1.0 / N); z2 = norm.ppf(1 - 1.0 / (N * np.e))
sr0 = np.sqrt(var_sr) * ((1 - ge) * z1 + ge * z2) # Sharpe atteso-massimo sotto null, N trial
den = np.sqrt(max(1 - g3 * sr + (g4 - 1) / 4.0 * sr ** 2, 1e-9))
dsr = float(norm.cdf((sr - sr0) * np.sqrt(T - 1) / den))
bpy = BARS_PER_YEAR[TF]
return dsr, sr * np.sqrt(bpy), sr0 * np.sqrt(bpy)
def main():
print("=" * 96)
print(" FASE 3 — conferma avversariale: TREND-following long-only (MA-cross) BTC/ETH")
print("=" * 96)
data = {a: load_data(a, TF) for a in ("BTC", "ETH")}
# ---------- 1) selezione SOLO pre-hold-out ----------
print(f"\n (1) SELEZIONE su pre-hold-out (< {HOLDOUT_START}) — Sharpe per config (plateau = robusto)")
for a in ("BTC", "ETH"):
line = []
for f, s in GRID:
pos = ma_cross(data[a], f, s, "lo")
sh = backtest(data[a], pos, TF, hi=HOLDOUT_START).sharpe
line.append(f"{f}/{s}={sh:>4.2f}")
print(f" {a}: " + " ".join(line))
print(f" -> config rappresentativa PRE-COMMITTATA per i test seguenti: {REPR[0]}/{REPR[1]}")
# ---------- 2) HOLD-OUT 2025-26 (sbloccato una volta) ----------
print(f"\n (2) HOLD-OUT {HOLDOUT_START}+ — LA PROVA DEL NOVE (mai usato in ricerca)")
for a in ("BTC", "ETH"):
bh = buy_hold(data[a], TF, lo=HOLDOUT_START)
print(f" {a}: buy&hold hold-out Sh {bh.sharpe:>5.2f} ret {bh.ret*100:>+7.1f}% DD {bh.maxdd*100:>4.1f}%")
for f, s in GRID:
pos = ma_cross(data[a], f, s, "lo")
r = backtest(data[a], pos, TF, lo=HOLDOUT_START)
star = " <-REPR" if (f, s) == REPR else ""
print(f" {f}/{s:<3d} Sh {r.sharpe:>5.2f} ret {r.ret*100:>+7.1f}% DD {r.maxdd*100:>4.1f}% expo {r.exposure:.2f}{star}")
# ---------- 3) per anno vs buy&hold (schiva i bear?) ----------
print(f"\n (3) PER ANNO — strat {REPR[0]}/{REPR[1]} vs buy&hold (expo = quanto è long; bear test 2018/2022)")
for a in ("BTC", "ETH"):
pos = ma_cross(data[a], *REPR, "lo")
py = per_year(data[a], pos, TF)
print(f" {a}:")
for y, (st, bh, ex) in py.items():
flag = " <- BEAR" if bh < -20 else ""
print(f" {y}: strat {st:>+7.0f}% | buy&hold {bh:>+7.0f}% | expo {ex:.2f}{flag}")
# ---------- 4) stress ----------
print(f"\n (4) STRESS — strat {REPR[0]}/{REPR[1]} | FULL e HOLD-OUT Sharpe")
print(f" {'scenario':<24s}{'BTC FULL':>10s}{'BTC HO':>9s}{'ETH FULL':>10s}{'ETH HO':>9s}")
scen = [
("base fee0.10%", dict(fee_rt=0.001), False),
("fee 0.20% (2x)", dict(fee_rt=0.002), False),
("lag 1 barra", dict(fee_rt=0.001), True),
("fee2x + lag", dict(fee_rt=0.002), True),
]
for name, kw, do_lag in scen:
row = [name]
for a in ("BTC", "ETH"):
pos = ma_cross(data[a], *REPR, "lo")
if do_lag:
pos = lag(pos, 1)
full = backtest(data[a], pos, TF, **kw).sharpe
ho = backtest(data[a], pos, TF, lo=HOLDOUT_START, **kw).sharpe
row += [f"{full:>9.2f}", f"{ho:>8.2f}"]
print(f" {row[0]:<24s}{row[1]:>10s}{row[2]:>9s}{row[3]:>10s}{row[4]:>9s}")
# ---------- 5) deflated Sharpe ----------
print(f"\n (5) DEFLATED SHARPE — corregge il multiple-testing (DSR>0.95 = regge)")
# trial set = TUTTE le config trend long-only provate (proxy del numero di tentativi)
N_TRIALS = 60 # stima conservativa dei backtest provati in Fase 2 (tutte le famiglie/asset/TF)
for a in ("BTC", "ETH"):
trials = [backtest(data[a], ma_cross(data[a], f, s, "lo"), TF, hi=HOLDOUT_START) for f, s in GRID]
sr_trials = []
for f, s in GRID:
net, _, _, _ = _net_series(data[a], ma_cross(data[a], f, s, "lo"))
m = window_mask(data[a], hi=HOLDOUT_START)
sr_trials.append(net[m].mean() / net[m].std())
net, _, _, _ = _net_series(data[a], ma_cross(data[a], *REPR, "lo"))
m = window_mask(data[a], hi=HOLDOUT_START)
dsr, sr_ann, sr0_ann = deflated_sharpe(net[m], sr_trials, N_TRIALS)
verdict = "REGGE" if dsr > 0.95 else "NON regge"
print(f" {a} (pre-hold-out): Sharpe {sr_ann:.2f} vs soglia-max-attesa(N={N_TRIALS}) {sr0_ann:.2f} "
f"-> DSR {dsr:.3f} [{verdict}]")
print("\n" + "=" * 96)
print(" VERDETTO: edge ONESTO solo se (2) hold-out positivo, (3) schiva i bear, (4) regge lo")
print(" stress, (5) DSR>0.95. Altrimenti: anche il trend era sample-luck del mercato toro.")
print("=" * 96)
if __name__ == "__main__":
main()
+208
View File
@@ -0,0 +1,208 @@
"""HARNESS DI RICERCA ONESTO — BTC/ETH, v2.0.0 (Fase 0).
Dopo che l'intera libreria precedente si è rivelata artefatto di feed/harness disonesti,
la prima cosa di cui fidarsi NON è una strategia ma il banco di prova. Questo modulo è
quel banco: causale per costruzione, netto fee, con baseline e null model.
MODELLO CANONICO = SERIE DI POSIZIONE.
Una strategia è una funzione signal(df, **params) -> pd.Series/np.array che dà la
posizione target per barra in [-1, +1]. REGOLA: position[i] è decisa con dati FINO a
close[i] (mai oltre) e GUADAGNA il rendimento close[i] -> close[i+1]. L'engine moltiplica
position[i] * fwd[i] (fwd strettamente futuro rispetto alla decisione) -> niente look-ahead
per costruzione, e niente fill sull'estremo di candela (si entra al close). La fee è
addebitata sul TURNOVER |Δposition| (un round-trip 0->1->0 = 2 unità = fee_rt intera).
GATE (vedi CLAUDE.md): ingresso eseguibile (qui per costruzione), netto fee 0.10% RT,
OOS held-out, robustezza su griglia, onestà statistica (null model + buy&hold), walk-forward
per i modelli fittati, liquidità (BTC/ETH ok).
uv run python scripts/analysis/research_lab.py # self-test del banco
"""
from __future__ import annotations
import sys
from dataclasses import dataclass
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from src.data.downloader import load_data
FEE_RT = 0.001 # 0.10% round-trip taker Deribit (0.05%/lato)
BARS_PER_YEAR = {"5m": 105192.0, "15m": 35064.0, "1h": 8766.0,
"4h": 2191.5, "12h": 730.5, "1d": 365.25}
def load_tf(asset: str, tf: str):
"""Carica un TF certificato. 5m/15m/1h diretti; 4h/12h/1d DERIVATI per resample dal 1h
(confini 00:00 UTC). >=12h e' il regime raccomandato (sotto, costi+overfit dominano)."""
if tf in ("5m", "15m", "1h"):
return load_data(asset, tf)
rule = {"4h": "4h", "12h": "12h", "1d": "1D"}[tf]
df = load_data(asset, "1h").copy()
df.index = pd.to_datetime(df["timestamp"], unit="ms", utc=True)
out = df.resample(rule, label="left", closed="left").agg(
{"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"}).dropna(subset=["open"])
epoch = pd.Timestamp("1970-01-01", tz="UTC")
out["timestamp"] = ((out.index - epoch) // pd.Timedelta(milliseconds=1)).astype("int64")
return out.reset_index(drop=True)[["timestamp", "open", "high", "low", "close", "volume"]]
# Hold-out FINALE bloccato: NIENTE ricerca/tuning lo tocca finché non è il verdetto (Fase 3).
HOLDOUT_START = "2025-01-01"
# Finestra di validazione OOS usata in ricerca (out-of-sample ma PRE hold-out).
VAL_START = "2023-01-01"
def ts(df) -> pd.Series:
return pd.to_datetime(df["timestamp"], unit="ms", utc=True)
def window_mask(df, lo: str | None = None, hi: str | None = None) -> np.ndarray:
t = ts(df)
m = np.ones(len(df), bool)
if lo is not None:
m &= (t >= pd.Timestamp(lo, tz="UTC")).values
if hi is not None:
m &= (t < pd.Timestamp(hi, tz="UTC")).values
return m
@dataclass
class BT:
n: int
ret: float # rendimento composto sulla finestra (pos 1x, leva 1x)
cagr: float
sharpe: float # annualizzato
maxdd: float # % (positivo)
exposure: float # |pos| medio
turnover: float # Σ|Δpos| / anno
ntrades: float # round-trip equivalenti / anno
def line(self, label="") -> str:
return (f" {label:<22s} Sh {self.sharpe:>6.2f} | ret {self.ret*100:>+8.1f}% "
f"CAGR {self.cagr*100:>+6.1f}% | DD {self.maxdd*100:>5.1f}% | "
f"expo {self.exposure:>4.2f} trd/y {self.ntrades:>6.1f} | n {self.n}")
def _net_series(df, position, fee_rt=FEE_RT):
"""Ritorna (net, gross, fwd, pos) per barra. net[i] = pos[i]*fwd[i] - fee sul cambio a i."""
c = df["close"].values.astype(float)
pos = np.nan_to_num(np.asarray(position, float), nan=0.0)
pos = np.clip(pos, -1.0, 1.0)
n = len(c)
fwd = np.zeros(n)
fwd[:-1] = c[1:] / c[:-1] - 1.0 # rendimento close[i]->close[i+1] (futuro vs decisione a i)
gross = pos * fwd
dpos = np.abs(np.diff(np.concatenate([[0.0], pos]))) # cambio di posizione a i (si tradea al close[i])
fee = dpos * (fee_rt / 2.0) # fee_rt = round-trip (2 unità di turnover); /2 per unità
net = gross - fee
return net, gross, fwd, pos
def backtest(df, position, tf="1h", fee_rt=FEE_RT, lo=None, hi=None) -> BT:
net, gross, fwd, pos = _net_series(df, position, fee_rt)
m = window_mask(df, lo, hi)
net_w, pos_w = net[m], pos[m]
dpos_w = np.abs(np.diff(np.concatenate([[0.0], pos_w])))
bpy = BARS_PER_YEAR[tf]
n = int(m.sum())
if n < 2:
return BT(n, 0, float("nan"), 0, 0, 0, 0, 0)
eq = np.cumprod(1.0 + net_w)
total = float(eq[-1] - 1.0)
years = n / bpy
cagr = float((1 + total) ** (1 / years) - 1) if years > 0 and total > -1 else float("nan")
mu, sd = float(net_w.mean()), float(net_w.std())
sharpe = mu / sd * np.sqrt(bpy) if sd > 0 else 0.0
peak = np.maximum.accumulate(eq)
maxdd = float(np.max((peak - eq) / peak)) if n else 0.0
expo = float(np.mean(np.abs(pos_w)))
turn_y = float(dpos_w.sum() / years) if years > 0 else 0.0
return BT(n, total, cagr, sharpe, maxdd, expo, turn_y, turn_y / 2.0)
def buy_hold(df, tf="1h", fee_rt=FEE_RT, lo=None, hi=None) -> BT:
return backtest(df, np.ones(len(df)), tf, fee_rt, lo, hi)
def mc_pvalue(df, position, tf="1h", fee_rt=FEE_RT, n=500, lo=None, hi=None, seed=0):
"""Null model a ROTAZIONE CIRCOLARE: ruota la serie di posizione di un offset casuale.
Preserva ESATTAMENTE exposure, turnover e distribuzione degli holding; distrugge solo
l'allineamento col mercato. p = P(Sharpe_ruotato >= Sharpe_reale). p alto = il timing
non batte il caso (nessuna skill)."""
pos = np.nan_to_num(np.asarray(position, float))
base = backtest(df, pos, tf, fee_rt, lo, hi).sharpe
N = len(pos)
if np.abs(np.diff(pos)).sum() == 0: # posizione costante -> rotazione degenere
return base, float("nan"), float("nan"), float("nan")
rng = np.random.default_rng(seed)
sims = np.empty(n)
for k in range(n):
off = int(rng.integers(1, N))
sims[k] = backtest(df, np.roll(pos, off), tf, fee_rt, lo, hi).sharpe
p = float((np.sum(sims >= base) + 1) / (n + 1))
return base, p, float(sims.mean()), float(sims.std())
def report(name, df, position, tf="1h", fee_rt=FEE_RT, mc_n=400):
"""Stampa il verdetto onesto: FULL / OOS-VAL / vs buy&hold / null p-value / sweep fee."""
print(f"\n === {name} ({tf}) ===")
print(backtest(df, position, tf, fee_rt).line("FULL"))
print(backtest(df, position, tf, fee_rt, lo=VAL_START, hi=HOLDOUT_START).line(f"OOS-VAL {VAL_START[:4]}-24"))
print(buy_hold(df, tf, fee_rt).line("buy&hold FULL"))
base, p, msh, ssd = mc_pvalue(df, position, tf, fee_rt, n=mc_n)
verdict = "RUMORE" if (np.isnan(p) or p > 0.05) else "batte il null"
print(f" null (rotazione, n={mc_n}): Sharpe reale {base:.2f} vs random {msh:.2f}±{ssd:.2f} "
f"-> p={p if not np.isnan(p) else float('nan'):.3f} [{verdict}]")
print(" sweep fee RT:", " ".join(
f"{f*100:.2f}%→Sh{backtest(df, position, tf, f).sharpe:.2f}" for f in (0.0, 0.0005, 0.001, 0.002)))
# ============================ SELF-TEST DEL BANCO ============================
def self_test():
"""Valida l'HARNESS, non una strategia. Tre prove:
(1) buy&hold: Sharpe positivo, DD grande (sanity dei numeri).
(2) CHEAT look-ahead (pos = segno del rendimento FUTURO): Sharpe enorme, p≈0
-> l'engine SA vedere un edge quando esiste davvero.
(3) NOISE causale (pos da rumore del passato): Sharpe≈0, p≈0.5
-> l'engine NON inventa edge dal nulla (niente leak)."""
print("=" * 78)
print(" SELF-TEST HARNESS — deve: vedere il cheat, NON vedere il rumore")
print("=" * 78)
df = load_data("BTC", "1h")
t = ts(df)
c = df["close"].values.astype(float)
bh = buy_hold(df, "1h")
print(bh.line("(1) buy&hold BTC"))
assert bh.sharpe > 0, "buy&hold dovrebbe avere Sharpe>0 sullo storico BTC"
# (2) CHEAT: posizione = segno del rendimento del prossimo bar (USA IL FUTURO)
fwd = np.zeros(len(c)); fwd[:-1] = c[1:] / c[:-1] - 1.0
cheat = np.sign(fwd)
bt_cheat = backtest(df, cheat, "1h")
_, p_cheat, _, _ = mc_pvalue(df, cheat, "1h", n=200, seed=1)
print(bt_cheat.line("(2) CHEAT look-ahead"))
print(f" -> null p={p_cheat:.4f} (atteso ≈0: l'edge finto È enorme e battibile dal caso ~mai)")
assert bt_cheat.sharpe > 20, "il cheat dovrebbe dare Sharpe enorme se l'engine è corretto"
assert p_cheat < 0.02, "il cheat dovrebbe battere il null in modo schiacciante"
# (3) NOISE causale a BASSO turnover (blocchi ~50 barre): isola la SKILL dalla fee-death.
# Posizione casuale (non usa il futuro) tenuta a blocchi -> turnover basso -> se l'engine non
# inventa edge dal nulla, Sharpe≈0 e il null p≈0.5 (random rotazioni indistinguibili).
rng = np.random.default_rng(42)
blk = 50
raw = np.sign(rng.standard_normal(len(c) // blk + 1))
noise_pos = np.repeat(raw, blk)[:len(c)]
noise_pos = pd.Series(noise_pos).shift(1).fillna(0).values # solo passato
bt_noise = backtest(df, noise_pos, "1h")
base_n, p_noise, msh, ssd = mc_pvalue(df, noise_pos, "1h", n=400, seed=2)
print(bt_noise.line("(3) NOISE causale"))
print(f" -> null p={p_noise:.3f} (atteso alto/≈0.5: nessuna skill, indistinguibile dal caso)")
assert bt_noise.sharpe < 2.0, "il rumore causale non deve sembrare SKILLATO (Sharpe positivo grande = leak)"
assert p_noise > 0.10, "il rumore causale non deve battere il null (p basso = edge spurio/leak)"
print("\n ✓ HARNESS VALIDATO: vede il cheat (Sharpe enorme, p≈0), non inventa edge dal rumore (p alto).")
print(f" Hold-out finale BLOCCATO da {HOLDOUT_START} (non usato in ricerca). OOS-VAL: {VAL_START}→hold-out.")
if __name__ == "__main__":
self_test()
+121
View File
@@ -0,0 +1,121 @@
"""STRESS-TEST di TP01 (integrato da strategy-research-2026-06) — robustezza avversariale.
Usa il modulo VERO integrato (src/strategies/trend_portfolio). Oltre a hold-out/cross-asset/multi-TF
(gia' in verify_tp01.py), qui: sweep FEE (fino 0.40% RT), LAG di esecuzione + slippage, PLATEAU dei
parametri (config cherry-picked?), DEFLATED-SHARPE (multiple-testing track A-E).
uv run python scripts/analysis/stress_tp01.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from scipy.stats import norm, skew, kurtosis
from src.data.downloader import load_data
from src.strategies.trend_portfolio import TrendPortfolio, resample_4h, simple_returns, CANONICAL
HOLDOUT = pd.Timestamp("2025-01-01", tz="UTC")
DF4H = {a: resample_4h(load_data(a, "1h")) for a in ("BTC", "ETH")}
def combo(cfg, lag_bars=0, fee_side=0.0005):
"""Rendimenti per-barra del portafoglio 50/50 con config cfg, lag extra e fee dati."""
tp = TrendPortfolio(**{**cfg, "fee_side": fee_side})
series = {}
for a in ("BTC", "ETH"):
df = DF4H[a]
r = simple_returns(df["close"].values.astype(float))
tgt = tp.target_series(df)
held = np.zeros(len(tgt))
s = 1 + lag_bars
held[s:] = tgt[:-s] # tenuta = decisa s barre prima (causale + lag)
net = held * r - fee_side * np.abs(np.diff(held, prepend=0.0))
net[0] = 0.0
series[a] = pd.Series(np.clip(net, -0.99, None), index=pd.to_datetime(df["datetime"]))
J = pd.concat(series, axis=1, join="inner").fillna(0.0)
return 0.5 * J["BTC"].values + 0.5 * J["ETH"].values, J.index
def met(combo_r, idx):
rr = combo_r[np.isfinite(combo_r)]
if len(rr) < 2 or np.std(rr) == 0:
return dict(sh=0, ret=0, dd=0)
bpy = 86400 * 365.25 / pd.Series(idx).diff().dt.total_seconds().median()
eq = np.cumprod(1 + rr); pk = np.maximum.accumulate(eq)
return dict(sh=float(np.mean(rr) / np.std(rr) * np.sqrt(bpy)),
ret=float(eq[-1] - 1), dd=float(np.max((pk - eq) / pk)))
def full_ho(cfg, lag_bars=0, fee_side=0.0005):
cr, idx = combo(cfg, lag_bars, fee_side)
ho = idx >= HOLDOUT
return met(cr, idx), met(cr[ho], idx[ho])
def main():
print("=" * 88)
print(" STRESS-TEST TP01 (PORT LF4h canonica) — robustezza avversariale")
print("=" * 88)
base_f, base_h = full_ho(CANONICAL)
print(f"\n BASELINE (4h, fee 0.10% RT): FULL Sh {base_f['sh']:.2f} ret {base_f['ret']*100:+.0f}% DD {base_f['dd']*100:.1f}%"
f" | HOLD-OUT Sh {base_h['sh']:.2f} ret {base_h['ret']*100:+.1f}% DD {base_h['dd']*100:.1f}%")
print("\n (1) SWEEP FEE (RT) — regge fino a 0.40%?")
print(f" {'fee RT':<10s}{'FULL Sh':>9s}{'FULL ret':>10s}{'HOLD Sh':>9s}{'HOLD ret':>10s}")
for frt in (0.0, 0.001, 0.002, 0.004):
f, h = full_ho(CANONICAL, fee_side=frt / 2)
print(f" {frt*100:>5.2f}% {f['sh']:>8.2f}{f['ret']*100:>+9.0f}%{h['sh']:>9.2f}{h['ret']*100:>+9.1f}%")
print("\n (2) LAG di esecuzione + slippage (fee 0.20% per simulare slippage)")
print(f" {'scenario':<22s}{'FULL Sh':>9s}{'HOLD Sh':>9s}{'HOLD ret':>10s}")
for name, lag, frt in [("base", 0, 0.001), ("lag 1 barra (4h)", 1, 0.001),
("lag 2 barre", 2, 0.001), ("lag1 + fee0.20% slip", 1, 0.002)]:
f, h = full_ho(CANONICAL, lag_bars=lag, fee_side=frt / 2)
print(f" {name:<22s}{f['sh']:>8.2f}{h['sh']:>9.2f}{h['ret']*100:>+9.1f}%")
print("\n (3) PLATEAU PARAMETRI — la config canonica e' un picco o un altopiano?")
print(f" {'variazione':<26s}{'FULL Sh':>9s}{'HOLD Sh':>9s}")
grid = [
("canonica (vt.20 lev2 30/90/180 vw30)", CANONICAL),
("target_vol 0.15", {**CANONICAL, "target_vol": 0.15}),
("target_vol 0.25", {**CANONICAL, "target_vol": 0.25}),
("leverage 1.5", {**CANONICAL, "leverage": 1.5}),
("leverage 3.0", {**CANONICAL, "leverage": 3.0}),
("horizons 20/60/120", {**CANONICAL, "horizons_days": (20, 60, 120)}),
("horizons 60/120/240", {**CANONICAL, "horizons_days": (60, 120, 240)}),
("vol_win 20", {**CANONICAL, "vol_win_days": 20}),
("vol_win 45", {**CANONICAL, "vol_win_days": 45}),
]
sr_trials = []
for name, cfg in grid:
f, h = full_ho(cfg)
cr, idx = combo(cfg)
sr_trials.append(cr[np.isfinite(cr)].mean() / cr[np.isfinite(cr)].std()) # Sharpe per-barra
print(f" {name:<26s}{f['sh']:>8.2f}{h['sh']:>9.2f}")
print("\n (4) DEFLATED SHARPE — corregge il multiple-testing (track A-E + sweep). DSR>0.95 = regge")
cr, idx = combo(CANONICAL)
rr = cr[np.isfinite(cr)]
sr = rr.mean() / rr.std(); T = len(rr)
g3 = float(skew(rr)); g4 = float(kurtosis(rr, fisher=False))
var_sr = float(np.var(sr_trials, ddof=1))
ge = 0.5772156649
for N in (10, 40, 100): # N = numero di trial/config provati (conservativo)
z1 = norm.ppf(1 - 1.0 / N); z2 = norm.ppf(1 - 1.0 / (N * np.e))
sr0 = np.sqrt(var_sr) * ((1 - ge) * z1 + ge * z2)
den = np.sqrt(max(1 - g3 * sr + (g4 - 1) / 4.0 * sr ** 2, 1e-9))
dsr = float(norm.cdf((sr - sr0) * np.sqrt(T - 1) / den))
bpy = 86400 * 365.25 / pd.Series(idx).diff().dt.total_seconds().median()
print(f" N={N:>3d} trial -> soglia-max-attesa Sh {sr0*np.sqrt(bpy):.2f} | DSR {dsr:.3f} [{'REGGE' if dsr>0.95 else 'NON regge'}]")
print("\n" + "=" * 88)
print(" Verdetto: TP01 robusto se regge fee 0.40%+lag (HOLD positivo), plateau (no picco), DSR>0.95.")
print("=" * 88)
if __name__ == "__main__":
main()
+96
View File
@@ -0,0 +1,96 @@
"""TP01 a BASSA FREQUENZA (>=12h) — ri-verifica dopo il bug look-ahead ffill-mixed-TF.
L'utente/agente ha trovato un look-ahead (ffill mixed-timeframe su barre open-labeled) che
gonfiava il 4h (~1.60 -> reale ~1.1) e ha concluso: NON scendere sotto le 12h (costi+overfit
dominano). Qui ricalcolo TP01 in modo PULITO per singolo TF (barre discrete, posizione shiftata
+1, NESSUN ffill/combine mixed-TF) su 4h/12h/1d, con un GUARD di causalita' esplicito sulla serie
resamplata (ricalcolo su prefisso). Fee 0.10% RT, hold-out 2025-26 bloccato.
uv run python scripts/analysis/tp01_lowfreq.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from src.data.downloader import load_data
from src.strategies.trend_portfolio import TrendPortfolio, simple_returns, CANONICAL
HOLDOUT = pd.Timestamp("2025-01-01", tz="UTC")
def resample_tf(df_1h, rule):
g = df_1h.copy()
g.index = pd.to_datetime(g["timestamp"], unit="ms", utc=True)
out = g.resample(rule, label="left", closed="left").agg(
{"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"}).dropna(subset=["open"])
out["datetime"] = out.index
return out.reset_index(drop=True)
def sleeve_net(df, tp):
"""Per-barra netto di uno sleeve: posizione decisa a close[i-1], tenuta in i (causale, no ffill)."""
r = simple_returns(df["close"].values.astype(float))
tgt = tp.target_series(df)
held = np.zeros(len(tgt)); held[1:] = tgt[:-1]
net = held * r - tp.fee_side * np.abs(np.diff(held, prepend=0.0)); net[0] = 0.0
return np.clip(net, -0.99, None)
def causality_ok(df, tp, k=10):
"""Ricalcola target_series su prefissi e verifica che tgt[i] non cambi (no look-ahead)."""
full = tp.target_series(df); n = len(df)
rng = np.random.default_rng(0); bad = 0
for i in rng.integers(int(n * 0.6), n - 1, size=k):
p = tp.target_series(df.iloc[:i + 1].copy())
if len(p) != i + 1 or not np.isclose(np.nan_to_num(p[i]), np.nan_to_num(full[i]), atol=1e-9):
bad += 1
return bad
def met(rr, idx):
rr = rr[np.isfinite(rr)]
if len(rr) < 2 or np.std(rr) == 0:
return dict(sh=0, ret=0, dd=0, n=len(rr))
bpy = 86400 * 365.25 / pd.Series(idx).diff().dt.total_seconds().median()
eq = np.cumprod(1 + rr); pk = np.maximum.accumulate(eq)
return dict(sh=float(np.mean(rr) / np.std(rr) * np.sqrt(bpy)), ret=float(eq[-1] - 1),
dd=float(np.max((pk - eq) / pk)), n=len(rr))
def main():
print("=" * 92)
print(" TP01 RI-VERIFICA BASSA FREQUENZA — calcolo pulito per-TF (no ffill mixed-TF) | fee 0.10% RT")
print("=" * 92)
tp = TrendPortfolio(**CANONICAL)
print(f" {'TF':<5s}{'leak':>6s}{'FULL Sh':>9s}{'FULL ret':>10s}{'FULL DD':>9s}{'HOLD Sh':>9s}{'HOLD ret':>10s}{'HOLD DD':>9s}")
for tf, rule in [("4h", "4h"), ("6h", "6h"), ("12h", "12h"), ("1d", "1D")]:
series = {}; leak = 0
for a in ("BTC", "ETH"):
df = resample_tf(load_data(a, "1h"), rule)
leak += causality_ok(df, tp)
series[a] = pd.Series(sleeve_net(df, tp), index=pd.to_datetime(df["datetime"]))
J = pd.concat(series, axis=1, join="inner").fillna(0.0)
combo = 0.5 * J["BTC"].values + 0.5 * J["ETH"].values
idx = J.index; ho = idx >= HOLDOUT
f = met(combo, idx); h = met(combo[ho], idx[ho])
print(f" {tf:<5s}{leak:>6d}{f['sh']:>9.2f}{f['ret']*100:>+9.0f}%{f['dd']*100:>8.1f}%"
f"{h['sh']:>9.2f}{h['ret']*100:>+9.1f}%{h['dd']*100:>8.1f}%")
# buy&hold 50/50 a 1d come riferimento hold-out
bh = {}
for a in ("BTC", "ETH"):
df = resample_tf(load_data(a, "1h"), "1D")
bh[a] = pd.Series(simple_returns(df["close"].values.astype(float)), index=pd.to_datetime(df["datetime"]))
Jb = pd.concat(bh, axis=1, join="inner").fillna(0.0)
cb = 0.5 * Jb["BTC"].values + 0.5 * Jb["ETH"].values; ix = Jb.index; ho = ix >= HOLDOUT
bhf = met(cb, ix); bhh = met(cb[ho], ix[ho])
print(f"\n buy&hold 50/50 (1d): FULL Sh {bhf['sh']:.2f} ret {bhf['ret']*100:+.0f}% DD {bhf['dd']*100:.0f}%"
f" | HOLD-OUT Sh {bhh['sh']:.2f} ret {bhh['ret']*100:+.0f}% DD {bhh['dd']*100:.0f}%")
print("\n (leak=0 = nessun look-ahead nel calcolo per-TF. Confronta con la tesi: >=12h trustworthy.)")
if __name__ == "__main__":
main()
+149
View File
@@ -0,0 +1,149 @@
"""VERIFICA AVVERSARIALE di TP01 (branch strategy-research-2026-06) col MIO gauntlet onesto.
TP01 = TSMOM multi-orizzonte (30/90/180g) long-flat, vol-target 20%, leva cap 2x, portafoglio
50/50 BTC+ETH. Codice riprodotto VERBATIM dal branch (src/strategies/trend_portfolio.py).
La loro tesi: 'positiva ogni anno 2019-2026, Sharpe ~1.32'. Il mio test decisivo: il HOLD-OUT
2025-26 (che ha bocciato il mio trend 1h in Fase 3) + cross-asset + multi-TF (cherry-picking 4h?).
uv run python scripts/analysis/verify_tp01.py
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np
import pandas as pd
from src.data.downloader import load_data
HOLDOUT = pd.Timestamp("2025-01-01", tz="UTC")
CANONICAL = dict(target_vol=0.20, leverage=2.0, long_only=True,
horizons_days=(30, 90, 180), vol_win_days=30, fee_side=0.0005)
# ---- TP01 riprodotto VERBATIM dal branch ----
def simple_returns(c):
r = np.zeros(len(c)); r[1:] = c[1:] / c[:-1] - 1.0; return r
def realized_vol(r, win, bpy):
return pd.Series(r).rolling(win, min_periods=win // 2).std().values * np.sqrt(bpy)
def tsmom_blend(c, horizons):
n = len(c); acc = np.zeros(n); cnt = np.zeros(n)
for h in horizons:
s = np.full(n, np.nan); s[h:] = np.sign(c[h:] / c[:-h] - 1.0)
v = np.isfinite(s); acc[v] += s[v]; cnt[v] += 1
out = np.zeros(n); nz = cnt > 0; out[nz] = acc[nz] / cnt[nz]; return out
def target_series(df, p, bpd):
c = df["close"].values.astype(float); bpy = bpd * 365.25
r = simple_returns(c)
vol = realized_vol(r, p["vol_win_days"] * bpd, bpy)
direction = tsmom_blend(c, tuple(d * bpd for d in p["horizons_days"]))
if p["long_only"]:
direction = np.clip(direction, 0, None)
scal = np.where((vol > 0) & np.isfinite(vol), p["target_vol"] / vol, 0.0)
tgt = np.clip(direction * scal, -p["leverage"], p["leverage"]); tgt[~np.isfinite(tgt)] = 0.0
return tgt
def net_returns(df, p, bpd):
c = df["close"].values.astype(float); r = simple_returns(c)
tgt = target_series(df, p, bpd)
pos_held = np.zeros(len(tgt)); pos_held[1:] = tgt[:-1] # decisa a close[t-1], tenuta in t -> causale
gross = pos_held * r
turn = np.abs(np.diff(pos_held, prepend=0.0))
net = gross - p["fee_side"] * turn; net[0] = 0.0
return np.clip(net, -0.99, None), pos_held
def resample(df_1h, rule):
g = df_1h.copy(); idx = pd.to_datetime(g["timestamp"], unit="ms", utc=True); g.index = idx
out = g.resample(rule, label="left", closed="left").agg(
{"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"}).dropna(subset=["open"])
out["timestamp"] = out.index
return out.reset_index(drop=True)
def metrics(combo, idx):
rr = combo[np.isfinite(combo)]
if len(rr) < 2 or np.std(rr) == 0:
return dict(sharpe=0, cagr=0, dd=0, ret=0, n=len(rr))
dt = pd.Series(idx).diff().dt.total_seconds().median()
bpy = 86400 * 365.25 / dt
eq = np.cumprod(1 + rr); peak = np.maximum.accumulate(eq)
years = (idx[-1] - idx[0]).total_seconds() / 86400 / 365.25
return dict(sharpe=float(np.mean(rr) / np.std(rr) * np.sqrt(bpy)),
cagr=float(eq[-1] ** (1 / years) - 1) if years > 0 else 0,
dd=float(np.max((peak - eq) / peak)), ret=float(eq[-1] - 1), n=len(rr))
def portfolio_combo(tf_rule, bpd):
series = {}
for a in ("BTC", "ETH"):
df = load_data(a, "1h")
if tf_rule:
df = resample(df, tf_rule)
net, _ = net_returns(df, CANONICAL, bpd)
series[a] = pd.Series(net, index=pd.to_datetime(df["timestamp"], unit="ms", utc=True) if not tf_rule
else pd.DatetimeIndex(df["timestamp"]))
J = pd.concat(series, axis=1, join="inner").fillna(0.0)
combo = 0.5 * J["BTC"].values + 0.5 * J["ETH"].values
return combo, J.index, J
def line(label, combo, idx):
m = metrics(combo, idx)
return f" {label:<22s} Sharpe {m['sharpe']:>5.2f} | ret {m['ret']*100:>+8.1f}% CAGR {m['cagr']*100:>+6.1f}% | DD {m['dd']*100:>5.1f}% | n {m['n']}"
def main():
print("=" * 92)
print(" VERIFICA TP01 (TSMOM 30/90/180 vol-target 20% lev2x long-flat, 50/50 BTC+ETH)")
print(" col gauntlet onesto: FULL vs buy&hold | HOLD-OUT 2025-26 bloccato | per-anno | multi-TF")
print("=" * 92)
TFS = [("15m", "15min", 96), ("1h", None, 24), ("4h", "4h", 6), ("1d", "1D", 1)]
print("\n (A) MULTI-TF: il 4h e' cherry-picked? FULL + HOLD-OUT per ogni timeframe")
for tf, rule, bpd in TFS:
combo, idx, J = portfolio_combo(rule, bpd)
ho = idx >= HOLDOUT
full = metrics(combo, idx)
hold = metrics(combo[ho], idx[ho])
tag = " <- canonica" if tf == "4h" else ""
print(f" {tf:<3s} FULL Sh {full['sharpe']:>5.2f} CAGR {full['cagr']*100:>+6.1f}% DD {full['dd']*100:>4.1f}% "
f"| HOLD-OUT Sh {hold['sharpe']:>5.2f} ret {hold['ret']*100:>+6.1f}% DD {hold['dd']*100:>4.1f}%{tag}")
# focus 4h canonica
combo, idx, J = portfolio_combo("4h", 6)
print("\n (B) 4h CANONICA — per anno (la tesi: positiva OGNI anno 2019-2026)")
s = pd.Series(combo, index=idx)
for y, g in s.groupby(s.index.year):
eq = np.cumprod(1 + g.values); pk = np.maximum.accumulate(eq)
ho_flag = " <- HOLD-OUT (mai usato per scegliere config?)" if y >= 2025 else ""
print(f" {y}: ret {(eq[-1]-1)*100:>+7.1f}% DD {np.max((pk-eq)/pk)*100:>5.1f}%{ho_flag}")
print("\n (C) HOLD-OUT 2025-26 — TP01 vs buy&hold 50/50 (4h)")
ho = idx >= HOLDOUT
print(line("TP01 portfolio HO", combo[ho], idx[ho]))
# buy&hold 50/50 sullo stesso indice/finestra
bh = {}
for a in ("BTC", "ETH"):
df = resample(load_data(a, "1h"), "4h")
r = simple_returns(df["close"].values.astype(float))
bh[a] = pd.Series(r, index=pd.DatetimeIndex(df["timestamp"]))
Jb = pd.concat(bh, axis=1, join="inner").reindex(idx).fillna(0.0)
bh_combo = 0.5 * Jb["BTC"].values + 0.5 * Jb["ETH"].values
print(line("buy&hold 50/50 HO", bh_combo[ho], idx[ho]))
print(line("TP01 portfolio FULL", combo, idx))
print(line("buy&hold 50/50 FULL", bh_combo, idx))
print("\n (D) CROSS-ASSET nel HOLD-OUT (lo stesso edge regge su ENTRAMBI?)")
for a in ("BTC", "ETH"):
df = resample(load_data(a, "1h"), "4h")
net, _ = net_returns(df, CANONICAL, 6)
ix = pd.DatetimeIndex(df["timestamp"]); m = ix >= HOLDOUT
print(line(f"TP01 {a} sleeve HO", net[m], ix[m]))
if __name__ == "__main__":
main()
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# BOOK DERIBIT-ONLY (TP01+SKH01 nettati) — esecuzione LIVE a cadenza ORARIA. v2.0.0+.
# SKH01 decide su griglia 230m -> serve girare piu' spesso del daily; orario IDEMPOTENTE:
# riconcilia al target NETTO corrente (se non cambia nulla -> HOLD). Il feed 5m fresco per il
# segnale SKH e' preso IN MEMORIA dentro book_execute (livefeed.fresh_5m): NON tocca i dati
# certificati su disco. Esecuzione reale gated da config/live.json (execution_enabled) + --execute.
export PATH="/home/adriano/.local/bin:$PATH"
cd /opt/docker/PythagorasGoal || exit 1
mkdir -p logs
{
echo "===== $(date -u '+%Y-%m-%dT%H:%M:%SZ') cron_book ====="
uv run python scripts/live/book_execute.py --execute
echo "===== done $(date -u '+%H:%M:%SZ') ====="
} >> logs/cron_book.log 2>&1
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
# Refresh dati certificati + avanza paper portfolio (per il dashboard). v2.0.0+.
export PATH="/home/adriano/.local/bin:$PATH"
cd /opt/docker/PythagorasGoal || exit 1
mkdir -p logs
{
echo "===== $(date -u '+%Y-%m-%dT%H:%M:%SZ') cron_daily ====="
uv run python scripts/analysis/rebuild_history.py --asset BTC ETH # BTC/ETH Deribit mainnet
uv run python scripts/analysis/fetch_hyperliquid.py # 52 alt Hyperliquid (certify)
uv run python scripts/research/fetch_dvol.py # DVOL (per ricerca opzioni)
uv run python scripts/live/paper_portfolio.py # avanza paper TP01+XS01
uv run python scripts/live/paper_prevday.py # forward-monitor lead prevday-breakout (PAPER, non deploy)
uv run python scripts/live/paper_statarb.py # forward-monitor lead STATARB-RESID ETH/BTC ortogonale (PAPER, non deploy)
# NB: l'esecuzione Deribit e' passata al BOOK (TP01+SKH01 nettati) via scripts/cron_book.sh a
# cadenza ORARIA (SKH01 e' a 230m: il daily mancherebbe gli ingressi). live_execute.py
# (TP01-only) NON va piu' eseguito qui, sennò i due farebbero a pugni sullo stesso strumento.
# --- COMBO cross-venue (PAPER): refresh ETF IB (GTAA) + avanza paper TP01+GTAA ---
docker compose up -d ib-gateway >/dev/null 2>&1 # gateway IB paper (idempotente)
for i in $(seq 1 25); do (echo > /dev/tcp/127.0.0.1/4002) >/dev/null 2>&1 && break; sleep 6; done
uv run --with ib_async python scripts/research/fetch_ib_equities.py --only SPY,QQQ,IWM,TLT,GLD,HYG # ETF GTAA freschi
uv run python scripts/live/paper_combo.py # avanza paper combo (forward-only)
echo "===== done $(date -u '+%H:%M:%SZ') ====="
} >> logs/cron_daily.log 2>&1
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# LOGGER FORWARD della vol term-structure Deribit — cadenza GIORNALIERA. v2.0.0+.
# Costruisce il dataset per un futuro calendar-vol (oggi NON backtestabile: storia per-scadenza non
# pubblica — vedi docs/diary/2026-06-26-vol-termstructure-feasibility.md). Append idempotente per
# giorno su data/raw/vol_term_<asset>.parquet. SOLO ricerca forward: NON tocca il book live ne' i
# dati certificati BTC/ETH; legge l'API pubblica Deribit (tokenless) e scrive un parquet dedicato.
export PATH="/home/adriano/.local/bin:$PATH"
cd /opt/docker/PythagorasGoal || exit 1
mkdir -p logs
{
echo "===== $(date -u '+%Y-%m-%dT%H:%M:%SZ') cron_vol_term ====="
uv run python scripts/research/log_vol_termstructure.py
echo "===== done $(date -u '+%H:%M:%SZ') ====="
} >> logs/cron_vol_term.log 2>&1
+162
View File
@@ -0,0 +1,162 @@
"""BOOK DERIBIT-ONLY LIVE EXECUTE — TP01 + SKH01 NETTATI in software su un solo conto Deribit mainnet.
Porta il conto reale al target NETTO per asset (vedi src/live/book.py): per ogni asset combina la
frazione long-flat di TP01 (peso 0.75) e il segno L/S di SKH01 (peso 0.25), e manda UN ordine con
segno (long/short/flip) per raggiungerlo. Poi assicura un disaster-SL on-book sulla posizione NETTA.
DOPPIO GATE DI SICUREZZA (entrambi necessari per inviare ordini reali):
1. config/live.json -> "execution_enabled": true (master switch, default false)
2. flag CLI --execute
Senza entrambi e' un DRY-RUN (stampa il piano, NON invia). Reconciliation dopo ogni ordine; log in
data/live/book_executions.jsonl.
⚠️ CADENZA: SKH01 decide su griglia 230m -> questo script va lanciato ogni ~230 minuti con la feed
fresca all'ultima barra chiusa (NON il cron giornaliero, che mancherebbe gli ingressi). Gli exit di
SKH sono SOFTWARE (latenza fino a fine barra 230m); solo il disaster-SL (-30%) e' on-book.
uv run python scripts/live/book_execute.py # DRY-RUN (piano, nessun ordine)
uv run python scripts/live/book_execute.py --execute # esegue SOLO se execution_enabled=true
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from src.live.book import book_report
from src.live.execution import DeribitTrader
from src.live.notifier import notify
CONFIG = PROJECT_ROOT / "config" / "live.json"
LOG_DIR = PROJECT_ROOT / "data" / "live"
LOG = LOG_DIR / "book_executions.jsonl"
def load_config() -> dict:
cfg = json.loads(CONFIG.read_text()) if CONFIG.exists() else {}
cfg.setdefault("execution_enabled", False)
cfg.setdefault("max_notional_per_asset_usd", 300.0)
cfg.setdefault("min_order_usd", 5.0)
cfg.setdefault("disaster_sl_pct", 0.30)
return cfg
def log_event(rec: dict):
LOG_DIR.mkdir(parents=True, exist_ok=True)
with open(LOG, "a") as f:
f.write(json.dumps(rec) + "\n")
def _run():
cfg = load_config()
want_execute = "--execute" in sys.argv[1:]
enabled = bool(cfg["execution_enabled"])
do_execute = want_execute and enabled
min_order = float(cfg["min_order_usd"])
sl_pct = float(cfg["disaster_sl_pct"])
r = book_report(live_feed=True) # target NETTO + conto/posizioni reali (feed SKH fresco)
equity = r["equity"]
print("=" * 88)
print(" BOOK DERIBIT LIVE EXECUTE — TP01(0.75)+SKH01(0.25) NETTATI — Deribit mainnet (USDC linear)")
print("=" * 88)
mode = ("ESECUZIONE REALE" if do_execute else
("ARMATO ma manca --execute" if enabled else "DRY-RUN (execution_enabled=false)"))
print(f" modo : {mode}")
print(f" gate : execution_enabled={enabled} | --execute={want_execute}")
print(f" conto reale : ${r['real_equity']:,.2f}" if r["real_equity"] else f" conto: {r['eq_basis']}")
print(f" sizing base : ${equity:,.2f} | cap/asset ${r['cap_per_asset']:.0f} | min ${min_order:.0f} | disaster-SL -{sl_pct*100:.0f}%")
print(f" ultima barra : {r['last_data']}\n")
if r.get("skh_error"): # SKH feed fallito -> book.py ha forzato flat IN SILENZIO
print(f" ⚠️ SKH FEED ERRORE (SKH forzato flat!): {r['skh_error']}")
notify("⚠️ BOOK — SKH feed fallito (sleeve forzato flat)", {"error": r["skh_error"]})
if not r["online"]:
print(" conto non leggibile (offline) -> stop, non eseguo a cieco.")
if do_execute:
notify("⚠️ BOOK LIVE — conto offline", {"nota": "salto l'esecuzione, non opero a cieco"})
return
if r.get("pos_error"): # ONLINE ma posizione IGNOTA (read fallita -> assunta flat)
print(f" 🛑 POSIZIONE NON LEGGIBILE -> NON eseguo a cieco: {r['pos_error']}")
if do_execute:
notify("🛑 BOOK LIVE — posizione non leggibile", {"error": r["pos_error"],
"nota": "salto l'esecuzione, non opero a cieco"})
return
if r.get("eq_fallback"): # equity reale non leggibile -> sizing su paper_cap
print(f" ⚠️ EQUITY FALLBACK (sizing su paper_cap, NON blocco): {r['eq_fallback']}")
if do_execute: # solo diagnostica: l'hard-cap $/asset limita il downside
notify("⚠️ BOOK LIVE — equity fallback (sizing su paper_cap)", {"nota": r["eq_fallback"]})
trader = DeribitTrader() if do_execute else None
actions = []
for a in r["assets"]:
asset, inst = a["asset"], a["instrument"]
net, cur, mark = a["net_target"], a["position_usd"], a["mark"]
sk = a["skh_state"]
sk_txt = "flat" if sk == "flat" else f"{sk['dir']}@{sk.get('entry')}"
order = a["order"]
if order is None:
act = "HOLD (a target)"
elif order.get("is_close"):
act = f"CLOSE ${cur:,.0f}"
elif order.get("needs_flip"):
act = f"FLIP -> ${net:,.0f}"
else:
act = f"{order['side'].upper()} ${order['delta']:+,.0f}"
print(f" {asset:<3} TP {a['tp_frac']:+.3f} · SKH {a['skh_sign']:+d}({sk_txt}) -> net ${net:+,.0f} "
f"| pos ${cur:+,.0f} -> {act}")
if do_execute and order is not None:
fills = trader.rebalance_signed(inst, net, mark, min_usd=min_order)
newpos = trader.position_usd(inst)
for f in fills:
print(f" -> {f.side.upper()} {f.filled:.4f} @ ${f.price or 0:,.1f} fee {f.fee_usdc:.5f} "
f"({'OK' if f.verified else 'NON VERIFICATO: ' + f.notes})")
log_event(dict(ts_utc=str(pd.Timestamp(r['last_data'])), asset=asset, action=act,
side=f.side, filled=f.filled, price=f.price, fee=f.fee_usdc,
verified=f.verified, notes=f.notes, net_target=net, pos_after=newpos,
tp_frac=a["tp_frac"], skh_sign=a["skh_sign"]))
det = dict(asset=asset, side=f.side, amount=round(f.filled, 4), price=round(f.price or 0, 1),
fee=round(f.fee_usdc, 5), net=round(net, 0), pos_after=round(newpos, 0))
notify(f"✅ BOOK {act}" if f.verified else "⚠️ BOOK ORDINE NON VERIFICATO",
det if f.verified else {**det, "notes": f.notes})
print(f" reconcile: pos ${newpos:,.0f}")
if do_execute:
ds = trader.ensure_disaster_sl(inst, sl_pct) # bracket su posizione NETTA (adatta long/short)
print(f" disaster-SL: {ds.get('state')}" + (f" @ ${ds['stop']:,.1f}" if ds.get("stop") else ""))
if ds.get("state") == "placed":
notify("🛡️ BOOK disaster-SL piazzato", {"asset": asset, "stop": round(ds.get("stop") or 0, 1),
"amount": round(ds.get("amount") or 0, 4)})
elif ds.get("state") == "place-failed":
notify("⚠️ BOOK disaster-SL FALLITO", {"asset": asset, "notes": ds.get("notes")})
actions.append(act)
print()
if not do_execute:
print(" => DRY-RUN: nessun ordine inviato." +
("" if enabled else " Per armare: config/live.json execution_enabled=true + --execute."))
elif all(x.startswith("HOLD") for x in actions):
print(" => Nessuna azione: conto gia' al target netto del book.")
else:
print(" => Esecuzione completata (vedi data/live/book_executions.jsonl).")
def main():
try:
_run()
except Exception as e:
notify("🛑 BOOK LIVE — ERRORE", {"error": f"{type(e).__name__}: {e}"})
raise
if __name__ == "__main__":
main()
+141
View File
@@ -0,0 +1,141 @@
"""TP01 LIVE EXECUTE — loop di esecuzione GATED su Deribit mainnet (USDC linear).
Porta il conto reale al target di TP01 (causale, dati certificati): per ogni asset calcola il notional
bersaglio = min(0.5 * frazione * equity, max_notional), e apre/riduce/chiude per raggiungerlo.
DOPPIO GATE DI SICUREZZA (entrambi necessari per inviare ordini reali):
1. config/live.json -> "execution_enabled": true (master switch, default false)
2. flag CLI --execute
Senza entrambi e' un DRY-RUN (stampa il piano, NON invia). Reconciliation dopo ogni ordine; log in
data/live/executions.jsonl. TP01 oggi e' FLAT -> target 0 -> nessuna azione finche' il segnale non gira.
uv run python scripts/live/live_execute.py # DRY-RUN (piano, nessun ordine)
uv run python scripts/live/live_execute.py --execute # esegue SOLO se execution_enabled=true
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pandas as pd
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from src.live.deribit import INSTRUMENT
from src.live.execution import DeribitTrader
from src.live.notifier import notify
from src.live.shadow import ASSETS, WEIGHT, shadow_report
CONFIG = PROJECT_ROOT / "config" / "live.json"
LOG_DIR = PROJECT_ROOT / "data" / "live"
LOG = LOG_DIR / "executions.jsonl"
def load_config() -> dict:
cfg = json.loads(CONFIG.read_text()) if CONFIG.exists() else {}
cfg.setdefault("execution_enabled", False)
cfg.setdefault("max_notional_per_asset_usd", 300.0)
cfg.setdefault("min_order_usd", 5.0)
cfg.setdefault("disaster_sl_pct", 0.30)
return cfg
def log_event(rec: dict):
LOG_DIR.mkdir(parents=True, exist_ok=True)
with open(LOG, "a") as f:
f.write(json.dumps(rec) + "\n")
def _run():
cfg = load_config()
want_execute = "--execute" in sys.argv[1:]
enabled = bool(cfg["execution_enabled"])
do_execute = want_execute and enabled
max_notional = float(cfg["max_notional_per_asset_usd"])
min_order = float(cfg["min_order_usd"])
sl_pct = float(cfg["disaster_sl_pct"])
r = shadow_report() # targets causali + conto/posizioni reali (online)
equity = r["equity"]
print("=" * 84)
print(" TP01 LIVE EXECUTE — Deribit mainnet (USDC linear)")
print("=" * 84)
mode = ("ESECUZIONE REALE" if do_execute else
("ARMATO ma manca --execute" if enabled else "DRY-RUN (execution_enabled=false)"))
print(f" modo : {mode}")
print(f" gate : execution_enabled={enabled} | --execute={want_execute}")
print(f" conto reale : ${r['real_equity']:,.2f}" if r["real_equity"] else f" conto: {r['eq_basis']}")
print(f" sizing base : ${equity:,.2f} | cap/asset ${max_notional:.0f} | min ${min_order:.0f} | disaster-SL -{sl_pct*100:.0f}%")
print(f" ultima barra : {r['last_data']}\n")
if not r["online"]:
print(" conto non leggibile (offline) -> stop, non eseguo a cieco.")
if do_execute:
notify("⚠️ TP01 LIVE — conto offline", {"nota": "salto l'esecuzione, non opero a cieco"})
return
trader = DeribitTrader() if do_execute else None
actions = []
for a in r["assets"]:
asset = a["asset"]; frac = a["target"]; mark = a["mark"]; cur = a["position_usd"]
tgt = min(WEIGHT * frac * equity, max_notional) if frac > 0 else 0.0
delta = tgt - cur
if abs(delta) < min_order:
act = "HOLD (a target)"
elif tgt < 1.0 and cur > 1.0:
act = f"CLOSE ${cur:,.0f}"
elif delta > 0:
act = f"BUY ${delta:,.0f}"
else:
act = f"REDUCE ${-delta:,.0f}"
print(f" {asset:<3} target {frac:+.3f}x -> ${tgt:,.0f} | pos ${cur:,.0f} | delta ${delta:+,.0f} -> {act}")
if do_execute:
if not act.startswith("HOLD"):
fills = trader.rebalance_to(INSTRUMENT[asset], tgt, mark, min_usd=min_order)
newpos = trader.position_usd(INSTRUMENT[asset])
for f in fills:
print(f" -> {f.side.upper()} {f.filled:.4f} @ ${f.price:,.1f} fee {f.fee_usdc:.5f} "
f"({'OK' if f.verified else 'NON VERIFICATO: ' + f.notes})")
log_event(dict(ts_utc=str(pd.Timestamp(r['last_data'])), asset=asset, action=act,
side=f.side, filled=f.filled, price=f.price, fee=f.fee_usdc,
verified=f.verified, notes=f.notes, pos_after=newpos))
det = dict(asset=asset, side=f.side, amount=round(f.filled, 4),
price=round(f.price or 0, 1), fee=round(f.fee_usdc, 5), pos_after=round(newpos, 0))
if f.verified:
notify(f"✅ TP01 {act}", det)
else:
notify("⚠️ TP01 ORDINE NON VERIFICATO", {**det, "notes": f.notes})
print(f" reconcile: pos ${newpos:,.0f}")
ds = trader.ensure_disaster_sl(INSTRUMENT[asset], sl_pct) # bracket: piazza se long, pulisce se flat
print(f" disaster-SL: {ds.get('state')}" + (f" @ ${ds['stop']:,.1f}" if ds.get("stop") else ""))
if ds.get("state") == "placed":
notify("🛡️ TP01 disaster-SL piazzato", {"asset": asset, "stop": round(ds.get("stop") or 0, 1),
"amount": round(ds.get("amount") or 0, 4)})
elif ds.get("state") == "place-failed":
notify("⚠️ TP01 disaster-SL FALLITO", {"asset": asset, "notes": ds.get("notes")})
actions.append(act)
print()
if not do_execute:
print(" => DRY-RUN: nessun ordine inviato." +
("" if enabled else " Per armare: config/live.json execution_enabled=true + --execute."))
elif all(x.startswith("HOLD") for x in actions):
print(" => Nessuna azione: conto gia' al target di TP01 (oggi flat).")
else:
print(" => Esecuzione completata (vedi data/live/executions.jsonl).")
def main():
try:
_run()
except Exception as e:
notify("🛑 TP01 LIVE — ERRORE", {"error": f"{type(e).__name__}: {e}"})
raise
if __name__ == "__main__":
main()
+78
View File
@@ -0,0 +1,78 @@
"""TP01 LIVE — SHADOW MODE (Deribit mainnet, SOLA LETTURA, nessun ordine inviato).
Valida l'esecuzione di TP01 a RISCHIO ZERO: gira il loop live completo contro dati/conto/posizioni
REALI del mainnet, calcola i target causali (stesso codice del backtest/paper), costruisce gli ordini
di ribilancio esatti e li STAMPA invece di inviarli. Confronta i target col paper trader (parita').
Perche' non testnet: il testnet Cerbero/Deribit e' la causa del reset v2.0.0 (feed farlocco). La
validazione a rischio zero qui e' "shadow su mainnet reale in sola lettura"; il fill (slippage/fee)
si valida solo col micro-test mainnet a size minima, in un passo successivo.
Logica condivisa con la dashboard in src/live/shadow.py (un solo codice, niente drift).
uv run python scripts/live/live_trend.py # shadow su mainnet reale
uv run python scripts/live/live_trend.py --equity 2000 # forza la base di sizing
uv run python scripts/live/live_trend.py --no-net # offline: solo matematica + parita'
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from src.live.deribit import notional_to_amount
from src.live.shadow import shadow_report
def main():
argv = sys.argv[1:]
offline = "--no-net" in argv
equity_override = float(argv[argv.index("--equity") + 1]) if "--equity" in argv else None
r = shadow_report(offline=offline, equity_override=equity_override)
print("=" * 84)
print(" TP01 LIVE — SHADOW MODE (Deribit mainnet, SOLA LETTURA — NESSUN ORDINE INVIATO)")
print("=" * 84)
real_eq = r["real_equity"]
conto = f"${real_eq:,.2f}" if real_eq else r["eq_basis"]
print(f" ultima barra 1d chiusa : {r['last_data']}")
print(f" rete : {'mainnet via Cerbero MCP' if r['online'] else 'OFFLINE / fallback close'}")
print(f" prezzi mark : " + " | ".join(f"{a['asset']} ${a['mark']:,.1f} ({a['mark_src']})" for a in r["assets"]))
print(f" conto reale : {conto}")
print(f" posizioni reali : " + ", ".join(f"{a['asset']} ${a['position_usd']:,.0f}" for a in r["assets"]) + f" ({r['pos_src']})")
print(f" base di sizing : ${r['equity']:,.2f} [{r['eq_basis']}]")
print("\n PER ASSET (target causale @ ultima barra chiusa):")
for a in r["assets"]:
state = "FLAT" if abs(a["target"]) < 1e-9 else ("LONG" if a["target"] > 0 else "SHORT")
line = (f" {a['asset']:<3} {state:<5} target {a['target']:+.3f}x -> notional ${a['target_notional']:,.0f}"
f" (pos reale ${a['position_usd']:,.0f})")
o = a["order"]
if o:
print(line + f"\n -> ORDINE: {o['side'].upper()} {o['amount']:.0f} {a['instrument']} "
f"(market{', reduce_only' if o['reduce_only'] else ''}, delta ${o['delta_notional']:,.0f})")
else:
print(line + " -> nessun ordine (gia' a target / sotto-soglia)")
print("\n PARITA' vs paper trader (target = current_target):")
if all(a["paper"] is None for a in r["assets"]):
print(" (paper non inizializzato: avvia scripts/live/paper_trend.py)")
else:
for a in r["assets"]:
print(f" {a['asset']}: paper {a['paper']:+.3f}x shadow {a['target']:+.3f}x -> {'OK' if a['parity'] else 'DIFFERISCE'}")
if not r["paper_aligned"]:
print(" NB paper non all'ultima barra -> avanzalo se i target differiscono")
print("\n VERIFICA costruttore ordini (quantizzazione step/minimo):")
for inst, samples in (("BTC-PERPETUAL", [1000, 1005, 7, 250.4]), ("ETH-PERPETUAL", [1000, 0.4, 33.7])):
got = ", ".join(f"${s}->{notional_to_amount(inst, s):.0f}" for s in samples)
print(f" {inst}: {got}")
print("\n => NESSUN ORDINE INVIATO (shadow). " +
(f"{len(r['orders'])} ordine/i costruito/i sopra." if r["orders"] else "Target flat: 0 ordini."))
if __name__ == "__main__":
main()
+92
View File
@@ -0,0 +1,92 @@
"""MICRO-TEST esecuzione su Deribit mainnet — round-trip minimo su BTC_USDC-PERPETUAL, apri+chiudi.
Conto reale = USDC -> strumento ESEGUIBILE = perp LINEARE `BTC_USDC-PERPETUAL` (amount in BTC, step
0.0001 ~ $6). Valida il percorso ordine->fill->reconciliation->chiusura con soldi VERI a size MINIMA
(~0x leva, decoupled dal segnale): test della plumbing, non della strategia. Usa open()/close()
verificati di src/live/execution.py (logica entrata/uscita presa da Old).
Sicurezze: default DRY-RUN. Pre-flight ABORT se posizione preesistente. La chiusura (reduce_only,
sempre permessa) flatta comunque dopo l'apertura; verifica finale di FLAT (alert se no).
uv run python scripts/live/microtest.py # DRY-RUN: nessun ordine inviato
uv run python scripts/live/microtest.py --live # invia il round-trip REALE
"""
from __future__ import annotations
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
from src.live.execution import FLAT_USD, MAX_AMOUNT, DeribitTrader
INSTRUMENT = "BTC_USDC-PERPETUAL"
AMOUNT = 0.0001 # base-coin (BTC) = 1 contratto minimo (~$6 a $63k)
def main():
live = "--live" in sys.argv[1:]
t = DeribitTrader()
print("=" * 82)
print(" MICRO-TEST esecuzione TP01 — round-trip 0.0001 BTC su BTC_USDC-PERPETUAL (leva ~0x)")
print("=" * 82)
try:
equity = float(t.account_summary("USDC").get("equity") or 0)
mark = t.mark_price(INSTRUMENT)
pos0 = t.position_usd(INSTRUMENT)
except Exception as e:
print(f" PRE-FLIGHT FALLITO (read): {type(e).__name__}: {e}\n -> non procedo.")
return
notional = AMOUNT * mark
print(f" conto USDC equity : ${equity:,.2f}")
print(f" mark {INSTRUMENT} : ${mark:,.1f}")
print(f" posizione attuale : ${pos0:,.2f} notional (dev'essere 0)")
print(f" apertura : BUY {AMOUNT:.4f} BTC market (~${notional:.2f}, leva {notional/equity:.4f}x)")
print(f" chiusura : SELL {AMOUNT:.4f} BTC market reduce_only")
print(f" guardrail: solo {INSTRUMENT}, cap apertura {MAX_AMOUNT[INSTRUMENT]} BTC")
if abs(pos0) >= FLAT_USD:
print(f"\n ABORT: posizione preesistente (${pos0:,.2f}). Non la tocco. Chiudila a mano e ripeti.")
return
if not live:
print("\n DRY-RUN: nessun ordine inviato. Rilancia con --live per il round-trip reale.")
return
# ---- LIVE: apertura ----
print("\n >>> LIVE: APERTURA ...")
fo = t.open(INSTRUMENT, "buy", AMOUNT, label="tp01-microtest-open")
if not fo.verified:
print(f" apertura NON verificata: {fo.notes}")
# safety: assicura comunque il flat
fc = t.close(INSTRUMENT, label="tp01-microtest-safeclose")
print(f" safe-close: {'eseguita' if fc else 'gia flat'}; posizione ${t.position_usd(INSTRUMENT):,.2f}")
return
print(f" FILL: {fo.filled:.4f} BTC @ ${fo.price:,.1f} fee {fo.fee_usdc:.6f} USDC (state={fo.state})")
# ---- LIVE: chiusura (reduce_only) ----
print(" >>> LIVE: CHIUSURA (reduce_only) ...")
fc = t.close(INSTRUMENT, label="tp01-microtest-close")
pos_end = t.position_usd(INSTRUMENT)
if fc:
print(f" FILL: {fc.filled:.4f} BTC @ ${fc.price:,.1f} fee {fc.fee_usdc:.6f} USDC (state={fc.state})")
print(f" posizione finale: ${pos_end:,.2f} notional")
# ---- report ----
print("\n " + "-" * 62)
if abs(pos_end) < FLAT_USD:
print(" ✓ ROUND-TRIP COMPLETO — posizione tornata a FLAT.")
else:
print(f" ⚠️ posizione NON flat (${pos_end:,.2f}) — INTERVENTO MANUALE: chiudi a mano.")
if fo.verified and fc:
tot_fee = fo.fee_usdc + fc.fee_usdc
pnl = AMOUNT * ((fc.price or 0) - (fo.price or 0))
print(f" entry ${fo.price:,.1f} -> exit ${fc.price:,.1f} | fee {tot_fee:.6f} USDC | "
f"pnl lordo {pnl:+.4f} | netto {pnl - tot_fee:+.4f} USDC")
print(" Validato: invio ordine reale, fill, fee reali, reconciliation, ritorno a flat.")
if __name__ == "__main__":
main()
+117
View File
@@ -0,0 +1,117 @@
"""PAPER COMBO — forward-only del combo cross-venue TP01 (Deribit) + GTAA (IB), NUDO vs PROTETTO.
Le due gambe eseguibili a basso capitale (XS01/VRP01 STAT-MODE esclusi), scorrelate (corr ~0.21) ->
blend Sharpe ~1.5, DD dimezzato. Traccia FORWARD-ONLY DUE versioni in parallelo:
* NUDO = blend 50/50 TP01+GTAA
* PROTETTO = stesso blend + GUARDIA-DRAWDOWN -4% (de-risk a 0.4x quando il DD da picco supera -4%,
ri-rischia a -1.6%). Backtest: MaxDD 8.4%->5.8%, 2022 -4.4%->-1.8%, Sharpe 1.48->1.38
(diario 2026-06-23-tail-hedge-lab). Le opzioni NON aiutano il grind del 2022 -> escluse.
Crypto compoundato sul grid giorni-di-borsa. NESSUNA esecuzione reale. Mostra posizioni azionabili.
uv run python scripts/live/paper_combo.py [--status|--reset]
"""
from __future__ import annotations
import sys, json
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np, pandas as pd
from src.portfolio.sleeves import _tp01_returns, _tp01_positions
from src.portfolio.gtaa import gtaa_returns, gtaa_weights
STATE_DIR = PROJECT_ROOT / "data" / "paper_combo"
STATE = STATE_DIR / "state.json"
EQ = STATE_DIR / "equity.csv"
INITIAL = 2000.0
W_CRYPTO = 0.5
DD_TRIGGER = 0.04 # guardia-drawdown della versione PROTETTA
def combo_daily(wc: float = W_CRYPTO) -> pd.Series:
tp = _tp01_returns()
if tp.index.tz is None:
tp.index = tp.index.tz_localize("UTC")
eq = gtaa_returns().dropna()
grid = eq.index[eq.index >= tp.index[0]]
cum = (1.0 + tp).cumprod()
tpg = (cum.reindex(cum.index.union(grid)).ffill().reindex(grid)).pct_change()
J = pd.concat({"c": tpg, "e": eq.reindex(grid)}, axis=1).dropna()
return (wc * J["c"] + (1 - wc) * J["e"]).dropna()
def apply_dd_guard(r: pd.Series, trigger: float = DD_TRIGGER) -> pd.Series:
"""De-risk a 0.4x quando il DD da picco > trigger; ri-rischia a 1.0x quando < 0.4*trigger."""
rv = r.values; n = len(rv); eq = np.cumprod(1 + rv); pk = np.maximum.accumulate(eq)
expo = np.ones(n); on = True
for i in range(1, n):
ddi = (pk[i - 1] - eq[i - 1]) / pk[i - 1] if pk[i - 1] > 0 else 0.0
if ddi > trigger: on = False
if ddi < trigger * 0.4: on = True
expo[i] = 1.0 if on else 0.4
return pd.Series(expo * rv, index=r.index)
def both_daily():
naked = combo_daily()
return naked, apply_dd_guard(naked)
def load():
return json.loads(STATE.read_text()) if STATE.exists() else None
def save(st):
STATE_DIR.mkdir(parents=True, exist_ok=True)
STATE.write_text(json.dumps(st, indent=2))
def advance():
naked, guard = both_daily()
st = load()
if st is None or "equity_g" not in st: # init (o migrazione a doppia versione)
last = str(naked.index[-1])
st = dict(start=last, last=last, initial=INITIAL, n_days=0, w_crypto=W_CRYPTO, dd_trigger=DD_TRIGGER,
equity=INITIAL, peak=INITIAL, max_dd=0.0,
equity_g=INITIAL, peak_g=INITIAL, max_dd_g=0.0)
save(st); EQ.write_text("date,nudo,protetto\n" + f"{last},{INITIAL},{INITIAL}\n")
return st
last = pd.Timestamp(st["last"])
nn = naked[naked.index > last]; gg = guard[guard.index > last]
if len(nn):
e = st["equity"]; pk = st["peak"]; dd = st["max_dd"]
eg = st["equity_g"]; pkg = st["peak_g"]; ddg = st["max_dd_g"]; lines = []
for d in nn.index:
e *= (1 + float(nn[d])); pk = max(pk, e); dd = max(dd, (pk - e) / pk if pk > 0 else 0)
eg *= (1 + float(gg[d])); pkg = max(pkg, eg); ddg = max(ddg, (pkg - eg) / pkg if pkg > 0 else 0)
lines.append(f"{d},{e:.4f},{eg:.4f}")
st.update(equity=e, peak=pk, max_dd=dd, equity_g=eg, peak_g=pkg, max_dd_g=ddg,
last=str(nn.index[-1]), n_days=st["n_days"] + len(nn))
save(st)
with open(EQ, "a") as f:
f.write("\n".join(lines) + "\n")
return st
def main():
a = sys.argv[1:]
if "--reset" in a:
for f in (STATE, EQ):
f.unlink(missing_ok=True)
print("paper combo azzerato.")
st = load() if "--status" in a else advance()
if st is None or "equity_g" not in st:
st = advance()
days = (pd.Timestamp(st["last"]) - pd.Timestamp(st["start"])).days
rn = st["equity"] / st["initial"] - 1; rg = st["equity_g"] / st["initial"] - 1
gw = gtaa_weights(); asof = gw.pop("_asof", "?"); cash = gw.pop("_cash", None)
print("PAPER COMBO — TP01 (Deribit) + GTAA (IB), forward-only, blend 50/50")
print(f" start {st['start'][:10]} -> last {st['last'][:10]} ({days}g, {st['n_days']} barre)")
print(f" NUDO : eq {st['equity']:.2f} ret {rn*100:+.2f}% maxDD {st['max_dd']*100:.1f}%")
print(f" PROTETTO : eq {st['equity_g']:.2f} ret {rg*100:+.2f}% maxDD {st['max_dd_g']*100:.1f}% (guardia-DD -{st.get('dd_trigger',DD_TRIGGER)*100:.0f}%)")
print(f" --- POSIZIONI AZIONABILI ---")
print(f" TP01 (Deribit): {_tp01_positions()}")
print(f" GTAA (IB, asof {asof}): " + ", ".join(f"{k} {v:.0%}" for k, v in gw.items() if v) + f" | cash {cash:.0%}")
if __name__ == "__main__":
main()
+86
View File
@@ -0,0 +1,86 @@
"""PAPER PORTFOLIO — forward-only del portafoglio attivo (TP01 + XS01), simulato.
Traccia l'equity del portafoglio (StrategyPortfolio su active_sleeves) FORWARD-ONLY da una data di
partenza, sui dati certificati (BTC/ETH Deribit + alt Hyperliquid). Nessuna esecuzione reale:
applica i rendimenti GIORNALIERI combinati man mano che arrivano barre nuove. Stato persistente.
Il dashboard (src/live/dashboard.py) legge questo stato + ricalcola il backtest a colpo d'occhio.
uv run python scripts/live/paper_portfolio.py # avanza (init al 1o run)
uv run python scripts/live/paper_portfolio.py --status # solo stato
uv run python scripts/live/paper_portfolio.py --reset # azzera (riparte da ora)
"""
from __future__ import annotations
import sys, json
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(PROJECT_ROOT))
import numpy as np, pandas as pd
from src.portfolio.portfolio import StrategyPortfolio
from src.portfolio.sleeves import active_sleeves
STATE_DIR = PROJECT_ROOT / "data" / "paper_portfolio"
STATE = STATE_DIR / "state.json"
EQ = STATE_DIR / "equity.csv"
INITIAL = 2000.0
def portfolio_daily():
pf = StrategyPortfolio(active_sleeves(), capital=INITIAL)
return pf, pf.combined_daily()
def load():
return json.loads(STATE.read_text()) if STATE.exists() else None
def save(st):
STATE_DIR.mkdir(parents=True, exist_ok=True)
STATE.write_text(json.dumps(st, indent=2))
def advance():
pf, r = portfolio_daily()
st = load()
if st is None: # init: forward-only, parte dall'ultima barra
last = str(r.index[-1])
st = dict(start=last, last=last, equity=INITIAL, initial=INITIAL,
peak=INITIAL, max_dd=0.0, n_days=0)
save(st)
STATE_DIR.mkdir(parents=True, exist_ok=True)
EQ.write_text("date,equity\n" + f"{last},{INITIAL}\n")
return st
last = pd.Timestamp(st["last"])
new = r[r.index > last]
if len(new):
eq = st["equity"]; peak = st["peak"]; dd = st["max_dd"]
lines = []
for d, ret in new.items():
eq *= (1.0 + float(ret)); peak = max(peak, eq); dd = max(dd, (peak - eq) / peak if peak > 0 else 0)
lines.append(f"{d},{eq:.4f}")
st.update(equity=eq, last=str(new.index[-1]), peak=peak, max_dd=dd, n_days=st["n_days"] + len(new))
save(st)
with open(EQ, "a") as f:
f.write("\n".join(lines) + "\n")
return st
def main():
a = sys.argv[1:]
if "--reset" in a:
for f in (STATE, EQ):
f.unlink(missing_ok=True)
print("paper portfolio azzerato.")
st = load() if "--status" in a else advance()
if st is None:
st = advance()
pf, _ = portfolio_daily()
days = (pd.Timestamp(st["last"]) - pd.Timestamp(st["start"])).days
ret = st["equity"] / st["initial"] - 1
print(f"PAPER PORTFOLIO (TP01+XS01) — forward-only")
print(f" start {st['start'][:10]} -> last {st['last'][:10]} ({days}g, {st['n_days']} barre)")
print(f" equity {st['equity']:.2f} (start {st['initial']:.0f}) ret {ret*100:+.2f}% maxDD {st['max_dd']*100:.1f}%")
print(f" posizioni correnti: {pf.current_positions()}")
if __name__ == "__main__":
main()

Some files were not shown because too many files have changed in this diff Show More