Commit Graph

40 Commits

Author SHA1 Message Date
Adriano Dal Pastro 612f2bfced feat(live): reconcile resting + orphan single-leg + circuit-breaker venue-lock + FEED_BOOK_GAP
Codice della tornata v1.1.27/28 (gia' in produzione, mai committato):
- reconcile_account: estensione ordini RESTING (FILLED_UNBOOKED/MISSING/STALE,
  caso MR02_BTC: TP fillato di notte scoperto ore dopo) + expected_resting in books
- strategy_worker: orphan_legs su REAL_CLOSE_PARTIAL anche single-leg, persistito
- execution: circuit-breaker su venue-lock admin (stop ordini dopo errori ripetuti)
- runner/hourly_report: alert FEED_BOOK_GAP + timestamp closed trades
- cerbero_client: get_open_orders (merge all + trigger_all)
Test: 12 nuovi, suite completa 126 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 20:29:02 +00:00
Adriano Dal Pastro 82c05f6f81 fix(exec): code-review serale — guard anti-posizione-nuda sul netting + verità per-frazione
7 finder paralleli sul diff della giornata (8adf388..HEAD), fix dei confermati:

CRITICI (money-path):
- close_amount: GUARD stato-stantio sul fallback netting — il residuo
  non-reduce-only e' consentito solo fino al gap (conto reale - libri degli
  altri worker - orfani) nella direzione della chiusura (src/live/books.py =
  fonte unica, usata anche dal reconciler). Senza guard, un close su stato
  stantio (DSL scattato in outage, flatten manuale) APRIVA una posizione nuda
  a taglia piena bookata come 'chiusura verificata'. Fail-safe se il gap non
  e' calcolabile. Check polvere PRIMA di _quantize_step (che clampa al lotto
  minimo: un residuo 1e-17 diventava un ordine nudo da un lotto).
- _real_close: market_amt = filled_amount anche a merged verified=False (i
  contratti chiusi dal reduce-only non si buttano se il leg netting fallisce);
  REAL_CLOSE_PARTIAL non piu' gateato su verified (era soppresso proprio nel
  caso parziale reale).
- pairs: verita' per-FRAZIONE di gamba (gross proporzionale al fillato, orfano
  = solo il residuo — prima falsava reconciler e real_capital della parte gia'
  chiusa); REAL_OPEN_PAIR booka filled_amount; docstring applied corretta.
- open_pair unwind: chiude il FILLATO, non il richiesto (senza il cap silenzioso
  del reduce-only avrebbe mangiato quota altrui).
- place_tp_limit: quantize CONSERVATIVO (sell=floor/buy=ceil) — il rounding al
  tick piu' vicino poteva mettere il resting oltre il TP sim -> tocco genuino
  classificato phantom sistematicamente.

ROBUSTEZZA/OSSERVABILITA':
- runner: WORKER_ERROR_STREAK a 5 e poi ogni 50 poll + recovery RIPRESO +
  flag real_in_position nell'alert (prima: one-shot a n==5, poi silenzio).
- _tp_phantom: TTL 120s sul verdetto (era ~50 HTTP/h per worker a barra
  fantasma); merge notes con entrambi gli order_id (audit-trail).
- reset_flatten: _quantize_step Decimal (round float produceva amount che
  Deribit rifiuta); hourly_report: book XS01 con gambe SHORT visibili (abs).
- validate_xsec_worker: POS/LEV importati (non hardcoded); xs01_tranche:
  regression-lock ESEGUITO vs xsec_sim; reconcile su src/live/books;
  drift_monitor: rolling vettoriale + exit code 1 su warn.

