From 0c6757f7ed5aff0207bf89da4e786774049f94a2 Mon Sep 17 00:00:00 2001 From: dsyoon Date: Fri, 3 Jun 2022 14:11:42 +0900 Subject: [PATCH] init --- hts/HTS.py | 2 +- hts/util/DataDownloader.py | 255 +++---------------------------------- 2 files changed, 17 insertions(+), 240 deletions(-) diff --git a/hts/HTS.py b/hts/HTS.py index 13457cd..3d87287 100644 --- a/hts/HTS.py +++ b/hts/HTS.py @@ -1,4 +1,4 @@ -#import win32com.client +import win32com.client import time from hts.OrderItem import OrderItem diff --git a/hts/util/DataDownloader.py b/hts/util/DataDownloader.py index 118f326..ed53755 100644 --- a/hts/util/DataDownloader.py +++ b/hts/util/DataDownloader.py @@ -1,7 +1,6 @@ -import time +import win32com.client import os from datetime import datetime, timedelta -import pandas as pd from hts.HTS import HTS @@ -40,241 +39,18 @@ class DataDownloader (HTS): size = objStockChart.GetHeaderValue(3) - outfp.write("%s,%s,%s,%s,%s,%s,%s\n" % ("날짜", "시간", "시가", "고가", "저가", "종가", "거래량")) - for i in range(size - 1, -1, -1): - day = objStockChart.GetDataValue(0, i) - time = objStockChart.GetDataValue(1, i) - start = objStockChart.GetDataValue(2, i) - high = objStockChart.GetDataValue(3, i) - low = objStockChart.GetDataValue(4, i) - close = objStockChart.GetDataValue(5, i) - vol = objStockChart.GetDataValue(6, i) - outfp.write("%d,%s,%d,%d,%d,%d,%d\n" % (day, str(time).zfill(4), start, high, low, close, vol)) - outfp.close() - - return - - - def write(self, day, result): - #날짜,시간,시가,고가,저가,종가,거래량 - #20210909,900,2070,2070,2070,2070,0 - - outFp = open(day+".csv", mode="w", encoding="UTF-8") - outFp.write("날짜,시간,시가,고가,저가,종가,거래량\n") - for i in range(len(result["time"])): - outFp.write("%s,%s,%s,%s,%s,%s,%s\n"%( - result["time"][i].strftime('%Y%m%d'), - result["time"][i].strftime('%H%M'), - result["open"][i], - result["high"][i], - result["low"][i], - result["close"][i], - result["vol"][i])) - outFp.close() - return - - # 주식 현재가 조회 - def getRealTime(self, stock_code, given_day, result): - int_given_day = int(given_day) - objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos") - bConnect = objCpCybos.IsConnect - if (bConnect == 0): - print("PLUS가 정상적으로 연결되지 않음. ") - exit() - - # 차트 객체 구하기 - objStockChart = win32com.client.Dispatch("CpSysDib.StockChart") - - objStockChart.SetInputValue(0, 'A'+stock_code) # 종목 코드 - objStockChart.SetInputValue(1, ord('1')) # 1: 기간으로 조회, 2: 개수로 조회 - objStockChart.SetInputValue(2, given_day) # 기간 조회 시, 시작일 - objStockChart.SetInputValue(3, given_day) # 기간 조회 시, 종료일 - objStockChart.SetInputValue(4, 400) # 조회 시 가져오는 Line 개수 - objStockChart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8]) # 날짜,시간,시가,고가,저가,종가,거래량 - objStockChart.SetInputValue(6, ord('m')) # '차트 주가 - 월(M), 주(W), 일(D), 시(H), 분(m), 초(S) 차트 요청 - objStockChart.SetInputValue(7, 1) - objStockChart.SetInputValue(9, ord('1')) # 수정주가 사용 - objStockChart.BlockRequest() - - size = objStockChart.GetHeaderValue(3) - - #print("날짜", "시간", "시가", "고가", "저가", "종가", "거래량") - start_time = datetime.strptime(given_day + " 090000", '%Y%m%d %H%M%S') - for i in range(size-1, -1, -1): - int_day = objStockChart.GetDataValue(0, i) - int_time = objStockChart.GetDataValue(1, i) - - if int_day < int_given_day: - continue - time = datetime.strptime(str(int_day)+" "+str(int_time).zfill(4)+"00", '%Y%m%d %H%M%S') - if time < start_time: - continue - - open = objStockChart.GetDataValue(2, i) - close = objStockChart.GetDataValue(5, i) - high = objStockChart.GetDataValue(3, i) - low = objStockChart.GetDataValue(4, i) - vol = objStockChart.GetDataValue(6, i) - - if len(result["check"]) == 0: - result["check"].add(start_time) - result["time"].append(start_time) - result["open"].append(open) - result["close"].append(open) - result["high"].append(open) - result["low"].append(open) - result["vol"].append(0) - - if time not in result["check"]: - result["check"].add(time) - result["time"].append(time) - - result["open"].append(open) - result["close"].append(close) - result["high"].append(high) - result["low"].append(low) - result["vol"].append(vol) - - return - - def checkTransaction(self, data): - size = len(data["close"]) - - bsLine = {} - bsLine['buy'] = [-1 for i in range(size)] - bsLine['weight'] = [-1 for i in range(size)] - bsLine['sell'] = [-1 for i in range(size)] - - i = size - 1 - if i < 5: - return -1, -1, -1 - - buy, weight, sell = self.buySellChecker.getPriceAndWeight1(data, i) - return buy, weight, sell - - def getSellingPrice(self, final_price): - # 만약 잔고가 있으면 장부가보다 5원 높게 매도한다. - jangoDic = self.requstJango() - if jangoDic and len(jangoDic.keys()) > 0: - for code in jangoDic: - if jangoDic[code]['매도가능'] > 0: - if final_price >= jangoDic[code]['장부가'] + 5: - return jangoDic[code]['매도가능'], final_price - else: - # 장부가 가격의 마지막 자리를 0으로 만든다. (2090 -> 2090, 2092 -> 2090, 2098 -> 2090) - sell_price = int(jangoDic[code]['장부가'] / 10) * 10 - # 장부가의 마지막 자리수를 가져온다. - last_number = int(jangoDic[code]['장부가']) % 10 - if last_number in [0, 1, 2, 3]: - # 장부가의 마지막 자리수가 0,1,2,3 이라면 (2090, 2091, 2092 -> 2095 에 매도) - return jangoDic[code]['매도가능'], sell_price + 5 - elif last_number in [4, 5, 6, 7]: - # 장부가의 마지막 자리수가 4,5,6,7 이라면 (2093, 2094, 2095, 2096 -> 2100 에 매도) - return jangoDic[code]['매도가능'], sell_price + 10 - else: - # 장부가의 마지막 자리수가 8,9 라면 (2098, 2099 -> 2105 에 매도) - return jangoDic[code]['매도가능'], sell_price + 15 - - return 0, 0 - - def buyRealTime(self, GIVEN_DAY): - orderChecker = OrderChecker(self.stock_code) - BASE_COUNT = 500 - - timecheckList = pd.read_csv("timecheck.csv").values.tolist() - timecheck = {GIVEN_DAY + " " + str(second).zfill(6):False for second, check in timecheckList} - - result = {"check": set(), - "time": [], - "open": [], - "close": [], - "high": [], - "low": [], - "vol": []} - - print ("START...") - THIS_TIME = datetime.now() - while datetime.strptime(GIVEN_DAY + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(GIVEN_DAY + " 15200", '%Y%m%d %H%M%S'): - - if datetime.strptime(GIVEN_DAY + " 090100", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(GIVEN_DAY + " 151500", '%Y%m%d %H%M%S'): - if THIS_TIME.strftime('%Y%m%d %H%M%S') in timecheck and not timecheck[THIS_TIME.strftime('%Y%m%d %H%M%S')]: - - # 데이터를 가지고 온다. - self.getRealTime(self.stock_code, GIVEN_DAY, result) - - # 분석을 통해서 볼린저밴드 상/하단을 계산한다. - data = self.buySellChecker.analyze(result) - # 사야 할 시점/가격과 팔아야 할 시점/가격을 체크한다. - bs_buy_price, bs_weight, bs_sell_price = self.checkTransaction(data) - data_size = len(data["close"]) - final_price = data["close"][data_size-1] - - if bs_buy_price > 0: - # 기본 100 주에 가중치를 추가해서 매수한다. - #BUY_COUNT = int(BASE_COUNT * bs_weight) - BUY_COUNT = int(BASE_COUNT * 1) - - - # 매수를 주문한다. - orderNum = self.requestOrder(OrderType.buy, self.stock_code, BUY_COUNT , bs_buy_price) - - # 미체결 기록을 가져온다. - ORDER_LIST = self.requestOrderList() - # 매수 주문을 기록한다. - orderListToCancel = orderChecker.add(self.stock_code, OrderType.buy, orderNum, BUY_COUNT, bs_buy_price, ORDER_LIST) - # 두 시간 이전 미체결을 모두 취소한다. - self.cancelOrderList(orderListToCancel) - # 로그 출력 - print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), BUY_COUNT, bs_buy_price, len(orderListToCancel), len(ORDER_LIST)) - - """ - if bs_sell_price > 0: - # 미체결 기록을 가져온다. - ORDER_LIST = self.requestOrderList() - # 매도 주문을 기록을 가져온다. - orderListToCancel = orderChecker.remove(self.stock_code, OrderType.sell, ORDER_LIST) - # 매도 미체결을 모두 취소한다. - self.cancelOrderList(orderListToCancel) - - # 매도 가격을 가져온다. - selling_count, selling_price = self.getSellingPrice(final_price) - # 분석되 가격으로 매도 요청한다. - if selling_count != 0 and selling_price != 0: - # 매도를 요청한다. - orderNum = self.requestOrder(OrderType.sell, self.stock_code, selling_count, selling_price) - - # 로그 출력 - print("SELL", THIS_TIME.strftime('%Y%m%d %H%M%S'), selling_count, selling_price, len(orderListToCancel), len(ORDER_LIST)) - """ - # 로그 출력 - print("TIMECHECK: %s, price: %d, low: %d, lower: %.2f, avg5: %.2f, slow_k_1: %.2f, slow_d_1: %.2f, slow_k: %.2f, slow_d: %.2f, rsi: %.2f, rsis: %.2f" % - (str(THIS_TIME), final_price, data["low"][data_size-1], data["lower"][data_size-1], data["avg5"][data_size-1], - data["slow_k"][data_size-2], data["slow_d"][data_size-2], data["slow_k"][data_size-1], data["slow_d"][data_size-1], - data["rsi"][data_size-1], data["rsis"][data_size-1])) - timecheck[THIS_TIME] = True - """ - if datetime.strptime(GIVEN_DAY + " 151530", '%Y%m%d %H%M%S') < THIS_TIME: - #### - # 손해 보지 않는 가격에 매도한다. - #### - - # 주문 리스트를 가져온다. - orderList = self.requestOrderList() - # 15:10:00 이후라면 모든 미체결 취소한다. - self.cancelOrderList(orderList) - - # 매도 가격을 가져온다. - selling_count, selling_price = self.getSellingPrice(final_price) - # 분석되 가격으로 매도 요청한다. - if selling_count != 0 and selling_price != 0: - orderNum = self.requestOrder(OrderType.sell, self.stock_code, selling_count, selling_price) - # 로그 출력 - print("SELL", THIS_TIME, selling_count, selling_price) - - break - """ - time.sleep(0.9) - THIS_TIME = datetime.now() + if size > 0: + outfp.write("%s,%s,%s,%s,%s,%s,%s\n" % ("날짜", "시간", "시가", "고가", "저가", "종가", "거래량")) + for i in range(size - 1, -1, -1): + day = objStockChart.GetDataValue(0, i) + time = objStockChart.GetDataValue(1, i) + start = objStockChart.GetDataValue(2, i) + high = objStockChart.GetDataValue(3, i) + low = objStockChart.GetDataValue(4, i) + close = objStockChart.GetDataValue(5, i) + vol = objStockChart.GetDataValue(6, i) + outfp.write("%d,%s,%d,%d,%d,%d,%d\n" % (day, str(time).zfill(4), start, high, low, close, vol)) + outfp.close() return @@ -282,14 +58,15 @@ if __name__ == "__main__": today = datetime.today() - PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__)))) - RESOURCE_DIR = PROJECT_HOME + "/resources/data" + PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__)))))) + RESOURCE_DIR = PROJECT_HOME + "/resources" stock_code = "252670" dataDownloader = DataDownloader() for i in range(1, 1000): given_day = datetime.today() - timedelta(i) + print(given_day) # '차트 주가 - 월(M), 주(W), 일(D), 시(H), 분(m), 초(S) 차트 요청 dataDownloader.writeStockData(stock_code, given_day.strftime('%Y%m%d'), 'm', RESOURCE_DIR)