## 문제
30s 폴링 × 3캔들 윈도우 × 600s 쿨다운이 맞물려, 동일 캔들에 대한 알림이
한 번 발송된 뒤 쿨다운(10분)이 풀리는 시점에 같은 캔들이 여전히 tail(3)
윈도우 안에 남아있으면(5m 기준 최대 15분 머무름) 두 번째 알림이 다시 발송
되는 현상.
## 변경 사항
- 시그널별로 마지막 발화 캔들의 open_time 을 추적하는 _last_fired_candle
dict 추가.
- check_and_alert 에서 tail(3) 중 신호가 True 인 가장 최신 캔들의 open_time
을 키로 잡고, 직전 발화와 동일하면 스킵.
- 기존 ALERT_COOLDOWN(시간 기반) 가드는 그대로 유지 — 다른 캔들로 신호가
연속 발생할 때의 과다 알림은 여전히 차단.
결과적으로 한 캔들당 시그널 종류별로 1회만 알림이 발송됨.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- streamlit / urllib3 추가: 코드에서 import 하지만 누락돼있어 새 환경에서
서버 기동 자체가 실패하던 원인.
- ccxt / dash 제거: 어디에서도 import 되지 않음 (잔재).
- python-dotenv 버전 핀 추가, 파일 끝 개행 정리.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## 문제
대시보드 차트에는 진입 신호가 정상 표기되지만 텔레그램 알림이 전혀 발송되지
않거나 일부 신호 종류가 영구적으로 누락되는 현상.
## 변경 사항
1. 알림 스레드 캔들 50 -> 200
- MA99(99 SMA) 가 50 캔들에서는 항상 NaN 이라 bull_ma / bear_ma 가
False 가 되고, strong_long_signal / strong_short_signal 이 영원히
발화하지 않던 문제. UI 와 동일한 200 캔들로 맞춰 신호 일관성 확보.
- OI 도 50 -> 200 으로 정렬해 lookback 보강.
2. 알림 스레드에 fundingRate fetch + merge 추가
- 기존 스레드 df 에 fundingRate 컬럼이 없어 short_caution_signal
('fundingRate' in df.columns 분기) 가 항상 False 였음.
- UI 와 동일한 패턴(get_funding_rate -> floor('1h') merge -> ffill)
으로 fundingRate 합류, short_caution_signal 정상 발화.
3. check_and_alert 1캔들 -> 3캔들 체크
- df.iloc[-1] (현재 형성 중 캔들)만 보던 로직을 df.tail(3) 으로 확장.
- 30s 폴링 사이 닫혀버린 캔들의 신호 누락 방지. cooldown 은 그대로
유지되므로 중복 알림은 발생하지 않음.
## 부가
- streamlit.log / streamlit.err.log 를 .gitignore 에 추가
(런타임 산출물 — 6.9MB까지 커지는 상황 발생).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>