import re import os import sqlite3 from datetime import datetime from hts.HTS import HTS from hts.OrderType import OrderType from hts.BuySellChecker import BuySellChecker from hts.OrderChecker import OrderChecker from stock.util.SlackBot import SlackBot from stock.analysis.StockStatus import StockStatus class HTS_Stocks (HTS): RESOURCE_PATH = None orderChecker = None buySellChecker = None labelChecker = None slackBot = None stockStatus = None analyzed_day = None MAX_BUY_PRICE = None def __init__(self, RESOURCE_PATH): super().__init__(RESOURCE_PATH) self.slackBot = SlackBot() self.RESOURCE_PATH = RESOURCE_PATH self.stockStatus = StockStatus(RESOURCE_PATH) self.buySellChecker = BuySellChecker() self.orderChecker = OrderChecker(self.RESOURCE_PATH) self.analyzed_day = 120 self.MAX_BUY_PRICE = 100000 return def getSellingPrice(self, log_time, stock_code, final_price, check=False): # final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미 # final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미 # final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임 sell_price = -1 orderNum = None jangoDic = self.requstJango() if jangoDic and len(jangoDic.keys()) > 0: for code in jangoDic: if code == "A" + stock_code: if jangoDic[code]['매도가능'] > 0: if check: if jangoDic[code]['장부가']*0.05 < jangoDic[code]['장부가'] - final_price: sell_price = jangoDic[code]['장부가'] orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price) print("ORDER_SELL", stock_code, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price) else: #max_price = max(jangoDic[code]['장부가'], final_price) # 10% 이상 수익이어야 매도한다. max_price = int(jangoDic[code]['장부가'] * 1.10) if max_price <= final_price: sell_price = (int(max_price) - int(max_price) % 5) orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price) print("ORDER_SELL", stock_code, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price) return orderNum def valid_company(self): valid_company = set() conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "stock.db")) cursor = conn.cursor() cursor.execute('select CODE, NAME, max(ymd) as ymd from fnguide where type != "E" group by 1 order by total_assets desc') items = cursor.fetchall() cursor.close() conn.close() for item in items: valid_company.add(item[0]) return valid_company def buyRealTime(self, today, n = 200): print ("START...") THIS_TIME = datetime.now() valid_company = self.valid_company() 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 + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'): stockTableName = 'stock' conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "stock.db")) cursor = conn.cursor() cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code') items = cursor.fetchall() cursor.close() conn.close() for idx, item in enumerate(items): if THIS_TIME < datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') or datetime.strptime(today + " 151500", '%Y%m%d %H%M%S') < THIS_TIME: break stock_code = item[0] stock_name = item[1] if ((stock_name.find('스팩') >= 0 or re.search("\d.*?호", stock_name) is not None) and stock_code not in valid_company): continue print(idx, stock_code, stock_name, ", CODE: ", stock_code, ", NAME: ", stock_name) stock = self.stockStatus.getLastData(stock_code, n) try: self.getRealTime_DailyCheck(today, stock_code, stock) data = self.stockStatus.analyze(stock, self.analyzed_day) except: print ("#ERROR:", stock_code, stock_name) continue # 분석일 데이터만 활용한다 (이전 데이터는 제거) data.drop(data.index[:len(data) - self.analyzed_day], inplace=True) bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, self.analyzed_day, isRealTime=False) # 다음 조건이면 매수한다. if len(data.index) > 10 and max(bsLine['buy'][len(bsLine['buy']) - 1:]) > 1000: if not self.orderChecker.exist(today, stock_code, hours=2): last_index = len(bsLine['buy'])-1 if bsLine['buy'][last_index] > 0: bs_buy_price = bsLine['buy'][last_index] bs_buy_weight = bsLine['buy_weight'][last_index] buy_count = int(self.MAX_BUY_PRICE / bs_buy_price) # 매수를 주문한다. orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price) # slackbot에 메시지를 보냄 self.slackBot.post_to_slack(stock_code, stock_name, "BUY", bsLine['buy'][len(bsLine['buy']) - 1], buy_count) self.orderChecker.add(today, stock_code, 1, buy_count, bs_buy_price, orderNum) # 로그 출력 print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, stock_name, bs_buy_price, buy_count) # 다음 조건이면 매도한다. if len(data.index) > 10 and max(bsLine['sell'][len(bsLine['sell']) - 1:]) > 0: last_index = len(bsLine['sell']) - 1 if bsLine['sell'][last_index] > 0: bs_sell_price = bsLine['sell'][last_index] orderNum = self.getSellingPrice(THIS_TIME, stock_code, bs_sell_price) # slackbot에 메시지를 보냄 self.slackBot.post_to_slack(stock_code, stock_name, "SELL", bsLine['sell'][len(bsLine['sell']) - 1], -1) self.orderChecker.delete(today, stock_code) # 로그 출력 print("SELL", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, stock_name, bs_sell_price) 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 if __name__ == "__main__": today = datetime.today() PROJECT_HOME = os.getcwd() RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") hts = HTS_Stocks(RESOURCE_PATH) today_str = today.strftime('%Y%m%d') hts.buyRealTime(today_str) print ("done...")