import time import os import sqlite3 from datetime import datetime from hts.HTS import HTS from hts.OrderType import OrderType from hts.OrderChecker import OrderChecker from stock.util.LabelChecker import LabelChecker from stock.util.TelegramBot import TelegramBot from stock.analysis.StockStatus import StockStatus from hts.BuySellChecker_122630 import BuySellChecker_122630 from hts.BuySellChecker_233740 import BuySellChecker_233740 from hts.BuySellChecker_251340 import BuySellChecker_251340 from hts.BuySellChecker_252670 import BuySellChecker_252670 class HTS_etf(HTS): RESOURCE_PATH = None SELL_GAP = None stock_code = None stock_name = None buy_count = None orderChecker = None buySellChecker = None labelChecker = None bot = None stockStatus = None def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP): 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.labelChecker = LabelChecker(RESOURCE_PATH) self.bot = TelegramBot() self.stockStatus = StockStatus(RESOURCE_PATH) self.buySellChecker = None if stock_code == '122630': self.buySellChecker = BuySellChecker_122630() elif stock_code == '233740': self.buySellChecker = BuySellChecker_233740() elif stock_code == '251340': self.buySellChecker = BuySellChecker_251340() elif stock_code == '252670': self.buySellChecker = BuySellChecker_252670() return def sellStocks(self, stock_code=None, bs_sell_price=None): check = False jangoDic = self.requstJango() if jangoDic and len(jangoDic.keys()) > 0: for code in jangoDic: if stock_code is not None: if code == "A" + stock_code: if bs_sell_price is not None: if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: # 1.5% 손해 혹은 2% 이상 시 수익 매도 self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price) check = True else: if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: # 1.5% 손해 혹은 2% 이상 시 수익 매도 self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) check = True else: if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: # 1.5% 손해 혹은 2% 이상 시 수익 매도 self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) check = True return check def getSellingPrice(self, log_time, stock_code, final_price, without_loss=False): # final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미 # final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미 # final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임 orderNum = None jangoDic = self.requstJango() if jangoDic and len(jangoDic.keys()) > 0: for code in jangoDic: if jangoDic[code]['매도가능'] > 0: if without_loss: if jangoDic[code]['장부가'] * 0.07 < jangoDic[code]['장부가'] - final_price: sell_price = jangoDic[code]['장부가'] if code == "A" + stock_code: orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price) return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price else: max_price = max(jangoDic[code]['장부가'], final_price) sell_price = (int(max_price) - int(max_price) % 5) + 5 if code == "A" + stock_code: orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price) return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price return orderNum, None, None, None def makeTickData(self, data, mins=30): result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []} for i in range(mins, len(data['time']) + 1): result["check"].add(data['time'][i - 1]) result["time"].append(data['time'][i - 1]) result["open"].append(data['open'][i - mins]) result["close"].append(data['close'][i - 1]) result["high"].append(max(data['high'][i - mins: i])) result["low"].append(min(data['low'][i - mins: i])) result["vol"].append(sum(data['vol'][i - mins: i])) return result def getLIMITInfo(self, stock_code, ymd, dbfile_name="stock.db"): conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, dbfile_name)) cursor = conn.cursor() cursor.execute('select ymd, open, close, high, low, volume from stock where code=? order by ymd desc limit ?', (stock_code, 100,)) db_result = cursor.fetchall() cursor.close() conn.close() match = False LIMIT_PRICE = [] for i, rows in enumerate(db_result): if rows[0].replace('.', '') == ymd: match = True if match: LIMIT_PRICE.append(rows[2]) return {'LOW_PRICE': sum(LIMIT_PRICE[:20]) / len(LIMIT_PRICE[:20])} def buyRealTime(self, today, analyzed_day=1000, logFp=None, MAX_PRICE=30000): INFO = self.getLIMITInfo(self.stock_code, today) print("START...") THIS_TIME = datetime.now() LAST_DATA = self.getLastData(self.stock_code, today) while datetime.strptime(today + " 063000", '%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)) logFp.write("START {} ({}) SLOW_K: {}\n".format(self.stock_code, self.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'): # 매도를 체크한다. self.sellStocks(self.stock_code) time.sleep(0.1) try: # 데이터를 가지고 온다. result = self.getRealTime(self.stock_code, today, LAST_DATA) except: print("#ERROR:", self.stock_code) continue data = self.buySellChecker.analyze(result) data.drop(data.index[:len(data) - analyzed_day], inplace=True) # 사야 할 시점과 팔아야 할 시점을 체크한다. bsLine = self.buySellChecker.checkTransaction(self.stock_code, data, INFO, isRealTime=True) bs_buy_price = bsLine['buy'][0] bs_buy_weight = bsLine['buy_weight'][0] bs_sell_price = bsLine['sell'][0] # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. ORDER_LIST = self.requestOrderList() orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10) if len(orderListToCancel) > 0: self.cancelOrderList(orderListToCancel) if bs_buy_price > 1000: #if not self.orderChecker.exist(today, "A" + self.stock_code, hours=9): buy_count = int(MAX_PRICE / bs_buy_price) if buy_count > 0: # 매수를 주문한다. orderNum = self.requestOrder(OrderType.buy, self.stock_code, buy_count, bs_buy_price) self.orderChecker.buy(today, "A" + self.stock_code, buy_count, bs_buy_price, orderNum) # 로그 출력 print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, self.stock_code, bs_buy_price, buy_count) logFp.write("{} BUY {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, buy_count)) if bs_sell_price > 1000: check = self.sellStocks(self.stock_code, bs_sell_price) if check: # 로그 출력 print("SELL", THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, self.stock_name, bs_sell_price) logFp.write("{} SELL {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, bs_sell_price)) # 로그 출력 print("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f" % (str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-1])) logFp.write("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f\n" % (str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-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, data["close"][len(data["close"])-1], data["macd"][len(data["macd"])-1]) logFp.flush() time.sleep(60) THIS_TIME = datetime.now() return True def updteTodayStock(self, stock_code, today_str): bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str) self.labelChecker.updateLabel(stock_code, bsLine, data, today_str) return