재시작 시 역사적 신호 burst 차단 — interval 별 silent sync

## 사례
Oracle systemd restart 후 첫 polling 에서 24h 내 tail(3) 안의 모든
True 신호가 한꺼번에 발사되어 텔레그램 채널에 알림 5~10건 burst.
사용자: "이거 지금 한번에 다 오게 해서 이 지랄 난거지 씨발 정신 없네"

## 원인
재시작 시 alert_state.last_fired_candle 가 빈 dict -> 첫 polling 의
tail(3) 검사에서 모든 신호가 "처음 보는 candle" 로 인식 -> 알림 발사.
이전에 본 candle 인지를 기억하는 매커니즘이 process restart 에서 끊김.

## 수정
alert_state.synced_intervals (set) 추가. check_and_alert 진입 시 해당
interval 이 set 에 없으면 (= 첫 처리):
1. 현재 df 의 모든 signal 컬럼 스캔
2. 각 signal 의 가장 최근 True candle 의 open_time 을 last_fired_candle
   에 silent set
3. set 에 interval 추가
4. return (알림 발사 안 함)

다음 polling 부터는 sync 된 dedup 상태 위에서 정상 동작 -> 새로 발화
된 candle 만 알림.

## 부작용
재시작 직후 가장 최근 candle 의 신호 1회 누락 (sync 가 dedup 처리해서
다음 polling 에 같은 candle 은 fire 안 함). 다음 candle 의 신호부터는
정상 알림. burst 폭주 vs "방금 막 발화한 신호 1회 놓침" 트레이드오프
에서 사용자 선호 따라 burst 차단 우선.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ILSEON-RYU
2026-05-05 00:29:11 +09:00
parent c72046909b
commit 3538b0324d
2 changed files with 17 additions and 0 deletions
+5
View File
@@ -28,6 +28,11 @@ short_entry = {}
# 항목 형식: {"interval", "direction", "candle_time", "msg", "sig_cols"}
pending_groups = []
# 재시작 후 첫 polling 시 alert_state 가 비어있어 tail(3) 의 역사적 신호들이
# 한꺼번에 발사되는 burst 차단. 첫 처리 시 dedup 상태만 동기화하고 알림은
# skip. interval 별로 각각 한 번씩 sync.
synced_intervals = set()
alert_symbol = "BTCUSDT"
alert_interval = "5m" # UI 표시용; 알림 스레드는 multi-TF 모니터링이라 무시
alert_lock = threading.Lock()
+12
View File
@@ -97,6 +97,18 @@ def check_and_alert(df, symbol, interval):
return
forming_ct = df.iloc[-1]["open_time"]
# 재시작 후 첫 polling — 역사적 신호 burst 차단을 위해 dedup 만 silent sync
if interval not in alert_state.synced_intervals:
for sig, key, _, _ in SIG_DEFS:
if sig not in df.columns:
continue
triggered = df[df[sig].fillna(False)]
if not triggered.empty:
alert_state.last_fired_candle[(interval, key)] = triggered.iloc[-1]["open_time"]
alert_state.synced_intervals.add(interval)
print(f"[알림스레드] {interval} 초기 sync 완료 — 이후 polling 부터 새 신호만 발사")
return
# Phase 1 — pending_groups 검증. forming candle 이라도 매 polling 마다 신호
# 상태 확인. 사라지면 즉시 [취소 알림] (캔들 마감까지 기다리지 않음).
new_pending = []