Test: +4 guard/dust, fixture filled_amount -> 114 passed.
Deferiti (TODO): resting esposti al netting, lifecycle orphan_legs, finestra
trade-history TP_PHANTOM, validazione feed a monte, dedup minori.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:36:30 +00:00
Adriano Dal Pastro 844a9d0e22 feat(exec): netting delle chiusure market — il residuo reduce-only cappato/respinto va in market puro
close_amount ora: (1) tenta il market reduce-only (sicurezza storica: un bug di
stato filla 0 invece di aprire posizioni); (2) il residuo cappato/respinto dal
netting di conto (worker in direzioni opposte sullo stesso strumento) viene
rieseguito in MARKET PURO con label '|net' — muove il conto esattamente del
delta del libro = netta contro le quote opposte. Niente piu' gambe pairs orfane
ne' close cappati per costruzione (close_pair passa da close_amount).

- _merge_close_fills: il chiamante riceve UN Fill (prezzo medio pesato sui fill,
  fee sommate, filled_amount totale, verified se copre il richiesto, notes
  'netting' quando il fallback scatta)
- worker single-leg + pairs: evento NET_CLOSE (log jsonl + Telegram) a ogni
  fallback — osservabilita' della frequenza dei conflitti di netting
- sicurezza persa sul residuo coperta dal reconciler orario (ACCOUNT_DRIFT);
  orphan_legs/REAL_CLOSE_PARTIAL restano come ultima difesa
- 4 test nuovi (full r-o senza fallback, cappato, respinto, doppio fail) -> 110 passed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 20:54:43 +00:00
Adriano Dal Pastro 429fa01c97 fix(exec): verità contabile sul netting — filled_amount, gambe orfane, tick isolato
Da audit live (3 indagini parallele, diario 2026-06-11-system-audit.md): il modello
quote-per-worker reduce-only si rompe con direzioni opposte sullo stesso strumento
(pairs long ETH vs fade short ETH) — close cappati bookati pieni, 3 gambe pairs mai
eseguite col PnL sim nel ledger reale, conto short 0.027 ETH oltre i libri
(riallineato a mano + DSL orfano cancellato).

- Fill.filled_amount (order.filled_amount): TUTTI i ledger usano il fillato reale
- REAL_CLOSE_PARTIAL (log+alert) su close cappato; residuo orfano dichiarato
- pairs: PnL solo per gambe verificate; gamba respinta -> orphan_legs persistito
  + alert PAIR_LEG_ORPHAN; applied solo con entrambe le gambe (else sim_fallback)
- REAL_DIVERGENCE anche su jsonl (prima solo Telegram)
- runner: tick isolato per-worker + WORKER_ERROR_STREAK a 5 fail consecutivi

Strutturale APERTO (decisione utente, opzioni nel diario): position-manager
centrale / sotto-conti per famiglia / status-quo monitorato.

