f5173fba06
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>
30 lines
1014 B
Python
30 lines
1014 B
Python
"""src.live.bars — detection condivisa della barra in formazione (lezione EXIT-16)."""
|
|
import numpy as np
|
|
|
|
from src.live.bars import bar_ms_of, last_bar_is_forming, last_settled_idx
|
|
|
|
H = 3_600_000
|
|
|
|
|
|
def _ts(n, end_ms):
|
|
return np.arange(end_ms - (n - 1) * H, end_ms + 1, H, dtype="int64")
|
|
|
|
|
|
def test_bar_ms_median():
|
|
assert bar_ms_of(_ts(50, 10 * H)) == H
|
|
assert bar_ms_of([1]) == 0 # troppo corta per stimare
|
|
|
|
|
|
def test_forming_vs_settled():
|
|
now = 1_000_000 * H
|
|
ts = _ts(60, now) # ultima barra appena aperta
|
|
assert last_bar_is_forming(ts, now_ms=now + 1) # in corso
|
|
assert last_settled_idx(ts, now_ms=now + 1) == -2
|
|
assert not last_bar_is_forming(ts, now_ms=now + H) # durata trascorsa
|
|
assert last_settled_idx(ts, now_ms=now + H) == -1
|
|
|
|
|
|
def test_degenerate_series_defaults_to_settled():
|
|
assert not last_bar_is_forming([], now_ms=0)
|
|
assert last_settled_idx([123], now_ms=0) == -1 # bar_ms non stimabile -> -1
|