Stage 07.4.3.6 — Smart alert throttling
This commit is contained in:
@@ -36,6 +36,10 @@ class AutoTradeRunner:
|
||||
_retry_after_until: float = 0.0
|
||||
_last_strong_alert_key: str | None = None
|
||||
|
||||
# защита от частых одинаковых alert-ов
|
||||
_strong_alert_cooldown_seconds = 120
|
||||
_last_strong_alert_at_by_key: dict[str, float] = {}
|
||||
|
||||
@classmethod
|
||||
def register_screen(
|
||||
cls,
|
||||
@@ -187,10 +191,27 @@ class AutoTradeRunner:
|
||||
f"{state.decision_status}:{reason}"
|
||||
)
|
||||
|
||||
if alert_key == cls._last_strong_alert_key:
|
||||
return
|
||||
now = time.monotonic()
|
||||
last_alert_at = cls._last_strong_alert_at_by_key.get(alert_key)
|
||||
|
||||
if last_alert_at is not None:
|
||||
elapsed = now - last_alert_at
|
||||
|
||||
if elapsed < cls._strong_alert_cooldown_seconds:
|
||||
cls._log_suppressed_strong_alert(
|
||||
signal=signal,
|
||||
symbol=symbol,
|
||||
strategy=strategy,
|
||||
repeat_count=repeat_count,
|
||||
confidence=confidence,
|
||||
leverage=leverage,
|
||||
reason=reason,
|
||||
cooldown_left=round(cls._strong_alert_cooldown_seconds - elapsed, 2),
|
||||
)
|
||||
return
|
||||
|
||||
cls._last_strong_alert_key = alert_key
|
||||
cls._last_strong_alert_at_by_key[alert_key] = now
|
||||
|
||||
signal_icon = {
|
||||
"BUY": "🟢",
|
||||
@@ -235,6 +256,39 @@ class AutoTradeRunner:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def _log_suppressed_strong_alert(
|
||||
cls,
|
||||
*,
|
||||
signal: str,
|
||||
symbol: str,
|
||||
strategy: str,
|
||||
repeat_count: int,
|
||||
confidence: float,
|
||||
leverage: object,
|
||||
reason: str,
|
||||
cooldown_left: float,
|
||||
) -> None:
|
||||
try:
|
||||
JournalService().log_ui_info(
|
||||
event_type="auto_strong_signal_alert_suppressed",
|
||||
message=f"Повторное уведомление о сильном сигнале {signal} подавлено.",
|
||||
screen="auto",
|
||||
action="strong_signal_alert",
|
||||
payload={
|
||||
"symbol": symbol,
|
||||
"strategy": strategy,
|
||||
"signal": signal,
|
||||
"repeat_count": repeat_count,
|
||||
"confidence": confidence,
|
||||
"leverage": leverage,
|
||||
"reason": reason,
|
||||
"cooldown_left": cooldown_left,
|
||||
},
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
async def _refresh_screen(cls, *, force: bool = False) -> None:
|
||||
now = time.monotonic()
|
||||
|
||||
Reference in New Issue
Block a user