Test: +2 (partial-close, orphan-leg), fixture filled_amount -> 106 passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 20:05:42 +00:00
Adriano Dal Pastro 12625b3315 feat(exec): gate TP_PHANTOM — il tocco TP va confermato dal book reale, non dal feed
Il feed testnet stampa wick che 'toccano' il TP intrabar senza che il prezzo
abbia mai scambiato al livello: il sim bookava +4% fantasma a bars_held=0 e
_real_close chiudeva A MERCATO una posizione col resting TP a zero fill
(-fee/spread a giro, 14 giri l'11-06). Ora StrategyWorker._tp_phantom sopprime
l'exit take_profit quando: tocco sim + resting LIMIT zero-fill + prezzo corrente
che non ha raggiunto il livello (il limit sul book reale e' l'oracolo del tocco).
Zero parametri (verita' d'esecuzione, non filtro di strategia); SL close-confirm
e max_bars restano attivi nello stesso tick; fill parziale/prezzo oltre il
livello/worker non eseguito/errore rete -> comportamento storico. Log TP_PHANTOM
dedup per barra + alert Telegram una tantum. 5 test nuovi (104 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:32:24 +00:00
Adriano Dal Pastro cc39c36c08 feat(live): REAL-TRUTH ledger — capital aggiornato dal PnL dei fill reali, sim ridotto a diagnostica
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 12:23:52 +00:00
Adriano Dal Pastro a85289d7c7 feat(xsec): XS01 reversione cross-sectional (8 asset) -> PORT06 PAPER
Famiglia NUOVA trovata in sessione (dopo aver scartato trend/breakout/seasonal/
opzioni/funding come rumore): ogni 12h long i perdenti relativi / short i vincenti
su 8 asset, market-neutral. Scorrelata (~0) da pairs e fade -> diversificatore.

- engine canonico scripts/strategies/XS01_cross_sectional.py (no look-ahead, plateau
  OOS Sharpe 2-3.9, 5/5 anni+, edge concentrato 2025, cost-sensitive ~0.35% RT).
- src/live/xsec_worker.py CrossSectionalWorker: validate_xsec_worker == backtest ESATTO
  (4993/1427 trade). Mirror della cadenza engine (entry-to-entry = hold+1).
- gate PORT06: +XS01 -> OOS Sharpe 9.66->10.07, FULL DD 3.68->3.46 (OOS DD +0.17pp,
  risk-contrib 2.2%). xsec_port06_gate.py.
- wiring: _defs XSEC in PORT06 (19 sleeve, family XSEC), build_everything, runner
  kind=xsec, asset_days da supported (fix fetch alt anche per paper sleeves), paper.
- 8 gambe -> niente exec reale -> gira PAPER. Regression-lock 18->19, FULL 7.20->7.34,
  OOS 9.66->10.07. 93 test verdi. Diario 2026-06-09-xs01-cross-sectional.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 21:38:05 +00:00
Adriano Dal Pastro d25d897fd1 feat(pairs): attiva ETH/BTC 15m flat-skip in PORT06 (BLEND, mezza size)
Origine: gioco "Blind Traders" (100 agenti ciechi su BTC/ETH anonimizzati) ->
vincitore = spread ETH/BTC reversion a 15m. Testato sul serio col gate PORT06:
non duplicato (corr 1h vs 15m = 0.37), robusto (16/16 celle Sharpe>1), edge NON
artefatto delle candele flat ETH 15m (filtrandole resta l'83% dello Sharpe).

Percorso live costruito e validato:
- pairs_research.pairs_sim_flat: engine generalizzato con exit LIVE-REALIZABLE
  (arma exit_ready, esce alla 1a barra pulita); regression-lock a pairs_sim.
- PairsWorker: flat_skip + exit_ready + rilevamento flat da OHLC (1h byte-exact).
- runner: fetch diretto dei timeframe sub-orari + override position_size per-sleeve.
- validate_worker_pairs: replay worker == backtest a 15m (8452 vs 8453 trade).
- _defs/build_everything: sleeve PR_ETHBTC_15M (mezza size, pos 0.10) -> PORT06
  FULL 6.43->7.20, OOS 8.58->9.66, DD giu'. Rischio bilanciato col 1h.
- smoke live: Cerbero serve candele 15m fresche; worker ticca.

Diari docs/diary/2026-06-09-*. Caveat slippage: mezza size = blend-tilt prudente.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 11:48:15 +00:00
Adriano Dal Pastro 0b900a5420 feat(live): SH01 in esecuzione reale shadow (diversificatore decorrelato)
L'infrastruttura no-TP esisteva gia': _place_real_tp ritorna subito senza TP,
_real_close chiude tutta la quota a market reduce-only (exit a orizzonte H=12).
Bastava: (1) _exec_for accetta kind 'ml', (2) SH01 in execution.sleeves.
Disaster-bracket on-book = unica protezione di coda di SH01 (esce a H=12 ben prima
del -30%). Motivo: SH01 e' il diversificatore piu' decorrelato (corr 0.07) — senza
i 5 sleeve PAPER il DD del portafoglio sale 3.96->5.35%, OOS Sharpe 8.58->8.27.

Test: SH01 open/close reale senza TP + disaster bracket (93/93). Copertura reale
ora ~81% (resta paper solo TR01/ROT02/TSM01, bloccati dal capitale).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 11:18:06 +00:00
Adriano Dal Pastro c655604131 feat(live): executor a 2 gambe per i pairs (PairsExecutionClient, shadow) — pronto, spento
PairsExecutionClient (compone ExecutionClient): open_pair (2 market long A/short B,
verifica per-gamba, LEG-RISK unwind se una sola filla), close_pair (2 reduce-only via
close_amount, MAI close_position), register_contract (fetch spec USDC). Spec LTC/ADA/SOL
aggiunti. PairsWorker: ledger reale shadow a 2 gambe resume-safe (_real_open_pair/
_real_close_pair, PnL per gamba dir A=+d/B=-d, doppio arrotondamento riportato). Runner:
pairs_executor gated su execution.pairs_enabled (false di default).

Validazione: test 92/92 (open/close, leg-risk unwind, resume) + smoke testnet
end-to-end (open 2 gambe verificate, close reduce-only, PnL reale -0.039 vs sim -0.036,
conto flat). Smoke ora aborta se ci sono posizioni di produzione + usa solo close_amount.

NB incidente testnet documentato (diario): pulizia manuale con close_position ha flattato
le quote shadow dei fade sul conto condiviso -> auto-riconciliazione al prossimo close.
Lezione: mai close_position su strumenti condivisi.

pairs_enabled resta FALSE: accendere con finestra a conto flat + osservazione.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:19:56 +00:00
Adriano Dal Pastro f509f51543 fix(live): ROT02/TSM01 scartano la barra 1d in formazione (forming-bar in _panel)
Code-review follow-up: i worker daily valutavano momentum/regime e bookavano il
return sulla candela 1d PARZIALE al primo poll dopo mezzanotte UTC, poi last_bar_ts
bloccava la rivalutazione a giorno chiuso (stessa classe del bug gia' fixato su
fade/TR01/Pairs). Fix in _panel (un punto solo -> ROT02 e TSM01 lo ereditano) via
src.live.bars.last_bar_is_forming. Replay honest invariato (dati storici: nessuna
barra in formazione). Test: 88/88 + parity drop forming daily bar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 10:00:16 +00:00
Adriano Dal Pastro 8c5372c487 feat(SH01): bootstrap storia full-history + last_block_only (punto-10: regime live non robusto)
Ri-validazione sh01_trainwindow_validate.py (rolling train_window == regime live):
- tw=8760 (live 365g): BTC FULL +82% ma fee-2x -42% (6/9 anni), ETH Sharpe -0.02,
  trade-rate 21.7-26.4% vs 9.8% validato -> NON robusto. Diagnosi sweep confermata
  (LogReg over-confident su train corto, th 0.58 inerte).
- progressione MONOTONA con la memoria (2y: Sh 2.05; 3y: 3.09; expanding: ROBUSTO
  8/9) -> l'edge di SH01 e' la memoria lunga.
- sweep soglia nel regime corto: instabile/incoerente fra asset -> NON ri-tunare.

Fix (decisione utente): ripristinare in live il regime validato.
- ml_wf_entries(last_block_only=True): fitta/predice solo l'ultimo blocco del WF
  (confini deterministici start+k*retrain) -> entries IDENTICHE per costruzione
  al tail del WF completo (parity test esatto); 0.6s/tick su 73k barre vs ~140 fit.
- runner._with_history: tick degli sleeve ml su parquet locale + feed live
  (dedup timestamp, gap-guard con WARN una-tantum se parquet stantio).
- _defs.py: params {last_block_only: true} sugli sleeve SHAPE (solo path live;
  il backtest canonico resta WF completo).

Effetto atteso live: trade-rate SH01 ~25% -> ~10% delle barre, selettivita'
ripristinata. Manutenzione: parquet fresco via download_all (oggi 2026-05-28,
margine ~11 mesi col feed 365g).

Test: 87/87 (4 nuovi: parity last-block esatta, merge storia, gap fallback).
Diario docs/diary/2026-06-07-sh01-trainwindow.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:48:22 +00:00
Adriano Dal Pastro f5173fba06 fix(live): 4 hardening da code-review — REAL_DIVERGENCE, outage su feed vuoto, bars.py condiviso, DSL cancel retry
Review multi-agente 7-angoli su 8c4e1cd..HEAD + check trades live:

1. Alert Telegram REAL_DIVERGENCE quando |slippage sim/reale| >= 100bps a
   open/close. Causa scatenante: spike print testnet 10:37 (candela 10:00
   H=65618, O/C ~62400) -> 3 fade BTC short su close fantasma 65266.5, reale
   fillato a 62395 (-440bps), sim +2.26 mai esistiti — passato in silenzio.
2. FEED_OUTAGE anche su feed degradato SENZA eccezione (HTTP 200 + candles
   vuote: i worker saltavano il tick in silenzio, streak a 0). Helper unico
   _outage_tick; chiavi payload uniformate (minuti su start e RIPRESO).
3. src/live/bars.py: detection forming-bar unificata (bar_ms_of /
   last_bar_is_forming / last_settled_idx) — era copiata in 4 punti
   (strategy_worker, basket, pairs, _check_stale_feed hardcoded 1h).
   E' l'invariante di sicurezza EXIT-16: ora una sola implementazione testata.
4. DSL cancel hardening in _real_close: retry su errore transitorio + alert
   REAL_DSL_CANCEL_FAIL se lo stop resta forse orfano sul book (prima l'id
   veniva dimenticato in silenzio); order_not_found = probabile trigger in
   outage -> solo log (il close a valle esce gia' verified=False).

Refutato il finding top dei finder ("stop_market senza trigger"): cerbero-mcp
traduce price->trigger_price+mark, e in produzione 2 DSL armati + 1 ciclo
completo pulito (MR07_BTC).

Test: 83/83 (9 nuovi: bars helper + DSL/divergence con executor finto).
Smoke testnet 4 scenari verdi, conto flat, zero falsi allarmi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:59:58 +00:00
Adriano Dal Pastro 6097205694 feat(pairs): position_size per-famiglia, PAIRS 0.5->0.20 (gate PORT06)
Punto 8 roadmap sweep. La famiglia pairs (SENZA stop, validata a pos 0.15 lev 3 =
esposizione 0.45) girava col position_size globale 0.5 a leva 2 = esposizione 1.0,
~2.2x il validato (ETH/BTC DD grezzo 78% a quella taglia; live: ADA/ETH -4.26%
sleeve in un trade il 2026-06-05).

Gate pairspos_port06_impact.py (pairs_sim alla leva live 2x, parita' canonica
1.00000 5/5, PORT06 pesi cap): griglia pos {0.5, 0.25, 0.20, 0.15}. Il gate
meccanico boccia ogni riduzione (costa OOS Sharpe — il compounding in-sample a 0.5
e' fantasia: +2.6e9% ETH/BTC), ma 0.20 e' il ginocchio del trade-off: OOS DD
3.40->1.26% (meglio anche di 0.15), famiglia DD 14->5.8%, costo OOS Sharpe
9.05->8.43. Decisione assicurativa (utente), come il precedente cap SHAPE.

- runner.pos_for_spec(sid, global, family_overrides): override per-famiglia
  (chiave weighting.family_of), plumbato in build_worker_for.
- portfolios.yml: position_size_family {PAIRS: 0.20} (globale 0.5 invariato).
- Test: pos_for_spec mapping + PairsWorker.position_size (74/74 verdi).

Nota transizione: la posizione LTC/ETH aperta verra' chiusa col pos nuovo
(one-time). Diario docs/diary/2026-06-07-pairspos-gate.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 10:44:15 +00:00
Adriano Dal Pastro 3909646028 fix(live): parita' worker multi-asset — TR01 fee x leva, forming-bar su TR01/Pairs, WARN panel corto
Punti 2-4 dell'improvement-sweep 2026-06-06 (fix di parita', nessun cambio di strategia):

- TR01 (basket_trend_worker): fee per flip = POS * LEV * fee_rt/2 come il reference
  honest_improve2._tr_basket_daily:150 (mancava il fattore leva -> fee sotto-caricate 2x,
  bias ottimistico che gonfiava total_capital al ribilancio).
- TR01: crossover EMA e booking del return valutati SOLO su barre 4h COMPLETE
  (la riga -1 e' la candela in corso finche' non e' trascorsa la sua durata) — lezione
  EXIT-16; evidenza live: flip SOL 0->1->0 in 59min nella stessa finestra 4h.
- PairsWorker: entry ED exit valutati sul close di barra COMPLETA, come il backtest
  pairs_research (close settled). Stesso pattern bar_ms di strategy_worker.tick.
- TSM01/ROT02: il silent return su panel inner-join troncato sotto il lookback ora
  emette WARN log + Telegram PANEL_SHORT (helper _warn_panel_short condiviso), gated
  su "era gia' operativo" (no falsi positivi al cold-start), una notifica per episodio.

Test: 72/72 verdi (7 nuovi: forming-bar TR01/pairs + controllo positivo, fee con leva,
PANEL_SHORT warn/dedup/cold-start). Replay parity: validate_worker_pairs ESATTO
(ETH/BTC e BTC/LTC == backtest); validate_honest_workers invariato (TR01 -44% vs ref
+42% IDENTICO pre/post fix: e' la divergenza di convenzione capitale-unico vs
media-equity gia' documentata, da rivisitare a parte).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 08:23:19 +00:00
Adriano Dal Pastro 2da3457ca7 fix(live): EXIT-16 confirm-SL valutato sul close di barra COMPLETATA + alert STALE_FEED
Il worker valutava il confirm sul prezzo della candela IN FORMAZIONE ad ogni poll,
reintroducendo la wick-sensitivity che EXIT-16 elimina (audit crash ETH 2026-06-05:
2 stop su 3 erano wick-stop che il backtest validato non avrebbe preso in quel
momento). Ora il confirm usa SOLO il close dell'ultima barra completata (riga -1 =
candela in corso finche' now < ts[-1]+bar_ms), buf dall'ATR della stessa barra,
fill al prezzo corrente (~ stress lag_close_exit OK in exit-lab), TP intrabar
invariato. Concausa feed-gap: non mitigabile lato exit (fill reali ~ sim);
entry-guard post-flat TESTATA e BOCCIATA (skippare i segnali dopo barre flat
peggiora tutti gli sleeve ETH: la candela-gap e' l'overshoot che la fade fada).
Aggiunto alert Telegram STALE_FEED (>=2 barre 1h flat -> notifica + gap % al
risveglio, dedup per episodio, solo osservabilita').

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 18:32:14 +00:00
Adriano Dal Pastro bd6232dc00 config(PORT06): cap SHAPE 0.0588 — SH01 resta senza SL (ricerca multi-agente: 11 famiglie di stop, 0 sopravvissute)
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>
2026-06-05 17:56:16 +00:00
Adriano Dal Pastro a2579d21bc feat(fade): EXIT-16 close-confirm SL — stop solo se il CLOSE sfonda sl∓0.5·ATR14 (immune ai wick)
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>
2026-06-04 21:25:17 +00:00
Adriano Dal Pastro ac6f3766b0 feat(fade): loss-guard Hurst (skip regime persistente) — dimezza il DD del PORT06
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>
2026-06-02 14:08:15 +00:00
Adriano Dal Pastro 83c4e7a334 fix(live): SH01 esegue shape-ML reale, non il wrapper squeeze scartato
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>
2026-06-01 12:24:13 +00:00
Adriano Dal Pastro ab4f706057 fix(live): win netto-fee + filtro TP edge-minimo sulle fade
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>
2026-06-01 11:07:30 +00:00
Adriano Dal Pastro 53e0965c4b fix(live): exit a orizzonte per strategie senza TP/SL (SH01)
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>
2026-06-01 09:05:53 +00:00
Adriano Dal Pastro c13773e762 test(portfolio): aggiorna regression-lock PORT06 dopo recupero dati BNB/DOGE/XRP
Il recupero dello storico BNB/DOGE/XRP (29 mag) ha ampliato la copertura del
backtest -> metriche migliorate, non una regressione:
  Sharpe FULL 6.07 -> 6.47, Sharpe OOS 8.19 -> 8.82, DD FULL 4.9% -> 4.1%.
Aggiornati i tre valori attesi (tolleranze invariate) + commento col motivo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 07:10:40 +00:00
Adriano 49039ac286 fix(live): StrategyWorker esce intrabar su TP/SL (high/low, al livello) come il backtest
Chiude il gap live-vs-backtest delle fade/DIP01: prima il worker controllava solo il
close, ora controlla high/low della barra ed esce AL LIVELLO tp/sl (SL prioritario),
identico alla semantica intrabar del backtest. +4 test. Pairs/rotation/tsmom invariati.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 18:00:12 +02:00
Adriano a7ada9f36c feat(portfolio): integra worker honest/TSM01 nel runner (PORT06 live completo)
build_worker_for gestisce basket/rotation/tsmom + DIP01 via StrategyWorker; run()
fetcha 1h e resampla a 4h/1d, lookback dimensionato sui daily (TSM01 252g); tick
multi-asset per kind. _defs marca TR01/ROT02/TSM01 col kind+universo. Niente piu'
sleeve saltati in PORT06.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 17:45:39 +02:00
Adriano 1e60835612 feat(live): TsmomWorker (TSM01) consenso TSMOM multi-orizzonte risk-gated 2026-05-29 17:42:44 +02:00
Adriano a40315563e feat(live): RotationWorker (ROT02) dual-momentum top-k risk-gated 2026-05-29 17:41:13 +02:00
Adriano e7e8041dae feat(live): BasketTrendWorker (TR01) EMA-cross long/flat multi-asset
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:39:11 +02:00
Adriano ce601c4507 feat(live): DIP01 dip-buy come Strategy single-asset (worker via StrategyWorker)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 17:36:32 +02:00
Adriano 0f582db265 fix(portfolio): runner data_dir dedicata, no resize posizioni aperte, poll da config, +test cap/cluster_rp
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 16:22:33 +02:00
Adriano a5547fb3d2 feat(portfolio): PortfolioRunner live (data v2, tick, ribilancio giornaliero, ledger)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 16:05:07 +02:00
Adriano 2b3d3e3ff8 feat(portfolio): build_worker_for (worker esecutori con capitale da alloc pool)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 16:02:35 +02:00
Adriano 169819fe31 feat(portfolio): portfolios.yml + load_active_portfolio (override operativi) 2026-05-29 16:00:54 +02:00
Adriano 7a4bdb74f0 feat(portfolio): PortfolioLedger (alloc, equity/DD, persistenza+resume)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:59:57 +02:00
Adriano eaf4800b6d feat(portfolio): definizioni PORT01-06 + report run() (default PORT06)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:58:33 +02:00
Adriano 3f6b0ccf91 feat(portfolio): SleeveSpec/Portfolio/backtest con parità verso report_families
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:55:29 +02:00
Adriano 9ff469cb8e feat(portfolio): builder unificato equity-per-sleeve (parità con report_families)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:51:38 +02:00
Adriano d99c9895bb feat(portfolio): schemi di peso (equal/manual/cap/inverse_vol/cluster_rp) 2026-05-29 15:49:27 +02:00
Adriano ea04dcd9d1 feat(portfolio): metodi Cerbero v2 (get_historical_v2, get_instruments, get_ticker_batch)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 15:47:10 +02:00
Adriano 988739b2f5 feat: strategie 1-10, framework analisi frattale, download dati storici BTC/ETH
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:55:13 +02:00