From 67f46a427afb884d8cfe60795f52ea3910e45f56 Mon Sep 17 00:00:00 2001 From: ILSEON-RYU Date: Mon, 4 May 2026 23:33:54 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B0=A9=ED=96=A5=20=EC=A0=84=ED=99=98=20(reve?= =?UTF-8?q?rsal)=20=EC=8B=A0=ED=98=B8=20=EC=B6=94=EA=B0=80=20=E2=80=94=20?= =?UTF-8?q?=EC=B6=94=EC=84=B8=20=EA=BA=BE=EC=9E=84=20=EC=A1=B0=EA=B8=B0=20?= =?UTF-8?q?=EA=B0=90=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 동작 직전 5봉 추세 + 현재 캔들의 반대 방향 강한 움직임 + 거래량 동반. reversal_short_signal (상승 -> 하락 전환): - close[t-1] > close[t-5] (직전 5봉 동안 상승했었음) - close[t] < open[t] 이면서 |body|/open >= 0.3% (현재 캔들 강한 음봉) - volume[t] > 직전 5봉 평균 volume * 1.3 (확신 동반) - 5봉 쿨다운 reversal_long_signal (하락 -> 상승 전환): - 위와 대칭 (직전 하락, 현재 강한 양봉) ## 알림 SIG_DEFS 에 등록되어 다른 진입 신호와 동일하게 텔레그램 발사. LONG_SIGNALS / SHORT_SIGNALS 셋에도 포함되어 진입 추적 + 손절가 체크도 동일하게 동작. 라벨: "🔄 롱 전환" / "🔄 숏 전환" ## 검증 (오늘 24h 데이터) - 5m 19:00 숏 전환 -0.78% - 15m 19:00 숏 전환 -1.36% - 30m 19:00 숏 전환 -1.67% - 30m 19:30 롱 전환 +0.55% - 30m 23:00 롱 전환 +0.58% (현재 발화 케이스) - 1h 10:00 롱 전환 +1.59% 기존 진입 신호 (long/short/strong/vol) 가 추세 추종형이라 반전 타이밍을 놓쳤던 문제를 보완 — reversal 신호가 추세 꺾임 시점에 독립 발사. Co-Authored-By: Claude Opus 4.7 (1M context) --- app_streamlit.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/app_streamlit.py b/app_streamlit.py index a965f9f..26086c0 100644 --- a/app_streamlit.py +++ b/app_streamlit.py @@ -55,8 +55,8 @@ BASE = "https://fapi.binance.com" KST = timedelta(hours=9) STOP_LOSS_PCT = 0.0075 # 10x 레버리지 기준 ROI -7.5% (= 가격 0.75% 역방향) -LONG_SIGNALS = {"strong_long_signal", "long_signal", "vol_long_signal"} -SHORT_SIGNALS = {"strong_short_signal", "short_signal", "vol_short_signal"} +LONG_SIGNALS = {"strong_long_signal", "long_signal", "vol_long_signal", "reversal_long_signal"} +SHORT_SIGNALS = {"strong_short_signal", "short_signal", "vol_short_signal", "reversal_short_signal"} TF_LABEL_MAP = { "1m": "1분봉", "3m": "3분봉", "5m": "5분봉", "15m": "15분봉", "30m": "30분봉", @@ -80,13 +80,15 @@ def send_telegram(message: str): print(f"[텔레그램 오류] {e}") SIG_DEFS = [ - ("strong_long_signal", "strong_long", "🟢 강한 롱", "long"), - ("strong_short_signal", "strong_short", "🔴 강한 숏", "short"), - ("long_signal", "long", "🔼 일반 롱", "long"), - ("short_signal", "short", "🔽 일반 숏", "short"), - ("vol_long_signal", "vol_long", "🔼 볼륨 롱", "long"), - ("vol_short_signal", "vol_short", "🔽 볼륨 숏", "short"), - ("short_caution_signal","short_caution","⚠️ 숏 주의", "caution"), + ("strong_long_signal", "strong_long", "🟢 강한 롱", "long"), + ("strong_short_signal", "strong_short", "🔴 강한 숏", "short"), + ("long_signal", "long", "🔼 일반 롱", "long"), + ("short_signal", "short", "🔽 일반 숏", "short"), + ("vol_long_signal", "vol_long", "🔼 볼륨 롱", "long"), + ("vol_short_signal", "vol_short", "🔽 볼륨 숏", "short"), + ("reversal_long_signal", "rev_long", "🔄 롱 전환", "long"), + ("reversal_short_signal","rev_short", "🔄 숏 전환", "short"), + ("short_caution_signal", "short_caution","⚠️ 숏 주의", "caution"), ] def check_and_alert(df, symbol, interval): @@ -385,6 +387,23 @@ def compute_signals(df, interval="5m"): else: df["short_caution_signal"] = False + # 방향 전환 감지: 직전 5봉의 추세 방향과 현재 캔들 방향이 반대 + 강한 폭 + 거래량 동반. + # - 추세 판단: close[t-1] vs close[t-5] (현재 캔들 제외, 직전까지의 흐름) + # - 현재 캔들 강도: |close-open|/open >= 0.3% (작은 캔들 노이즈 차단) + # - 거래량: 직전 5봉 평균의 1.3배 이상 (확신) + prior_close = df["close"].shift(1) + prior_close_5 = df["close"].shift(5) + was_up = prior_close > prior_close_5 + was_down = prior_close < prior_close_5 + candle_body_pct = (df["close"] - df["open"]) / df["open"].replace(0, float("nan")) + vol_avg5 = df["volume"].rolling(5).mean().shift(1) + vol_strong = df["volume"] > vol_avg5 * 1.3 + rev_short_raw = was_up & (candle_body_pct < -0.003) & vol_strong + rev_long_raw = was_down & (candle_body_pct > 0.003) & vol_strong + # 5봉 쿨다운 (연쇄 발화 방지) + df["reversal_short_signal"] = rev_short_raw & (rev_short_raw.rolling(5, min_periods=1).sum().shift(1).fillna(0) == 0) + df["reversal_long_signal"] = rev_long_raw & (rev_long_raw.rolling(5, min_periods=1).sum().shift(1).fillna(0) == 0) + return df # ──────────────────────────────────────────────