diff --git a/HTS_etf.py b/HTS_etf.py index b4b9cef..264ddb4 100644 --- a/HTS_etf.py +++ b/HTS_etf.py @@ -37,15 +37,11 @@ class HTS_etf(HTS): ichimokuCloud = None - def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP): + def __init__(self, RESOURCE_PATH): super().__init__(RESOURCE_PATH) self.RESOURCE_PATH = RESOURCE_PATH - self.SELL_GAP = SELL_GAP - self.stock_code = stock_code - self.stock_name = stock_name - self.orderChecker = OrderChecker(self.RESOURCE_PATH, self.stock_code) self.bot = TelegramBot() self.stockStatus = StockStatus(RESOURCE_PATH) @@ -55,7 +51,7 @@ class HTS_etf(HTS): self.macd = MACD() self.ichimokuCloud = IchimokuCloud() - self.buySellChecker = BuySellChecker(self.RESOURCE_PATH, self.stock_code) + self.buySellChecker = BuySellChecker(self.RESOURCE_PATH) return @@ -412,89 +408,89 @@ class HTS_etf(HTS): return result - def buyRealTime(self, today, MAX_PRICE=30000): + def buyRealTime(self, stocks, today, MAX_PRICE=30000): + self.orderChecker = OrderChecker(self.RESOURCE_PATH, stock_code) + BUY_LIST = {'buy_count': 0, 'buy_avg': 0, 'buy_list': []} print("START...") THIS_TIME = datetime.now() - LAST_DATA = self.getLastData(self.stock_code, today) + #LAST_DATA = self.getLastData(stock_code, today) while datetime.strptime(today + " 060000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100",'%Y%m%d %H%M%S'): if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 090100", '%Y%m%d %H%M%S'): - self.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(self.stock_code, self.stock_name, MAX_PRICE)) + self.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(stock_code, stock_name, MAX_PRICE)) if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'): - # 매도를 체크한다. - check = self.sellStocks(self.stock_code, self.stock_name) + for stock in stocks: + stock_code = stock['stock_code'] + stock_name = stock['stock_name'] - # jangoDic[code]['장부가'], jangoDic[code]['평가금액'], jangoDic[code]['평가손익'], - buy_avg, amount, profit = self.getBallance(self.stock_code) - if check or buy_avg == 0: - BUY_LIST['buy_avg'] = 0 - BUY_LIST['buy_count'] = 0 - BUY_LIST['buy_list'].clear() + # 매도를 체크한다. + check = self.sellStocks(stock_code, stock_name) - time.sleep(0.1) + # jangoDic[code]['장부가'], jangoDic[code]['평가금액'], jangoDic[code]['평가손익'], + buy_avg, amount, profit = self.getBallance(stock_code) + if check or buy_avg == 0: + BUY_LIST['buy_avg'] = 0 + BUY_LIST['buy_count'] = 0 + BUY_LIST['buy_list'].clear() - try: - # 데이터를 가지고 온다. - result_m1 = self.getRealTime(self.stock_code, today, LAST_DATA) - except: - print("#ERROR:", self.stock_code) - continue + time.sleep(0.1) - result_tic_m1 = self.makeTickData1(result_m1, mins=1) - data = self.analyze(result_tic_m1) - result_tic_m30 = self.makeTickData2(result_tic_m1, mins=30) - data_signal = self.analyze(result_tic_m30) + #result_m1 = self.getRealTime(stock_code, today, LAST_DATA) + result_m1 =self.getRealTime(stock_code, today) + result_tic_m1 = self.makeTickData1(result_m1, mins=1) + data = self.analyze(result_tic_m1) + result_tic_m30 = self.makeTickData2(result_tic_m1, mins=30) + data_signal = self.analyze(result_tic_m30) + #data.drop(data.index[:len(data) - analyzed_day], inplace=True) - #data.drop(data.index[:len(data) - analyzed_day], inplace=True) + # 사야 할 시점과 팔아야 할 시점을 체크한다. + bsLine1 = self.buySellChecker.checkTransaction1(stock_code, MAX_PRICE, data, data_signal, BUY_LIST, isRealTime=True) - # 사야 할 시점과 팔아야 할 시점을 체크한다. - bsLine1 = self.buySellChecker.checkTransaction1(self.stock_code, MAX_PRICE, data, data_signal, BUY_LIST, isRealTime=True) + if 'sell_price' in bsLine1: + sell_price = bsLine1['sell_price'][-1] + if 0 < sell_price: + profit_rate = 1.002 + if buy_avg * profit_rate < data['close'][-1]: + check = self.sellStocks(stock_code, sell_price) + if check: + self.orderChecker.sell(datetime.today().strftime('%Y%m%d'), stock_code) + BUY_LIST['buy_avg'] = 0 + BUY_LIST['buy_count'] = 0 + BUY_LIST['buy_list'].clear() + self.bot.sendMsg( "Profit {:.2f}, {} ({})".format(profit, stock_code, stock_name)) - if 'sell_price' in bsLine1: - sell_price = bsLine1['sell_price'][-1] - if 0 < sell_price: - profit_rate = 1.002 - if buy_avg * profit_rate < data['close'][-1]: - check = self.sellStocks(self.stock_code, sell_price) - if check: - self.orderChecker.sell(datetime.today().strftime('%Y%m%d'), self.stock_code) - BUY_LIST['buy_avg'] = 0 - BUY_LIST['buy_count'] = 0 - BUY_LIST['buy_list'].clear() - self.bot.sendMsg( "Profit {:.2f}, {} ({})".format(profit, self.stock_code, self.stock_name)) + if 'buy_price' in bsLine1: + buy_price = bsLine1['buy_price'][-1] + buy_count = int(bsLine1['buy_count'][-1]) + if buy_price > 0: + # 매수를 요청 한다. + orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, buy_price) + self.orderChecker.buy(today, "A" + stock_code, buy_count, buy_price, orderNum) - if 'buy_price' in bsLine1: - buy_price = bsLine1['buy_price'][-1] - buy_count = int(bsLine1['buy_count'][-1]) - if buy_price > 0: - # 매수를 요청 한다. - orderNum = self.requestOrder(OrderType.buy, self.stock_code, buy_count, buy_price) - self.orderChecker.buy(today, "A" + self.stock_code, buy_count, buy_price, orderNum) - - self.orderChecker.buy(datetime.today().strftime('%Y%m%d'), self.stock_code, buy_count, buy_price) - self.bot.post(self.stock_code, self.stock_name, "[BUY] ", buy_price, buy_count, data['rsi'][-1], -1) - - # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. - ORDER_LIST = self.requestOrderList() - orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=3) - if len(orderListToCancel) > 0: - self.cancelOrderList(orderListToCancel) + self.orderChecker.buy(datetime.today().strftime('%Y%m%d'), stock_code, buy_count, buy_price) + self.bot.post(stock_code, stock_name, "[BUY] ", buy_price, buy_count, data['rsi'][-1], -1) - if (int(THIS_TIME.strftime("%M")) % 50 == 0 or int(THIS_TIME.strftime("%M")) % 20 == 0): - #self.bot.alarm_live(self.stock_code, self.stock_name) - vm = psutil.virtual_memory() - vm_item = dict() - vm_item['free'] = vm.available // (1024 * 1024) - vm_item['idle'] = vm.available / vm.total * 100 - self.bot.sendMsg("Alive... {} ({}) avg: {:.2f}, close: {:.2f}, mem: {:.1f}".format(self.stock_code, self.stock_name, buy_avg, data['close'][-1], vm_item['idle'])) + # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. + ORDER_LIST = self.requestOrderList() + orderListToCancel = self.orderChecker.cancel(today, "A" + stock_code, ORDER_LIST, mins=3) + if len(orderListToCancel) > 0: + self.cancelOrderList(orderListToCancel) - time.sleep(60) - THIS_TIME = datetime.now() + if (int(THIS_TIME.strftime("%M")) % 50 == 0 or int(THIS_TIME.strftime("%M")) % 20 == 0): + #self.bot.alarm_live(stock_code, stock_name) + vm = psutil.virtual_memory() + vm_item = dict() + vm_item['free'] = vm.available // (1024 * 1024) + vm_item['idle'] = vm.available / vm.total * 100 + self.bot.sendMsg("Alive... {} ({}) avg: {:.2f}, close: {:.2f}, mem: {:.1f}".format(stock_code, stock_name, buy_avg, data['close'][-1], vm_item['idle'])) + + time.sleep(60) + THIS_TIME = datetime.now() return True \ No newline at end of file diff --git a/HTS_etf_all.py b/HTS_etf_all.py new file mode 100644 index 0000000..a89a7b6 --- /dev/null +++ b/HTS_etf_all.py @@ -0,0 +1,34 @@ +import os +from datetime import datetime +from HTS_etf import HTS_etf + +if __name__ == "__main__": + today = datetime.today() + + PROJECT_HOME = os.getcwd() + RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") + + stocks = [ + {'stock_code': '122630', 'stock_name': 'KODEX 레버리지'}, + {'stock_code': '233740', 'stock_name': 'KODEX 코스닥150레버리지'}, + {'stock_code': '251340', 'stock_name': 'KODEX 코스닥150선물인버스'}, + {'stock_code': '252670', 'stock_name': 'KODEX 200선물인버스2X'} + ] + + hts = HTS_etf(RESOURCE_PATH) + hts.connect2DB("hts.db") + + today_str = today.strftime('%Y%m%d') + + if not os.path.exists(os.path.join(RESOURCE_PATH, "log")): + os.mkdir(os.path.join(RESOURCE_PATH, "log")) + + MAX_PRICE = 500000 + hts.buyRealTime(stocks, today_str, MAX_PRICE=MAX_PRICE) + + db_filename = os.path.join(RESOURCE_PATH, "hts.db") + hts.insertStockData(today, stock_code, stock_name) + + hts.disconnect() + hts.bot.sendMsg("done... {} ({})".format(stock_code, stock_name)) + print("done...") \ No newline at end of file diff --git a/hts/BuySellChecker.py b/hts/BuySellChecker.py index bad5b40..4bb371b 100644 --- a/hts/BuySellChecker.py +++ b/hts/BuySellChecker.py @@ -10,7 +10,7 @@ class BuySellChecker(): PATTERNS = None RESOURCE_PATH = None - def __init__(self, RESOURCE_PATH, s): + def __init__(self, RESOURCE_PATH): self.RESOURCE_PATH = RESOURCE_PATH return @@ -98,58 +98,10 @@ class BuySellChecker(): df_signal = data_signal.loc[df_tmp] si = len(df_signal) - 1 - """ - if isRealTime: - macds = data['macd'][i-300:i].to_list() - if 0 < len(macds): - macds_max = max(macds) - mi = i-300 + macds.index(macds_max) - - if data['macd'][i] < macds_max and data['close'][mi] < data['close'][i]: - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - else: - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - else: - macds = self.getMacd(ticker['ticker_code'], data['ymd'][i].strftime('%Y%m%d'), mins=1) - if len(macds) == 0: - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - - macds_sort = sorted(macds, key=lambda x:x[0], reverse=True) - if data['macd'][i] < macds_sort[0][1] and macds_sort[0][2] < data['close'][i]: - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - """ - duration = 3 if sum(data['trend_avg'][i - duration:i]) / duration < data['trend_avg'][i]: # 상승 트렌드 if data_signal['avg20'][si] < data_signal['avg5'][si]: - """ - # 방법 1: - if max(data['volume_up'][i-180:i]) < data['volume_up'][i]: - if data_signal['slow_k'][si] < 70: - if BUY_LIST is not None and 0 < len(BUY_LIST['buy_list']) and BUY_LIST['buy_list'][-1]['buy_price'] < data['close'][i]: - buy_price = data['close'][i] - buy_type = 'volume_up' - buy_ymd = data['ymd'][i] - if data['slow_k'][si] < 30: - buy_count = MAX_BUY_PRICE / (1 * data['close'][i]) - elif data['slow_k'][si] < 50: - buy_count = MAX_BUY_PRICE / (2 * data['close'][i]) - else: - buy_count = MAX_BUY_PRICE / (3 * data['close'][i]) - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - else: - buy_price = data['close'][i] - buy_type = 'volume_up' - buy_ymd = data['ymd'][i] - if data['slow_k'][si] < 30: - buy_count = MAX_BUY_PRICE / (1 * data['close'][i]) - elif data['slow_k'][si] < 50: - buy_count = MAX_BUY_PRICE / (2 * data['close'][i]) - else: - buy_count = MAX_BUY_PRICE / (3 * data['close'][i]) - return buy_ymd, buy_price, buy_count, buy_cut, buy_type - """ # 방법 2: if data['avg480'][i] < data['avg120'][i] < data['avg60'][i] < data['avg20'][i] < data['avg5'][i] < data['close'][i]: diff --git a/hts/HTS.py b/hts/HTS.py index baebbf6..45037c2 100644 --- a/hts/HTS.py +++ b/hts/HTS.py @@ -647,25 +647,20 @@ class HTS: return result # 주식 현재가 조회 - def getRealTime(self, stock_code, today, LAST_DATA=None): - if LAST_DATA is not None: - #result = copy.deepcopy(LAST_DATA) - - result = {"check": set(), "ymd": [], "open": [], "close": [], "high": [], "low": [], "volume": [], "label": []} - for i in range(len(LAST_DATA['ymd'])): - result["ymd"].append(LAST_DATA['ymd'][i]) - result["open"].append(LAST_DATA['open'][i]) - result["close"].append(LAST_DATA['close'][i]) - result["high"].append(LAST_DATA['high'][i]) - result["low"].append(LAST_DATA['low'][i]) - result["volume"].append(LAST_DATA['volume'][i]) - result["label"].append(LAST_DATA['label'][i]) - else: - result = {"check": set(), "ymd": [], "open": [], "close": [], "high": [], "low": [], "volume": [], "label": []} - - #### real time에서 아직 저장된 것이 없기 때문에 result는 아무것도 채워지지 않는다. - self.getDBData(stock_code, today, result) + def getRealTime(self, stock_code, today, LAST_DATA=None, n=7): + result = {"check": set(), "ymd": [], "open": [], "close": [], "high": [], "low": [], "volume": [], "label": []} + days = [] + for i in range(1, 100): + last_day = (datetime.strptime(today, '%Y%m%d') - timedelta(i)).strftime('%Y%m%d') + isValid = self.isValidYMD(stock_code=stock_code, day=last_day) + if isValid: + days.append(last_day) + if len(days) >= n: + break + days = sorted(days) + for day in days: + self.getDBData(stock_code, day, result) int_given_day = int(today) objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")