Files
PythagorasGoal/docs/diary/2026-06-07-sweep-fixes.md
T
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

6.2 KiB
Raw Blame History

2026-06-07 — Implementazione fix improvement-sweep (P0 + punti 2-6, settimana 1)

Implementati e deployati i fix "settimana 1" del piano dello sweep 2026-06-06 (tutti fix di parità/protezione/osservabilità, nessun cambio di strategia → nessun gate OOS richiesto). Versioni: v1.1.3 (punti 1-4), v1.1.4 (punti 5-6).

P0 — cap SHAPE 0.0588 ripristinato (v1.1.3)

portfolios.yml ridichiara il dict caps COMPLETO {PAIRS: 0.33, SHAPE: 0.0588} (l'override sostituisce interamente i caps di _defs.py via setattr in base.py:load_active_portfolio — footgun ora commentato nel yml). Verificato live post-restart: SH_BTC+SH_ETH = 0.0588 totale (prima 0.1176 = 2x intended), non-cappati risaliti a 0.0647, sum = 1.0 — parità col backtest canonico (FULL 6.43 / OOS 8.58).

Punti 2-4 — parità worker multi-asset (v1.1.3)

  • TR01 fee × leva: POS · LEV · fee_rt/2 per flip come il reference honest_improve2._tr_basket_daily:150 (prima sotto-caricata 2x).
  • TR01 forming-bar: crossover EMA E booking del return solo su barre 4h COMPLETE (riga -1 = candela in corso finché non è trascorsa la sua durata, pattern EXIT-16). Evidenza live che non può più ripetersi: flip SOL 0→1→0 in 59min stessa finestra 4h.
  • PairsWorker forming-bar: entry ED exit sul close di barra COMPLETA, come il backtest pairs_research (close settled).
  • TSM01/ROT02 silent-return: WARN log + Telegram PANEL_SHORT quando il panel inner-join è sotto il lookback (helper condiviso _warn_panel_short in rotation_worker), gated su "era già operativo", una notifica per episodio.

Verifiche: 72 test (7 nuovi), validate_worker_pairs ESATTO, validate_honest_workers invariato. Nota onesta: TR01 replay worker 44% vs reference +42% è IDENTICO pre/post fix → divergenza di convenzione pre-esistente (capitale-unico con mean(rets) solo sugli asset in posizione vs media-equity 1/N del reference). Da rivisitare a parte: "stesso ordine di grandezza" oggi non regge più.

Punto 5 — disaster-bracket on-book + alert outage (v1.1.4)

Durante un outage (poll-loop in except) le posizioni REALI restavano senza stop sul book e senza valutazione exit. Ora:

  • ExecutionClient.place_disaster_sl: STOP_MARKET reduce-only a ~30% dall'ingresso (trigger sul mark), piazzato a ogni REAL_OPEN sui fade eseguiti (MR01/MR02/MR07/DIP01) e cancellato in _real_close (prima del TP-reconcile). In operatività normale non scatta mai → 0 costo Sharpe; nei crash il fill è al gap (cappa la coda, non la elimina). Config: overrides.execution.disaster_sl_pct (default 0.30, 0 = off). real_dsl_order_id persistito (resume-safe).
  • SCOPERTA: il set_stop_loss di cerbero-mcp è un private/edit Deribit (solo ordini APERTI) → inutilizzabile su market già fillati; il bracket va piazzato come trigger order autonomo via place_order(type="stop_market") (già supportato).
  • Semantica cancel trigger order (verificata su testnet): la cancel risponde con lo stato AL MOMENTO della cancel (untriggered = successo; il re-cancel dà order_not_found); error = non più in book (probabile trigger scattato → il market a valle filla 0 e REAL_CLOSE esce verified=False).
  • Alert FEED_OUTAGE: dopo 5 poll falliti consecutivi (~5 min) Telegram con l'elenco delle posizioni reali aperte; notifica di ripresa con durata.

Smoke testnet (live_shadow_smoke.py, esteso): 4 scenari long+short — il path short-side TP-resting (BUY limit reduce-only) non era MAI stato esercitato. Tutti verdi: resting/cross-immediato due lati, DSL piazzato/cancellato (verificato zero ordini orfani sul book), conto flat a fine smoke.

Punto 6 — osservabilità multi-asset (v1.1.4)

  • in_position aggiunto ai _save() di TR01/ROT02/TSM01.
  • hourly_report: nuova sezione MULTI-ASSET (book corrente | ultimo flip | freschezza status) — prima i 3 worker erano invisibili nel report (collect() filtra su event/in_position che non emettevano): impossibile distinguere "flat/risk-off by-design" da "wiring rotto". I multi-asset sono esclusi dalla tabella IN CORSO (assume entry/bars single-leg).

Code review multi-agente del giorno stesso (v1.1.7)

Review a 7 angoli su 8c4e1cd..HEAD + check trades live. Il candidato top dei finder ("stop_market senza trigger") è REFUTATO: cerbero-mcp traduce price→trigger_price + trigger=mark_price e in produzione 2 DSL erano armati + 1 ciclo completo pulito. Quattro fix applicati:

  1. Alert REAL_DIVERGENCE (|slippage sim/reale| ≥ 100bps a open/close). Scoperta dal check trades: alle 10:37 uno spike print testnet (candela 10:00 H=65618 con O/C~62400) ha fatto shortare alle 3 fade BTC un close fantasma a 65266.5 — il reale ha fillato correttamente a ~62395 (440bps) ma il sim ha bookato +2.26 mai esistiti (MR07 reale 0.13). Prima passava in silenzio.
  2. FEED_OUTAGE anche su feed degradato senza eccezione (HTTP 200 con candles vuote → i worker saltavano il tick in silenzio e lo streak restava 0). Helper unico _outage_tick (fix anche dell'incoerenza chiavi minuti/durata_min).
  3. src/live/bars.py: detection forming-bar UNIFICATA (era copiata in 4 punti, con _check_stale_feed che hardcodava 1h). È l'invariante di sicurezza di EXIT-16: ora vive in un posto solo, testato (test_bars.py).
  4. DSL cancel hardening: retry su errore transitorio + alert Telegram REAL_DSL_CANCEL_FAIL se lo stop resta forse ORFANO sul book (prima l'id veniva dimenticato in silenzio → lo stop stantio poteva colpire la posizione successiva); order_not_found = probabile trigger durante outage → solo log (il close a valle esce già verified=False). Test con executor finto (test_real_close_dsl.py).

Finding noti NON ancora fixati (in coda): ROT02/TSM01 valutano la candela 1d in formazione al primo poll dopo mezzanotte (stessa classe del fix TR01/Pairs, pre-esistente); engine dei gate copiato fra i 3 script *_port06_impact.py; epoche hourly_report hardcoded.

Resta in roadmap (settimana 2, OGNUNO dietro gate PORT06/OOS)

trend_max=3.0 sulle 6 fade → pos pairs 0.15-0.25 per-famiglia → DIP01 EXIT-16 (validazione gap-aware) → SH01 ri-validazione train-window ~8760 barre. Follow-up tecnico: divergenza convenzione TR01 worker vs reference (sopra).