From a9ad52f3d76a73f83d2a2a9e5894737058d8096f Mon Sep 17 00:00:00 2001 From: ILSEON-RYU Date: Mon, 4 May 2026 22:22:35 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B7=A8=EC=86=8C=20=EC=95=8C=EB=A6=BC=20formi?= =?UTF-8?q?ng=20candle=20=EB=A7=88=EA=B0=90=20=EB=8C=80=EA=B8=B0=20X=20?= =?UTF-8?q?=E2=80=94=20=EC=8B=A0=ED=98=B8=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EB=A9=B4=20=EC=A6=89=EC=8B=9C=20=EC=B7=A8=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 사례 2026-05-04 22:00 15분봉 강한 숏 진입 알림 발사 후 같은 캔들 마감 (22:15) 후 [취소 알림]. 사용자: "15분 봉을 15분 후에 취소하는 거냐" ## 원인 pending_groups 검증 로직이 forming candle 동안에는 검증 skip 하고, candle 이 closed 된 다음에만 신호 재확인. forming 중 신호가 깜빡 False 로 바뀌어도 다음 polling 에서 알 수 없었음. 15분봉 의 경우 forming 기간이 15분 -> 취소 알림이 진입 알림 후 최대 15분 늦게 도착 (사용자 입장 ROI 마이너스 누적). ## 수정 forming/closed 구분 없이 매 polling (30s) 마다 pending 항목의 신호 상태 재확인. 사라졌으면 즉시 [취소 알림] 발송 + 진입 추적 클리어. 흐름: - forming + 신호 살아있음 -> 계속 감시 (pending 유지) - forming + 신호 사라짐 -> 즉시 취소 (~30초 이내) - closed + 신호 살아있음 -> 확정, pending 에서 제거 (조용히) - closed + 신호 사라짐 -> 즉시 취소 (기존 동작 유지) per-candle dedup 으로 같은 캔들 재발사는 차단됨 -> 깜빡임 폭주 X. Co-Authored-By: Claude Opus 4.7 (1M context) --- app_streamlit.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app_streamlit.py b/app_streamlit.py index a46ea69..692f0ae 100644 --- a/app_streamlit.py +++ b/app_streamlit.py @@ -95,22 +95,26 @@ def check_and_alert(df, symbol, interval): return forming_ct = df.iloc[-1]["open_time"] - # Phase 1 — pending_groups 검증. + # Phase 1 — pending_groups 검증. forming candle 이라도 매 polling 마다 신호 + # 상태 확인. 사라지면 즉시 [취소 알림] (캔들 마감까지 기다리지 않음). new_pending = [] for p in alert_state.pending_groups: if p["interval"] != interval: new_pending.append(p) continue ct = p["candle_time"] - if ct == forming_ct: - new_pending.append(p) - continue row_match = df[df["open_time"] == ct] if row_match.empty: - continue + continue # 캔들이 df 윈도우 밖 — 검증 포기, drop row = row_match.iloc[0] any_still_true = any(bool(row.get(s, False)) for s in p["sig_cols"]) - if not any_still_true: + if any_still_true: + if ct == forming_ct: + # forming 중 + 신호 살아있음 → 계속 감시 + new_pending.append(p) + # closed + 신호 살아있음 → 확정, pending 에서 제거 + else: + # 신호 사라짐 (forming/closed 무관) → 즉시 취소 알림 send_telegram(f"[취소 알림]\n{p['msg']}") le = alert_state.long_entry.get(interval) se = alert_state.short_entry.get(interval)