import re import os import time import psutil import sqlite3 from datetime import datetime, timedelta from hts.HTS import HTS from hts.OrderType import OrderType from hts.BuySellChecker import BuySellChecker from hts.OrderChecker import OrderChecker from stock.util.TelegramBot import TelegramBot from stock.analysis.StockStatus import StockStatus class HTS_Stocks (HTS): RESOURCE_PATH = None orderChecker = None buySellChecker = None labelChecker = None bot = None stockStatus = None analyzed_day = None MAX_BUY_PRICE = None conn_stock = None cursor_stock = None def __init__(self, RESOURCE_PATH): super().__init__(RESOURCE_PATH) self.bot = TelegramBot() self.RESOURCE_PATH = RESOURCE_PATH self.stockStatus = StockStatus(RESOURCE_PATH) self.buySellChecker = BuySellChecker(RESOURCE_PATH) self.orderChecker = OrderChecker(self.RESOURCE_PATH, "STOCK") self.analyzed_day = 120 self.MAX_BUY_PRICE = 300000 return def connect2StockDB(self): self.conn_stock = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "stock.db")) self.cursor_stock = self.conn_stock.cursor() return def disconnectStockDB(self): self.cursor_stock.close() self.conn_stock.close() return def sellStocks(self, stock_code=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 jangoDic[code]['매도가능'] > 0: if 3.0 < jangoDic[code]['평가손익']: self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) self.bot.sendMsg("Profit {} ({}): {:.2f} ({:.2f}%)".format(jangoDic[code]['종목명'], jangoDic[code]['종목코드'], (jangoDic[code]['현재가']-jangoDic[code]['장부가'])*jangoDic[code]['잔고수량'], jangoDic[code]['평가손익'])) check = True else: if 10.0 < jangoDic[code]['평가손익']: self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) self.bot.sendMsg("Profit {} ({}): {:.2f} ({:.2f}%)".format(jangoDic[code]['종목명'], jangoDic[code]['종목코드'], (jangoDic[code]['현재가']-jangoDic[code]['장부가'])*jangoDic[code]['잔고수량'], jangoDic[code]['평가손익'])) check = True return check def buyRealTime(self, today, n = 200): print ("START...") THIS_TIME = datetime.now() while datetime.strptime(today + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'): # 1515 까지만 매수를 시도한다. if datetime.strptime(today + " 080000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'): today_stock = self.get_today_stock() if len(today_stock) < 1: self.sellStocks() time.sleep(300) continue for idx, stock in enumerate(today_stock): stock_code = stock['code'] filename = stock['filename'] time.sleep(0.1) stock = self.stockStatus.fetchLastData(self.cursor_stock, stock_code, n) self.getRealTime_DailyCheck(today, stock_code, stock) data = self.stockStatus.analyze(stock, self.analyzed_day) # 매도 if not data['avg60'][-1] < data['avg20'][-1] < data['avg5'][-1]: self.sellStocks(stock_code) # 매수 bs_buy_price = data["close"][-1] if 150000 < bs_buy_price: buy_count = 1 else: buy_count = 150000 // bs_buy_price # 매수를 주문한다. orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price) self.orderChecker.buy(today, "A" + stock_code, buy_count, bs_buy_price, orderNum) # bot에 메시지를 보냄 self.bot.sendMsg('BUY {} {} ({})'.format(stock_code, bs_buy_price, buy_count)) arr = os.path.splitext(filename) os.rename(filename, arr[0]+'.[BUY]'+arr[1]) # 로그 출력 print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, '', bs_buy_price, buy_count) if int(THIS_TIME.strftime("%M")) in (10, 40): vm = psutil.virtual_memory() vm_item = dict() vm_item['free'] = vm.available // (1024 * 1024) vm_item['idle'] = vm.available / vm.total * 100 hts.bot.sendMsg("Alive... mem: {:.1f}".format(vm_item['idle'])) time.sleep(600) THIS_TIME = datetime.now() return def updteTodayStock(self, db_filename, stock_code, today_str): bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str) self.labelChecker.updateLabel(db_filename, stock_code, bsLine, data, today_str) return def get_today_stock(self): today_stock = [] path = os.path.join(self.RESOURCE_PATH, 'analysis', '종목선택') file_list = os.listdir(path) for filename in file_list: # '20240130_2_daily_최적_타이밍_후보__1162_넥스틸_092790.html' #pattern = '([0-9]+)_[1-9]_daily_최적_타이밍_후보__[0-9]+_([ㄱ-ㅎ가-힣a-zA-Z0-9]+)_([0-9]+)\.html' pattern = '([0-9]+)_[1-9]_daily_final_candidate__[0-9]+_.*_([0-9]+)\.html' info = re.search(pattern, filename) if info is None: continue date_str = datetime.strptime(info.group(1), "%Y%m%d").strftime("%Y%m%d") if date_str == datetime.today().strftime("%Y%m%d") or date_str == (datetime.today() - timedelta(days=1)).strftime("%Y%m%d"): stock = {'code': info.group(2), 'filename': os.path.join(path, filename)} today_stock.append(stock) return today_stock if __name__ == "__main__": today = datetime.today() PROJECT_HOME = os.getcwd() RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") hts = HTS_Stocks(RESOURCE_PATH) hts.connect2DB("hts.db") hts.connect2StockDB() today_str = today.strftime('%Y%m%d') hts.buyRealTime(today_str) hts.disconnectStockDB() hts.disconnect() print ("done...")