Crash ETH 2026-06-05: SH01 ETH −15.6% su un trade (exit solo a orizzonte, nessuna
protezione). Ricerca con harness dedicato sh01_exit_lab (cache walk-forward, engine
fill gap-aware worse(livello,open), parity esatta con explore_lab, train<=2023-11-01):
ATR intrabar/close-confirm, %, chandelier, breakeven, giveback, loser-timestop,
disaster-cap close+intrabar, swing, vol-regime — NESSUNA passa il gate (ogni stop
stretto rompe BTC, ogni stop largo non tocca la coda ETH; nei crash il fill e' al gap).
Mitigazione: peso famiglia SHAPE 11.8%->5.9% in PORT06 (FULL 6.47->6.43 DD 4.10->3.96,
OOS 8.82->8.58 DD 1.30->1.36) — la prossima coda impatta il conto per meta'.
Regression-lock test aggiornato. Diario: docs/diary/2026-06-05-sh01-sl-research.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Param sl_confirm_atr (None = comportamento storico) in FadeStrategy.backtest,
MR01.backtest e StrategyWorker.tick; attivo live a 0.5 sulle 6 fade in _defs.py.
TP intrabar al livello e max_bars invariati; in modalita' confirm il TP ha
priorita' nel bar. Ricerca exit-lab (34 agenti, 3 lenti avversariali + tail
audit): gli stop intrabar da wick sono falsi negativi per le fade. PORT06
canonico: FULL Sharpe 6.47->7.84 DD 4.10->2.60, OOS 8.82->10.06 DD 1.30->1.15.
NB path grezzo non filtrato: ret esplode ma DD per-sleeve sale — la riduzione
DD vive nel config live (trend_max+hurst) + diversificazione, come misurato.
5 test nuovi (59 verdi).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
23 famiglie esplorate (harness condiviso exit_lab, train/OOS embargo nov-2023,
tutto lo storico 1h 2018-2026) + 10 verifiche avversariali + test PORT06.
'Cavalcare il prezzo' non esiste (4a conferma: oltre il TP=media non c'e' coda).
Scoperta: lo SL intrabar fisso e' il distruttore di valore n.1 delle fade
(stop da wick = falsi negativi). Forma robusta: SL solo su CHIUSURA oltre
sl0±0.5·ATR14 — PORT06 FULL Sharpe 6.47→7.84 DD 4.10→2.60, OOS 8.82→10.06.
Collaterali: bias gap-through dell'engine sugli stop stretti; ramo -2% del
worker morto con sl=0. Diario: docs/diary/2026-06-04-exit-lab.md
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Test onesto scripts/analysis/partial_tp_ladder.py: stessi segnali, engine
intrabar fade_base, fee identiche. Il ladder compra win-rate/DD pagando i
winner migliori — stesso profilo del vol-target gia' scartato.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All'apertura reale il worker piazza un limit reduce-only al TP della strategia
(quota del SOLO worker, prezzo quantizzato al tick); alla chiusura sim cancella
il resting, riconcilia i fill (anche parziali) via get_trade_history per
order_id e chiude a market solo il residuo. real_tp_order_id persistito
(resume-safe). SL resta market-on-poll (deliberato: trigger Deribit = nuovo
order_id al trigger, fill non verificabile; e il rimbalzo sul SL lavora a
favore). Smoke testnet 2 scenari OK (resting+cancel / fill immediato).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- telegram_notifier: eventi REAL_EXEC_LIVE (primo ordine reale verificato per worker)
e REAL_OPEN_FAIL (apertura reale non verificata)
- StrategyWorker: notifica una-tantum al primo REAL_OPEN verificato + ogni FAIL;
flag real_first_notified persistito
- CLAUDE.md: documentato lo shadow-execution (ExecutionClient, lineari USDC,
verifica sul trade, fee reali, config, alert, smoke)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il fallback a Deribit mainnet per i dati introduceva una DIVERGENZA paper<->esecuzione: il paper
simulava su prezzi mainnet ma gli ordini (place_order via Cerbero) andrebbero su TESTNET, i cui
prezzi/liquidità divergono ~9%. Un paper trader deve usare la STESSA fonte/venue dove gli ordini
verrebbero eseguiti, altrimenti non predice il comportamento reale. Durante un outage testnet il
runner si mette in pausa (corretto: senza il venue non si eseguirebbe comunque). Rimosso
get_historical_mainnet e il wiring nel runner.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deribit testnet (test.deribit.com) va giu' periodicamente (502) e Cerbero lo rilancia ->
il runner si bloccava senza dati. Aggiunto CerberoClient.get_historical_mainnet (Deribit MAINNET
public, NO-AUTH, paginato sotto il cap ~5000 candele/chiamata) e fallback nel runner: try Cerbero
-> on fail/empty usa mainnet. Prezzi REALI (meglio del testnet farlocco per il paper). Verificato
durante l'outage: tutti gli 8 strumenti (BTC/ETH + alt _USDC) coperti su mainnet. Log una-tantum
all'attivazione/disattivazione del fallback.
Caveat: testnet e mainnet hanno prezzi diversi (~9%) -> al primo switch le posizioni aperte su
prezzi testnet vanno resettate (transizione pulita).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Traccia lo stop-rate delle fade (MR01/MR02/MR07) PRIMA/DOPO l'attivazione del loss-guard
(2026-06-02 14:34 UTC). Verdetto automatico quando il campione DOPO >= 30 trade. Conferma gia'
visibile: stop-rate live PRIMA 42% (n=36) == backtest 42.1%. Gira host-side (cron), no rebuild.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
File VERSION (semver, cotto nell'immagine) letto da src/version.py. Compare nelle notifiche trade
(telegram_notifier) e nel report orario -> sai quale codice ha generato quale msg.
scripts/bump_version.py incrementa la patch; scripts/deploy.sh = bump+commit+rebuild (versione
aumenta ad OGNI deploy). v1.0.0 = primo release versionato (include hurst loss-guard).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sistema anti-perdite: skip fade in regime persistente (hurst>=0.55). Dimezza il DD del PORT06
(FULL 4.10%->2.39%, Sharpe 6.62->6.76, OOS 8.89->9.15). Solo l'Hurst supera il gate (ADX/vol-expansion
falliscono). Attivo live sulle 6 fade. Diagnostici + workflow 11 agenti + diario.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Attivazione live: hurst_max=0.55 nei params delle 6 fade (MR01/MR02/MR07 x BTC/ETH) in _defs.py.
hurst_skip_mask step=6 (5.9s/fade su 10560 barre live, ~35s per le 6 -> OK su poll 60s, e coincide
con la cache di validazione). Calcolato dalle SOLE close -> nessun feed esterno, il worker lo computa
inline.
NB live/backtest: il filtro agisce solo sul path LIVE (spec.params); il backtest canonico
(build_everything/regression-lock, via risk_management) NON e' filtrato -> il live FARA' meglio del
backtest sul DD (FULL 4.10%->2.39% atteso). Divergenza intenzionale (miglioramento). Backtest-parity
aggiornabile in seguito. Suite: 54 passed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GOAL: limitare le perdite delle fade in regime sfavorevole. Diagnosi (3022 trade): le perdite/stop
si concentrano nel regime PERSISTENTE (hurst>0.55: stop-rate 43% vs 21% anti-persistente), NON in
bassa vol (low-vol e' net positivo). Ricerca web + workflow 11 agenti: l'UNICO meccanismo che riduce
DD senza uccidere l'edge e' il filtro Hurst (ADX, vol-expansion, time-stop, ER, vol-target falliscono
il gate FR01). Test esterni ADX/vol-expansion NON si replicano su queste fade crypto.
TEST DECISIVO PORT06 (gate FR01) SUPERATO: Hurst-skip h<0.55 sulle 6 fade ->
FULL Sharpe 6.62->6.76, FULL DD 4.10%->2.39% (quasi dimezzato), OOS Sharpe 8.89->9.15.
Migliora il portafoglio (a differenza di FR01 che diluiva).
Implementazione: hurst_skip_mask in fade_base.py (rolling-Hurst causale dalle SOLE close -> nessun
feed dati esterno, deployabile inline dal worker) + param hurst_max (default None=off) in
MR01/MR02/MR07. Test: test_hurst_lossguard.py. Default off -> zero impatto su backtest/parita'/live
finche' non attivato.
FIX collaterale: regime_fetcher/regime_lab scrivevano DVOL/funding/feature in data/raw/ ->
inquinavano la discovery asset del backtest (rompeva il regression-lock PORT06). Spostati in
data/regime/ (gitignored). Suite: 54 passed (lock incluso).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diagnosi (3022 trade fade 2021+): perdite/stop concentrati in regime PERSISTENTE (hurst>0.55,
SL-rate 43% vs 21% anti-persistente), NON in bassa vol (low-vol e' net positivo). Ricerca web
conferma: filtro Hurst<0.45 / ADX<20 / vol-expansion ratio>1.5 (prevenne 72% perdite maggiori).
Workflow 11 agenti testa i meccanismi sulle fade reali.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributo marginale al MASTER (equal-weight): OOS Sharpe 8.89->8.72 (diluisce),
OOS ret +175%->+156%. Corr FR01 vs MASTER +0.18/+0.23. Sharpe daily-return standalone
~1.85 (non il 3.73 per-trade) -> troppo basso per un PORT06 a 8.89. Ridondanza robusta.
ESITO: search a 100 agenti rigoroso, ma nessuna strategia migliora PORT06. Deploy abbandonato,
resta record di ricerca sul branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Script standalone che legge lo stato persistito del paper trader a portafoglio
(data/portfolio_paper/*/ + data/portfolios/PORT06/status.json) e invia su
Telegram: (1) trade CHIUSI positivi/negativi NETTO fee con breakdown per motivo
e PnL; (2) tabella trade IN CORSO (posizioni aperte, single e pairs a 2 gambe);
(3) PnL realizzato totale + equity mark-to-market (con non realizzato).
Carica .env da solo (cron non eredita l'env del container), legge file
world-readable scritti dal container, non tocca lo stato del trader. Riusa
send_telegram di telegram_notifier.
Schedulazione: crontab host orario (minuto 0):
0 * * * * uv run --project /opt/docker/PythagorasGoal python \
scripts/portfolios/hourly_report.py
(uv run --project + path assoluto: nessun cd necessario.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bug di wiring: runner.py avvolgeva lo sleeve SH01 nel MLWorkerWrapper legacy
di multi_runner, che usa SignalEngine (famiglia squeeze ML01 SCARTATA), apre
con Signal nudo ed esce a hold_bars=3 con tick() propria. Risultato: lo sleeve
"SH01" del portafoglio live NON eseguiva SH01_shape_ml (generate_signals mai
chiamata) e il fix horizon-exit era in un ramo morto -> SH01 continuava a
chiudere a hold_limit/3.
Fix: SH01 (kind="ml") gira come StrategyWorker normale. SH01_shape_ml.
generate_signals fa il walk-forward internamente ad ogni tick ed emette
metadata.max_bars=H=12 -> exit via StrategyWorker.tick (orizzonte H, fix
applicato). Rimosso l'import/uso di MLWorkerWrapper e il blocco train esterno.
ml_wf_entries ha train_min=4000 (>=4000 barre 1h per produrre segnali):
aggiunto _ML_LOOKBACK_DAYS=365 cosi gli asset di sleeve ml fetchano >=365g
(~8760 barre), senza dipendere dal fetch 440g di TSM01/ROT02. generate_signals
su 365g: 0,17-0,24s (logit) -> trascurabile sul poll 60s.
Test: test_build_ml_sh01_is_plain_strategyworker (StrategyWorker + strategy
SH01_shape_ml + niente engine squeeze). Suite: 51 passed.
Stato live: SH01 BTC/ETH flat -> contatori resettati (capitale preservato),
trade squeeze archiviati. Rebuild+recreate: 14 worker RESUME puliti, healthy.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Due correzioni emerse da close live con win=True ma pnl<0.
1) Metrica win lorda -> netta. _close_position contava is_win=trade_return>0
(lordo), gonfiando l'accuracy: un take-profit colpito con mossa < fee RT
risultava "win" pur perdendo. 51 close live: 39 win (76,5%) -> 13 falsi win
-> accuracy netta reale 52,9%. Fix: is_win = net > 0. Capitale/PnL erano
già corretti (netti). Contatori persistiti riconciliati a parte (MR01/DIP01
BTC 7->1).
2) Filtro edge-minimo min_tp_frac. I 13 falsi win erano tutti MR01/DIP01 BTC in
regime piatto: TP (la media) entro il costo round-trip -> perdenti garantiti.
Aggiunto param min_tp_frac (default 0.0=off) a tutte e 4 le fade (MR01 banda,
MR02 midpoint, MR07 ATR, DIP01): salta i segnali col TP entro la soglia.
Non si "allarga" il TP (rischierebbe di perdere di piu'): si evita la trade.
Cablato live a 0.0015 (1,5x fee) in _defs.py.
Validazione backtest BTC+ETH 1h: neutro su tutte le fade (0-1 trade rimossi,
pnl invariato o +leggero su DIP01). I micro-scalp sotto-fee non esistono nello
storico -> artefatto del regime attuale. Filtro puro-upside.
Test: test_win_net_of_fees.py, test_min_tp_frac.py (monotonia + gap > soglia +
default-off invariato). Suite: 50 passed.
NB deploy: il sorgente e' COPY nell'immagine, non montato -> serve
`docker compose up -d --build`, non un semplice restart (vale anche per il fix
SH01 horizon-exit, andato live solo con questo rebuild). Volume ./data persiste,
14 worker in RESUME puliti.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lo StrategyWorker onorava max_bars (orizzonte del Signal) solo nel ramo
`if self.tp and self.sl`. SH01 (shape-ML, H=12) non porta TP/SL, quindi
cadeva sul fallback legacy hold_bars=3 e chiudeva a 3 barre invece delle
12 validate: l'edge (asimmetria sull'orizzonte, non frequenza) non aveva
tempo di realizzarsi -> accuratezza live falsata (33%), tutti exit
"hold_limit" a bars_held=3.
Aggiunto un ramo `elif self.max_bars` che esce a "time_limit" quando
bars_held>=max_bars, prima del fallback hold_bars. Tocca solo le
strategie horizon-only (SH01); le fade con tp+sl+max_bars sono invariate.
Test: tests/portfolio/test_horizon_exit.py (resta in posizione a 3 barre
con max_bars=12; esce a 12 con reason time_limit). Suite: 43 passed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tre alternative di uscita misurate su MR02 (fee-aware) vs baseline TP=centro canale:
- 15m "scalp": piu' PnL lordo ma fragile a fee/slippage (DD esplode a 0.20%).
- trailing/TP dinamico: win-rate 48%->36%, azzera l'edge (let-it-run = continuazione).
- TP-ATR: TP stretto m=0.5 -> win 77% ma edge ~0 (trappola scalping); nessun
multiplo ATR batte il centro su avg/trade e Sharpe (FULL+OOS, BTC/ETH).
Verdetto: TP=centro canale e' ottimale (target adattivo alla struttura, gia'
scalato alla vol). Design blindato. Nota: win-rate alto != edge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>