diff --git a/config.py b/config.py index b66caa0..91a364c 100644 --- a/config.py +++ b/config.py @@ -33,8 +33,8 @@ KR_COINS = { "KAIA": "KAIA", "LINK": "Chainlink", "ONDO": "ONDO", - "PEPE": "PEPE", "PENGU": "Pudgy Penguins", + "PEPE": "PEPE", "POL": "POL", "SAND": "Sandbox", "SEI": "SEI", diff --git a/monitor_coin_ADA.py b/monitor_coin_ADA.py new file mode 100644 index 0000000..d8b6d43 --- /dev/null +++ b/monitor_coin_ADA.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'ADA' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_APE.py b/monitor_coin_APE.py new file mode 100644 index 0000000..7ebf728 --- /dev/null +++ b/monitor_coin_APE.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'APE' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_ARB.py b/monitor_coin_ARB.py new file mode 100644 index 0000000..52df465 --- /dev/null +++ b/monitor_coin_ARB.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'ARB' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_BONK.py b/monitor_coin_BONK.py new file mode 100644 index 0000000..331d7e0 --- /dev/null +++ b/monitor_coin_BONK.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'BONK' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_ENA.py b/monitor_coin_ENA.py new file mode 100644 index 0000000..e55cb1b --- /dev/null +++ b/monitor_coin_ENA.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'ENA' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_HBAR.py b/monitor_coin_HBAR.py new file mode 100644 index 0000000..e5e537b --- /dev/null +++ b/monitor_coin_HBAR.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'HBAR' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_KAIA.py b/monitor_coin_KAIA.py new file mode 100644 index 0000000..d99f757 --- /dev/null +++ b/monitor_coin_KAIA.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'KAIA' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_LINK.py b/monitor_coin_LINK.py new file mode 100644 index 0000000..99a2ec9 --- /dev/null +++ b/monitor_coin_LINK.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'LINK' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_ONDO.py b/monitor_coin_ONDO.py new file mode 100644 index 0000000..7868dec --- /dev/null +++ b/monitor_coin_ONDO.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'ONDO' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_PENGU.py b/monitor_coin_PENGU.py new file mode 100644 index 0000000..4c47ef4 --- /dev/null +++ b/monitor_coin_PENGU.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'PENGU' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_PEPE.py b/monitor_coin_PEPE.py new file mode 100644 index 0000000..a9d8a20 --- /dev/null +++ b/monitor_coin_PEPE.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'PEPE' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_POL.py b/monitor_coin_POL.py new file mode 100644 index 0000000..54e9ac8 --- /dev/null +++ b/monitor_coin_POL.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'POL' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_SAND.py b/monitor_coin_SAND.py new file mode 100644 index 0000000..e172401 --- /dev/null +++ b/monitor_coin_SAND.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'SAND' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_SEI.py b/monitor_coin_SEI.py new file mode 100644 index 0000000..e60acd4 --- /dev/null +++ b/monitor_coin_SEI.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'SEI' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_SHIB.py b/monitor_coin_SHIB.py new file mode 100644 index 0000000..8bb11a6 --- /dev/null +++ b/monitor_coin_SHIB.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'SHIB' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_STORJ.py b/monitor_coin_STORJ.py new file mode 100644 index 0000000..ec4e6a1 --- /dev/null +++ b/monitor_coin_STORJ.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'STORJ' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_SUI.py b/monitor_coin_SUI.py new file mode 100644 index 0000000..5c90bd9 --- /dev/null +++ b/monitor_coin_SUI.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'SUI' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_TON.py b/monitor_coin_TON.py new file mode 100644 index 0000000..170982b --- /dev/null +++ b/monitor_coin_TON.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'TON' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_TRX.py b/monitor_coin_TRX.py new file mode 100644 index 0000000..d0791b5 --- /dev/null +++ b/monitor_coin_TRX.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'TRX' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_UXLINK.py b/monitor_coin_UXLINK.py new file mode 100644 index 0000000..504b879 --- /dev/null +++ b/monitor_coin_UXLINK.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'UXLINK' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_VIRTUAL.py b/monitor_coin_VIRTUAL.py new file mode 100644 index 0000000..106b179 --- /dev/null +++ b/monitor_coin_VIRTUAL.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'VIRTUAL' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_WLD.py b/monitor_coin_WLD.py new file mode 100644 index 0000000..2a7a3ff --- /dev/null +++ b/monitor_coin_WLD.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'WLD' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_XLM.py b/monitor_coin_XLM.py new file mode 100644 index 0000000..09d0df5 --- /dev/null +++ b/monitor_coin_XLM.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'XLM' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol) diff --git a/monitor_coin_XRP.py b/monitor_coin_XRP.py new file mode 100644 index 0000000..d0602ab --- /dev/null +++ b/monitor_coin_XRP.py @@ -0,0 +1,164 @@ +import pandas as pd +from dateutil.relativedelta import relativedelta +from datetime import datetime +import sqlite3 +import time +import requests +import json +from config import * + +from monitor import Monitor + +class MonitorCoin (Monitor): + """자산(코인/주식/ETF) 모니터링 및 매수 실행 클래스""" + + def __init__(self, cooldown_file: str = 'coins_buy_time.json') -> None: + super().__init__(cooldown_file) + + # ------------- Data fetch ------------- + def get_coin_data(self, symbol: str, interval: int = 60, to: str | None = None, retries: int = 3) -> pd.DataFrame | None: + for attempt in range(retries): + try: + if to is None: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200").format(interval, symbol) + else: + url = ("https://api.bithumb.com/v1/candles/minutes/{}?market=KRW-{}&count=200&to={}").format(interval, symbol, to) + 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['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_coin_more_data(self, symbol: str, interval: int, bong_count: int = 3000) -> pd.DataFrame: + to = datetime.now() + data: pd.DataFrame | None = None + while data is None or len(data) < bong_count: + if data is None: + data = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + else: + previous_count = len(data) + df = self.get_coin_data(symbol, interval, to.strftime("%Y-%m-%d %H:%M:%S")) + data = pd.concat([data, df], ignore_index=True) + if previous_count == len(data): + break + time.sleep(0.3) + to = to - relativedelta(minutes=interval * 200) + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def get_coin_saved_data(self, symbol: str, interval: int, data: pd.DataFrame) -> pd.DataFrame: + conn = sqlite3.connect('coins.db') + cursor = conn.cursor() + for i in range(1, len(data)): + cursor.execute( + "SELECT * from " + symbol + " where CODE = ? and ymdhms = ? and interval = ?", + (symbol, data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), interval), + ) + arr = cursor.fetchone() + if not arr: + cursor.execute( + "INSERT INTO " + symbol + " (interval, CODE, NAME, ymdhms, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ( + interval, + symbol, + KR_COINS[symbol], + data['datetime'].iloc[-i].strftime('%Y-%m-%d %H:%M:%S'), + data['datetime'].iloc[-i].strftime('%Y%m%d'), + data['datetime'].iloc[-i].strftime('%H%M%S'), + data['Close'].iloc[-i], + data['Open'].iloc[-i], + data['High'].iloc[-i], + data['Low'].iloc[-i], + data['Volume'].iloc[-i], + ), + ) + else: + break + cursor.execute( + "select * from (SELECT Open,Close,High,Low,Volume,ymdhms as datetime from " + + symbol + + " order by ymdhms desc limit 5000) subquery order by datetime" + ) + result = cursor.fetchall() + conn.commit() + cursor.close() + conn.close() + df = pd.DataFrame(result) + df.columns = ['Open', 'Close', 'High', 'Low', 'Volume', 'datetime'] + df = df.set_index('datetime') + df = df.sort_index() + df['datetime'] = df.index + return df + + def get_coin_some_data(self, symbol: str, interval: int) -> pd.DataFrame: + data = self.get_coin_data(symbol, interval) + data_1 = self.get_coin_data(symbol, interval=1) + data_1.at[data_1.index[-1], 'Volume'] = data_1['Volume'].iloc[-1] * 60 + saved_data = self.get_coin_saved_data(symbol, interval, data) + data = pd.concat([data, saved_data, data_1.iloc[[-1]]], ignore_index=True) + data['datetime'] = pd.to_datetime(data['datetime'], format='%Y-%m-%d %H:%M:%S') + data = data.set_index('datetime') + data = data.sort_index() + data = data.drop_duplicates(keep='first') + data["datetime"] = data.index + return data + + def monitor_coins(self, symbol) -> None: + print("[{}] KRW COINs: {}".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ','.join(KR_COINS.keys()))) + + interval = 60 + data = self.get_coin_some_data(symbol, interval) + if data is not None and not data.empty: + try: + data = self.calculate_technical_indicators(data) + recent_data = self.check_buy_point(symbol, data) + if recent_data['buy_point'].iloc[-1] != 1: + return + buy_success = self.buy_ticker(symbol, recent_data) + if not buy_success: + return + 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 + # ------------- Scheduler ------------- + def run_schedule(self, ticker) -> None: + + while True: + self.monitor_coins(symbol) + time.sleep(1) + +if __name__ == "__main__": + symbol = 'XRP' + cooldown_file = 'coins_buy_'+symbol+'.json' + + MonitorCoin(cooldown_file).run_schedule(symbol)