From d469df8759a6a9c013ad2bf3bba0cf310e17e473 Mon Sep 17 00:00:00 2001 From: dsyoon Date: Sat, 26 Apr 2025 00:13:33 +0900 Subject: [PATCH] init --- config.py | 13 +++++++++ requirements.txt | 8 ++++- stock_monitor.py | 76 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/config.py b/config.py index 72b4251..dc541bf 100644 --- a/config.py +++ b/config.py @@ -95,6 +95,19 @@ KR_ETFS = { "376410.KS": 'TIGER 탄소효율그린뉴딜' } +KR_COINS = { + "ADA": "ADA", + "BTC": "BTC", + "ETH": "ETH", + "HBAR": "HBAR", + "LINK": "LINK", + "ONDO": "ONDO", + "SOL": "SOL", + "SUI": "SUI", + "XLM": "XLM", + "XRP": "XRP", +} + # 볼린저 밴드 설정 BOLLINGER_PERIOD = 20 # 볼린저 밴드 기간 BOLLINGER_STD = 2 # 표준편차 승수 diff --git a/requirements.txt b/requirements.txt index ce48393..b1a71ae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,9 @@ yfinance pandas -numpy \ No newline at end of file +numpy +ccxt +PyJWT +pycurl +certifi +python-dateutil +python-telegram-bot diff --git a/stock_monitor.py b/stock_monitor.py index 5634cca..83423a9 100644 --- a/stock_monitor.py +++ b/stock_monitor.py @@ -3,6 +3,8 @@ import pandas as pd from datetime import datetime, timedelta import telegram import time +import requests +import json import asyncio from multiprocessing import Pool from config import * @@ -27,9 +29,14 @@ def check_bollinger_bands(symbol, data): if len(data) < BOLLINGER_PERIOD: return None latest = data.iloc[-1] - upper_band = latest['Upper'].iloc[0] - lower_band = latest['Lower'].iloc[0] - current_price = latest['Close'].iloc[0] + if isinstance(latest['Upper'], float): + upper_band = latest['Upper'] + lower_band = latest['Lower'] + current_price = latest['Close'] + else: + upper_band = latest['Upper'].iloc[0] + lower_band = latest['Lower'].iloc[0] + current_price = latest['Close'].iloc[0] distance = (current_price - lower_band) / (upper_band - lower_band) return { 'symbol': symbol, @@ -38,6 +45,42 @@ def check_bollinger_bands(symbol, data): 'distance': distance } +def get_coin_data(symbol, retries=3): + for attempt in range(retries): + try: + url = ('https://api.bithumb.com/v1/candles/days?market=KRW-{}&count=100').format(symbol) + headers = {"accept": "application/json"} + response = requests.get(url, headers=headers) + json_data = json.loads(response.text) + df_temp = pd.DataFrame(json_data) + df_temp = df_temp.sort_index(ascending=False) + if 'candle_date_time_kst' not in df_temp: + return None + + data = pd.DataFrame() + # data.columns = ['datetime', 'open', 'close', 'high', 'low', 'volume'] + # data['datetime'] = pd.to_datetime(data_temp['candle_date_time_kst']) + data['datetime'] = pd.to_datetime(df_temp['candle_date_time_kst'], format='%Y-%m-%dT%H:%M:%S') + data['Open'] = df_temp['opening_price'] + data['Close'] = df_temp['trade_price'] + data['High'] = df_temp['high_price'] + data['Low'] = df_temp['low_price'] + data['Volume'] = df_temp['candle_acc_trade_volume'] + data = data.set_index('datetime') + data = data.astype(float) + data["datetime"] = data.index + + if not data.empty: + return data + print(f"No data received for {symbol}, attempt {attempt + 1}") + time.sleep(0.5) + except Exception as e: + print(f"Attempt {attempt + 1} failed for {symbol}: {str(e)}") + if attempt < retries - 1: + time.sleep(5) + continue + return None + def get_stock_data(symbol, retries=3): for attempt in range(retries): try: @@ -54,7 +97,7 @@ def get_stock_data(symbol, retries=3): if not data.empty: return data print(f"No data received for {symbol}, attempt {attempt + 1}") - time.sleep(2) + time.sleep(0.5) except Exception as e: print(f"Attempt {attempt + 1} failed for {symbol}: {str(e)}") if attempt < retries - 1: @@ -117,5 +160,30 @@ def monitor_stocks(): return +def monitor_coins(): + # 미국 주식 모니터링 + print("Monitoring KR Coins...") + for symbol in KR_COINS: + data = get_coin_data(symbol) + if data is not None and not data.empty: + try: + data = calculate_bollinger_bands(data) + info = check_bollinger_bands(symbol, data) + info['name'] = KR_COINS[symbol] + print(" - {} ({}): {:.2f} ({:.2f})".format(info['name'], symbol, info['price'], info['distance'])) + + if info['distance'] <= ALERT_THRESHOLD: + sendAlertMsg(info, "US") + print(f"Alert generated for {symbol}") + except Exception as e: + print(f"Error processing data for {symbol}: {str(e)}") + else: + print(f"Data for {symbol} is empty or None.") + time.sleep(0.5) + + return + + if __name__ == "__main__": + monitor_coins() monitor_stocks()