This commit is contained in:
dsyoon
2025-07-27 20:40:16 +09:00
parent f19cf092e9
commit 7251826f38
2 changed files with 23 additions and 4 deletions

View File

@@ -16,6 +16,10 @@ BREAKOUT_LOOKBACK = 30 # U자 반등 후 돌파 판단에 사용할 과거 캔
BREAKOUT_WEEK_LOOKBACK = 42 # 4시간봉 1주일 ≒ 42개 BREAKOUT_WEEK_LOOKBACK = 42 # 4시간봉 1주일 ≒ 42개
BREAKOUT_WEEK_LIMIT = 0.05 # 1주일 대비 5% 미만 상승 조건 BREAKOUT_WEEK_LIMIT = 0.05 # 1주일 대비 5% 미만 상승 조건
# 장기간 저항선 돌파 감지 설정
RESISTANCE_LOOKBACK = 120 # 저항선 판단을 위한 과거 캔들 수 (예: 120개)
RESISTANCE_BREAK_THRESHOLD = 0.01 # 저항선 대비 1% 이상 돌파 시 신호
KR_COINS = { KR_COINS = {
"ADA": "ADA", "ADA": "ADA",
"APE": "ApeCoin", "APE": "ApeCoin",

View File

@@ -131,6 +131,16 @@ def check_buy_signals(symbol, data):
and week_change <= BREAKOUT_WEEK_LIMIT and week_change <= BREAKOUT_WEEK_LIMIT
): ):
breakout_signal = True breakout_signal = True
# 장기간 저항선 돌파 여부 계산 (LONG RESISTANCE BREAKOUT)
long_breakout_signal = False
if len(data) >= RESISTANCE_LOOKBACK + 1:
resistance_level = data['Close'].iloc[-RESISTANCE_LOOKBACK-1:-1].max()
previous_closes = data['Close'].iloc[-RESISTANCE_LOOKBACK-1:-1]
# 과거 구간에서 저항선 이상으로 종가가 한번도 올라가지 않은 경우 + 현재 가격이 저항선 돌파
if (previous_closes <= resistance_level * (1 + RESISTANCE_BREAK_THRESHOLD)).all() and \
current_price > resistance_level * (1 + RESISTANCE_BREAK_THRESHOLD):
long_breakout_signal = True
# RSI 과매도 신호 (RSI < 30) # RSI 과매도 신호 (RSI < 30)
if not isinstance(latest['Upper'], float): if not isinstance(latest['Upper'], float):
@@ -152,7 +162,8 @@ def check_buy_signals(symbol, data):
'macd_signal': macd_signal, 'macd_signal': macd_signal,
'ma_signal': ma_signal, 'ma_signal': ma_signal,
'volume_signal': volume_signal, 'volume_signal': volume_signal,
'breakout_signal': breakout_signal 'breakout_signal': breakout_signal,
'long_breakout_signal': long_breakout_signal
} }
# 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주 # 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주
@@ -168,7 +179,7 @@ def check_buy_signals(symbol, data):
'signal_line': latest['Signal'].iloc[0], 'signal_line': latest['Signal'].iloc[0],
'buy_signals': buy_signals, 'buy_signals': buy_signals,
'signal_count': signal_count, 'signal_count': signal_count,
'buy': breakout_signal or ((bb_signal and rsi_signal) or (signal_count >= 2 and (bb_signal or rsi_signal))) 'buy': long_breakout_signal or breakout_signal or ((bb_signal and rsi_signal) or (signal_count >= 2 and (bb_signal or rsi_signal)))
} }
else: else:
rsi_signal = latest['RSI'] < 30 rsi_signal = latest['RSI'] < 30
@@ -189,7 +200,8 @@ def check_buy_signals(symbol, data):
'macd_signal': macd_signal, 'macd_signal': macd_signal,
'ma_signal': ma_signal, 'ma_signal': ma_signal,
'volume_signal': volume_signal, 'volume_signal': volume_signal,
'breakout_signal': breakout_signal 'breakout_signal': breakout_signal,
'long_breakout_signal': long_breakout_signal
} }
# 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주 # 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주
@@ -205,7 +217,7 @@ def check_buy_signals(symbol, data):
'signal_line': latest['Signal'], 'signal_line': latest['Signal'],
'buy_signals': buy_signals, 'buy_signals': buy_signals,
'signal_count': signal_count, 'signal_count': signal_count,
'buy': breakout_signal or ((bb_signal and rsi_signal) or (signal_count >= 2 and (bb_signal or rsi_signal))) 'buy': long_breakout_signal or breakout_signal or ((bb_signal and rsi_signal) or (signal_count >= 2 and (bb_signal or rsi_signal)))
} }
def format_message(info, market_type): def format_message(info, market_type):
@@ -238,6 +250,9 @@ def format_message(info, market_type):
if info['buy_signals'].get('breakout_signal'): if info['buy_signals'].get('breakout_signal'):
message += "- U자 반등 돌파" message += "- U자 반등 돌파"
count += 1 count += 1
if info['buy_signals'].get('long_breakout_signal'):
message += "- 장기 저항 돌파"
count += 1
message += "\n" message += "\n"
message = message.replace("{count}", str(count)) message = message.replace("{count}", str(count))
return message return message