알림 신호 누락 버그 수정 (3건 묶음)
## 문제
대시보드 차트에는 진입 신호가 정상 표기되지만 텔레그램 알림이 전혀 발송되지
않거나 일부 신호 종류가 영구적으로 누락되는 현상.
## 변경 사항
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>
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
.claude/settings.local.json
|
||||||
|
streamlit.log
|
||||||
|
streamlit.err.log
|
||||||
+14
-4
@@ -66,7 +66,7 @@ def send_telegram(message: str):
|
|||||||
|
|
||||||
def check_and_alert(df, symbol, interval):
|
def check_and_alert(df, symbol, interval):
|
||||||
now = time.time()
|
now = time.time()
|
||||||
last = df.iloc[-1]
|
recent = df.tail(3)
|
||||||
for sig, key, msg in [
|
for sig, key, msg in [
|
||||||
("strong_long_signal", "strong_long", f"🟢 강한 롱 진입 신호\n{symbol} {interval}"),
|
("strong_long_signal", "strong_long", f"🟢 강한 롱 진입 신호\n{symbol} {interval}"),
|
||||||
("strong_short_signal", "strong_short", f"🔴 강한 숏 진입 신호\n{symbol} {interval}"),
|
("strong_short_signal", "strong_short", f"🔴 강한 숏 진입 신호\n{symbol} {interval}"),
|
||||||
@@ -76,7 +76,7 @@ def check_and_alert(df, symbol, interval):
|
|||||||
("vol_short_signal", "vol_short", f"🔽 볼륨급등 숏 신호\n{symbol} {interval}"),
|
("vol_short_signal", "vol_short", f"🔽 볼륨급등 숏 신호\n{symbol} {interval}"),
|
||||||
("short_caution_signal","short_caution",f"⚠️ 숏 진입 주의 신호\n{symbol} {interval}"),
|
("short_caution_signal","short_caution",f"⚠️ 숏 진입 주의 신호\n{symbol} {interval}"),
|
||||||
]:
|
]:
|
||||||
if last.get(sig, False) and now - _last_alert[key] > ALERT_COOLDOWN:
|
if sig in recent.columns and recent[sig].fillna(False).any() and now - _last_alert[key] > ALERT_COOLDOWN:
|
||||||
send_telegram(msg)
|
send_telegram(msg)
|
||||||
_last_alert[key] = now
|
_last_alert[key] = now
|
||||||
|
|
||||||
@@ -542,10 +542,10 @@ def _alert_loop():
|
|||||||
with _alert_lock:
|
with _alert_lock:
|
||||||
symbol = _alert_symbol
|
symbol = _alert_symbol
|
||||||
interval = _alert_interval
|
interval = _alert_interval
|
||||||
df = get_klines(symbol, interval, 50)
|
df = get_klines(symbol, interval, 200)
|
||||||
oi_period = interval if interval in ["5m","15m","30m","1h","4h","12h","1d","3d","1M"] else "5m"
|
oi_period = interval if interval in ["5m","15m","30m","1h","4h","12h","1d","3d","1M"] else "5m"
|
||||||
try:
|
try:
|
||||||
oi = get_open_interest_history(symbol, oi_period, 50)
|
oi = get_open_interest_history(symbol, oi_period, 200)
|
||||||
if not oi.empty:
|
if not oi.empty:
|
||||||
oi_m = oi[["timestamp","sumOpenInterest"]].rename(columns={"timestamp":"open_time"})
|
oi_m = oi[["timestamp","sumOpenInterest"]].rename(columns={"timestamp":"open_time"})
|
||||||
df["open_time_r"] = df["open_time"].dt.floor(_to_floor_freq(oi_period))
|
df["open_time_r"] = df["open_time"].dt.floor(_to_floor_freq(oi_period))
|
||||||
@@ -554,6 +554,16 @@ def _alert_loop():
|
|||||||
df = df.drop(columns=["open_time_r","open_time_oi"], errors="ignore")
|
df = df.drop(columns=["open_time_r","open_time_oi"], errors="ignore")
|
||||||
df["sumOpenInterest"] = df["sumOpenInterest"].ffill()
|
df["sumOpenInterest"] = df["sumOpenInterest"].ffill()
|
||||||
except: pass
|
except: pass
|
||||||
|
try:
|
||||||
|
fr = get_funding_rate(symbol, 200)
|
||||||
|
if not fr.empty:
|
||||||
|
fr_m = fr[["fundingTime","fundingRate"]].rename(columns={"fundingTime":"open_time"})
|
||||||
|
fr_m["open_time"] = fr_m["open_time"].dt.floor(_to_floor_freq("1h"))
|
||||||
|
df["open_time_r2"] = df["open_time"].dt.floor(_to_floor_freq("1h"))
|
||||||
|
df = df.merge(fr_m, left_on="open_time_r2", right_on="open_time", how="left", suffixes=("","_fr"))
|
||||||
|
df = df.drop(columns=["open_time_r2","open_time_fr"], errors="ignore")
|
||||||
|
df["fundingRate"] = df["fundingRate"].ffill().fillna(0)
|
||||||
|
except: pass
|
||||||
df = compute_indicators(df, interval)
|
df = compute_indicators(df, interval)
|
||||||
check_and_alert(df, symbol, interval)
|
check_and_alert(df, symbol, interval)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user