From e681e9b326c246770e6d955c6166e646aef74e53 Mon Sep 17 00:00:00 2001 From: dsyoon Date: Thu, 1 May 2025 11:41:06 +0900 Subject: [PATCH] init --- config.py | 4 -- stock_monitor.py | 127 +++++++++++++++++++++++++++++++---------------- 2 files changed, 85 insertions(+), 46 deletions(-) diff --git a/config.py b/config.py index 68985a0..fdeaae6 100644 --- a/config.py +++ b/config.py @@ -202,12 +202,8 @@ KR_ETFS = { "032190.KQ": "다우데이타 / IT,클라우드", "200130.KQ": "콜마비앤에이치 / 건강기능식품", "091700.KQ": "파트론 / 전장,카메라모듈", - "036490.KQ": "SK머티리얼즈 / 반도체 소재", "086900.KQ": "메디톡스 / 바이오,제약", "039860.KQ": "나노엔텍 / 바이오,진단", - "048260.KQ": "오스템임플란트 / 의료기기", - "060250.KQ": "NHN한국사이버결제 / 핀테크,결제", - "090460.KQ": "비에이치 / 전자부품", "041960.KQ": "코미팜 / 바이오,제약", "058820.KQ": "CMG제약 / 바이오,제약" } diff --git a/stock_monitor.py b/stock_monitor.py index 040e8f0..edf49c0 100644 --- a/stock_monitor.py +++ b/stock_monitor.py @@ -87,41 +87,78 @@ def check_buy_signals(symbol, data): bb_signal = distance < BOLLINGER_THRESHOLD # RSI 과매도 신호 (RSI < 30) - rsi_signal = latest['RSI'].iloc[0] < 30 + if not isinstance(latest['Upper'], float): + rsi_signal = latest['RSI'].iloc[0] < 30 - # MACD 신호 (MACD가 시그널 라인을 상향 돌파) - macd_signal = (prev['MACD'].iloc[0] < prev['Signal'].iloc[0]) and (latest['MACD'].iloc[0] > latest['Signal'].iloc[0]) - - # 이동평균선 골든크로스 임박 또는 발생 - ma_signal = (prev['MA5'].iloc[0] < prev['MA20'].iloc[0]) and (latest['MA5'].iloc[0] >= latest['MA20'].iloc[0]) - - # 거래량 증가 신호 (5일 평균 대비 150% 이상) - volume_signal = latest['Volume'].iloc[0] > (latest['Volume_MA5'].iloc[0] * 1.5) - - # 종합 신호 - buy_signals = { - 'bb_signal': bb_signal, - 'rsi_signal': rsi_signal, - 'macd_signal': macd_signal, - 'ma_signal': ma_signal, - 'volume_signal': volume_signal - } - - # 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주 - signal_count = sum(1 for signal in buy_signals.values() if signal) - - return { - 'symbol': symbol, - 'price': current_price, - 'lower_band': lower_band, - 'distance': distance, - 'rsi': latest['RSI'].iloc[0], - 'macd': latest['MACD'].iloc[0], - 'signal_line': latest['Signal'].iloc[0], - 'buy_signals': buy_signals, - 'signal_count': signal_count, - 'buy': signal_count >= 3 - } + # MACD 신호 (MACD가 시그널 라인을 상향 돌파) + macd_signal = (prev['MACD'].iloc[0] < prev['Signal'].iloc[0]) and (latest['MACD'].iloc[0] > latest['Signal'].iloc[0]) + + # 이동평균선 골든크로스 임박 또는 발생 + ma_signal = (prev['MA5'].iloc[0] < prev['MA20'].iloc[0]) and (latest['MA5'].iloc[0] >= latest['MA20'].iloc[0]) + + # 거래량 증가 신호 (5일 평균 대비 150% 이상) + volume_signal = latest['Volume'].iloc[0] > (latest['Volume_MA5'].iloc[0] * 1.5) + + # 종합 신호 + buy_signals = { + 'bb_signal': bb_signal, + 'rsi_signal': rsi_signal, + 'macd_signal': macd_signal, + 'ma_signal': ma_signal, + 'volume_signal': volume_signal + } + + # 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주 + signal_count = sum(1 for signal in buy_signals.values() if signal) + + return { + 'symbol': symbol, + 'price': current_price, + 'lower_band': lower_band, + 'distance': distance, + 'rsi': latest['RSI'].iloc[0], + 'macd': latest['MACD'].iloc[0], + 'signal_line': latest['Signal'].iloc[0], + 'buy_signals': buy_signals, + 'signal_count': signal_count, + 'buy': signal_count >= 3 + } + else: + rsi_signal = latest['RSI'] < 30 + + # MACD 신호 (MACD가 시그널 라인을 상향 돌파) + macd_signal = (prev['MACD'] < prev['Signal']) and (latest['MACD'] > latest['Signal']) + + # 이동평균선 골든크로스 임박 또는 발생 + ma_signal = (prev['MA5'] < prev['MA20']) and (latest['MA5'] >= latest['MA20']) + + # 거래량 증가 신호 (5일 평균 대비 150% 이상) + volume_signal = latest['Volume'] > (latest['Volume_MA5'] * 1.5) + + # 종합 신호 + buy_signals = { + 'bb_signal': bb_signal, + 'rsi_signal': rsi_signal, + 'macd_signal': macd_signal, + 'ma_signal': ma_signal, + 'volume_signal': volume_signal + } + + # 최소 3개 이상의 신호가 동시에 발생할 때 매수 신호로 간주 + signal_count = sum(1 for signal in buy_signals.values() if signal) + + return { + 'symbol': symbol, + 'price': current_price, + 'lower_band': lower_band, + 'distance': distance, + 'rsi': latest['RSI'], + 'macd': latest['MACD'], + 'signal_line': latest['Signal'], + 'buy_signals': buy_signals, + 'signal_count': signal_count, + 'buy': signal_count >= 3 + } def format_message(info, market_type): message = "" @@ -132,19 +169,25 @@ def format_message(info, market_type): message += f"현재가: {'$' if market_type == 'US' else '₩'}{info['price']:.2f}\n" # 매수 신호 상세 정보 + count = 0 if any(info['buy_signals'].values()): - message += "📊 매수 신호:\n" + message += "📊 매수 신호:" if info['buy_signals']['bb_signal']: - message += "- 볼린저 밴드 하단 근접 (근접도: {:.1f}%)\n".format(info['distance'] * 100) + message += "- 볼린저 밴드 하단 근접 (근접도: {:.1f}%),".format(info['distance'] * 100) + count += 1 if info['buy_signals']['rsi_signal']: - message += f"- RSI 과매도 구간 (RSI: {info['rsi']:.1f})\n" + message += f"- RSI 과매도 구간 (RSI: {info['rsi']:.1f})," + count += 1 if info['buy_signals']['macd_signal']: - message += "- MACD 골든크로스\n" + message += "- MACD 골든크로스," + count += 1 if info['buy_signals']['ma_signal']: - message += "- 이동평균선 골든크로스\n" + message += "- 이동평균선 골든크로스," + count += 1 if info['buy_signals']['volume_signal']: - message += "- 거래량 급증\n" - + message += "- 거래량 급증" + count += 1 + message += f" ({count})" return message def get_coin_data(symbol, retries=3): @@ -297,9 +340,9 @@ def monitor_coins(): def run_schedule(): + monitor_coins() monitor_kr_stocks() monitor_us_stocks() - monitor_coins() # 코인 모니터링 스케줄 (매시간 1분, 11분, 21분, 31분, 41분, 51분) for minute in [1, 11, 21, 31, 41, 51]: