3538b0324d
## 사례 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>
42 lines
1.7 KiB
Python
42 lines
1.7 KiB
Python
"""
|
|
Streamlit 의 매 rerun 마다 메인 스크립트는 새 namespace 에서 재실행되어
|
|
모듈 최상단의 mutable state 가 모두 초기화된다 (`globals()` 가드도 우회됨).
|
|
|
|
이 파일은 별도 모듈로 단 한 번만 import 되므로 (Python 의 sys.modules 캐싱)
|
|
state 가 process lifetime 동안 보존된다. 알림 dedup, 진입 추적, 스레드
|
|
기동 가드 등 다중 rerun 환경에서 살아남아야 하는 모든 mutable 상태는
|
|
여기에 둔다.
|
|
|
|
알림 스레드는 multi-TF (1m/3m/5m/15m/30m/1h) 동시 모니터링 모드라
|
|
dedup 과 진입 추적은 모두 (interval, key) 또는 interval 별로 분리된다.
|
|
"""
|
|
import threading
|
|
|
|
# (interval, key) 별 마지막 알림 시각 (cooldown 용). default 0.
|
|
# 키가 없으면 dict.get 으로 0 fallback.
|
|
last_alert = {}
|
|
|
|
# (interval, key) 별 마지막으로 알림 보낸 candle open_time (per-candle dedup).
|
|
last_fired_candle = {}
|
|
|
|
# interval 별 진입 추적. value = entry_record dict 또는 None.
|
|
long_entry = {}
|
|
short_entry = {}
|
|
|
|
# forming candle 에서 발사된 알림은 캔들 마감 후 신호 재검증을 받는다.
|
|
# 마감 시점에 신호가 사라졌으면 [취소 알림] 을 보낸다.
|
|
# 항목 형식: {"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()
|
|
alert_started = False
|
|
daily_report_started = False
|
|
last_report_date = None
|