This commit is contained in:
dosangyoon
2021-10-16 14:24:27 +09:00
parent 0a92e96d50
commit c1ce87aa37
6 changed files with 152 additions and 54 deletions

View File

@@ -3,7 +3,7 @@ from stockpredictor.analysis.Common import Common
from stockpredictor.analysis.Stochastic import Stochastic from stockpredictor.analysis.Stochastic import Stochastic
from stockpredictor.analysis.RSI import RSI from stockpredictor.analysis.RSI import RSI
class BS: class BuySellChecker:
common = None common = None
stochastic = None stochastic = None
@@ -207,16 +207,16 @@ class BS:
# rsi가 rsis 위로 올라오며 15 이하일 경우 10배로 주문함 (14:30 이전) # rsi가 rsis 위로 올라오며 15 이하일 경우 10배로 주문함 (14:30 이전)
if data["rsi"][i] < 15 and data["rsis"][i] < 15 and data["rsi"][i - 1] < data["rsis"][i - 1] and data["rsis"][i] < data["rsi"][i]: if data["rsi"][i] < 15 and data["rsis"][i] < 15 and data["rsi"][i - 1] < data["rsis"][i - 1] and data["rsis"][i] < data["rsi"][i]:
buy = data["Low"][i] buy = data["Low"][i]
weight = 3 weight = 4
if data["rsi"][i] < 10: if data["rsi"][i] < 10:
weight = 3 weight = 4
if data["slow_k"][i] in (0, 1, 2, 3): if data["slow_k"][i] in (0, 1, 2, 3):
weight = 2.5 weight = 3
if data["slow_k"][i] in (4, 5, 6, 7, 8): if data["slow_k"][i] in (4, 5, 6, 7, 8):
weight = 2 weight = 2.5
elif data["slow_k"][i] in (9, 10, 11, 12, 13): elif data["slow_k"][i] in (9, 10, 11, 12, 13):
weight = 1.5 weight = 2
elif data["slow_k"][i] in (14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25): elif data["slow_k"][i] in (14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25):
weight = 1 weight = 1

View File

@@ -1,29 +1,14 @@
import win32com.client import win32com.client
import time import time
import os import os
from datetime import datetime, timedelta from datetime import datetime
import pandas as pd import pandas as pd
from enum import Enum
from BS import BS from OrderType import OrderType
from OrderItem import OrderItem
# enum 주문 상태 세팅용 from BuySellChecker import BuySellChecker
class EorderBS(Enum): from OrderChecker import OrderChecker
buy = 1 # 매수
sell= 2 # 매도
none =3
class orderData:
def __init__(self):
self.dicEx = {EorderBS.buy: "매수", EorderBS.sell: "매도", EorderBS.none: "없음"}
self.orderNum = 0
self.bs = EorderBS.none # 0 : buy 1: sell
self.code = ""
self.amount = 0
self.price = 0
def debugPrint(self):
print(self.dicEx.get(self.bs), self.code, self.orderNum, self.amount, self.price)
class HTS: class HTS:
@@ -31,10 +16,10 @@ class HTS:
objCpCybos = None objCpCybos = None
objCpCodeMgr = None objCpCodeMgr = None
bs = None buySellChecker = None
def __init__(self): def __init__(self):
self.bs = BS() self.buySellChecker = BuySellChecker()
#self.connect() #self.connect()
return return
@@ -189,13 +174,13 @@ class HTS:
nRet = objStockOrder.BlockRequest() nRet = objStockOrder.BlockRequest()
if (nRet != 0): if (nRet != 0):
print("order error", nRet) print("order error", nRet)
return return None
rqStatus = objStockOrder.GetDibStatus() rqStatus = objStockOrder.GetDibStatus()
rqRet = objStockOrder.GetDibMsg1() rqRet = objStockOrder.GetDibMsg1()
print("통신상태", rqStatus, rqRet) print("통신상태", rqStatus, rqRet)
if rqStatus != 0: if rqStatus != 0:
return return None
orderNum = objStockOrder.GetHeaderValue(0) orderNum = objStockOrder.GetHeaderValue(0)
@@ -330,7 +315,7 @@ class HTS:
break break
for i in range(cnt): for i in range(cnt):
item = orderData() item = OrderItem()
item.orderNum = objResult.GetDataValue(1, i) item.orderNum = objResult.GetDataValue(1, i)
item.orderPrev = objResult.GetDataValue(2, i) item.orderPrev = objResult.GetDataValue(2, i)
item.code = objResult.GetDataValue(3, i) # 종목코드 item.code = objResult.GetDataValue(3, i) # 종목코드
@@ -356,9 +341,7 @@ class HTS:
return orderList return orderList
# 미체결 취소하기 # 미체결 취소하기
def cancelOrderList(self): def cancelOrderList(self, orderList):
#주문 리스트를 가져온다.
orderList = self.requestOrderList()
if len(orderList) < 1: if len(orderList) < 1:
return return
@@ -534,7 +517,7 @@ class HTS:
if i < 5: if i < 5:
return -1, -1, -1 return -1, -1, -1
buy, weight, sell = self.bs.getPriceAndWeight1(data, i) buy, weight, sell = self.buySellChecker.getPriceAndWeight1(data, i)
return buy, weight, sell return buy, weight, sell
def getSellingPrice(self, final_price): def getSellingPrice(self, final_price):
@@ -563,6 +546,9 @@ class HTS:
return 0, 0 return 0, 0
def buyRealTime(self, stock_code, given_day): def buyRealTime(self, stock_code, given_day):
orderChecker = OrderChecker()
BASE_COUNT = 100
timecheckList = pd.read_csv("timecheck.csv").values.tolist() timecheckList = pd.read_csv("timecheck.csv").values.tolist()
timecheck = {given_day + " " + str(second).zfill(6):False for second, check in timecheckList} timecheck = {given_day + " " + str(second).zfill(6):False for second, check in timecheckList}
@@ -587,19 +573,25 @@ class HTS:
self.getRealTime(stock_code, given_day, result) self.getRealTime(stock_code, given_day, result)
# 분석을 통해서 볼린저밴드 상/하단을 계산한다. # 분석을 통해서 볼린저밴드 상/하단을 계산한다.
data = self.bs.analyze(result) data = self.buySellChecker.analyze(result)
# 사야 할 시점/가격과 팔아야 할 시점/가격을 체크한다. # 사야 할 시점/가격과 팔아야 할 시점/가격을 체크한다.
bs_buy_price, bs_weight, bs_sell_price = self.checkTransaction(data) bs_buy_price, bs_weight, bs_sell_price = self.checkTransaction(data)
data_size = len(data["Close"]) data_size = len(data["Close"])
final_price = data["Close"][data_size-1] final_price = data["Close"][data_size-1]
if bs_buy_price > 0: if bs_buy_price > 0:
BUY_COUNT = int(200 * bs_weight) # 기본 100 주에 가중치를 추가해서 매수한다.
BUY_COUNT = int(BASE_COUNT * bs_weight)
# 매수 전에 모든 미체결을 취소한다. # 매수를 주문한다.
# self.cancelOrderList() orderNum = self.requestOrder(OrderType.buy, stock_code, BUY_COUNT , bs_buy_price)
# 현재까지 매입금액이 7백만원 이하일 때만 매수를 한다. # 미체결 기록을 가져온다.
self.requestOrder("2", stock_code, bs_weight * BUY_COUNT , bs_buy_price) orderList = self.requestOrderList()
# 매수 주문을 기록한다.
orderListToCancel = orderChecker.add("2", orderNum, BUY_COUNT, bs_buy_price, orderList)
# 두 시간 이전 미체결을 취소한다.
self.cancelOrderList(orderListToCancel)
# 로그 출력
print("BUY", second, BUY_COUNT, bs_buy_price) print("BUY", second, BUY_COUNT, bs_buy_price)
if bs_sell_price > 0: if bs_sell_price > 0:
@@ -607,20 +599,31 @@ class HTS:
selling_count, selling_price = self.getSellingPrice(final_price) selling_count, selling_price = self.getSellingPrice(final_price)
# 분석되 가격으로 매도 요청한다. # 분석되 가격으로 매도 요청한다.
if selling_count != 0 and selling_price != 0: if selling_count != 0 and selling_price != 0:
self.requestOrder("1", stock_code, selling_count, selling_price) orderNum = self.requestOrder(OrderType.sell, stock_code, selling_count, selling_price)
# 미체결 기록을 가져온다.
orderList = self.requestOrderList()
# 매도 주문을 기록한다.
orderListToCancel = orderChecker.add(OrderType.sell, orderNum, selling_count, selling_price, orderList)
# 두 시간 이전 미체결을 취소한다.
self.cancelOrderList(orderListToCancel)
# 로그 출력
print("SELL", second, selling_count, selling_price) print("SELL", second, selling_count, selling_price)
# 로그 출력
print("TIMECHECK", second, final_price, data["Low"][data_size-1], data["slow_k"][data_size-1], data["slow_d"][data_size-1]) print("TIMECHECK", second, final_price, data["Low"][data_size-1], data["slow_k"][data_size-1], data["slow_d"][data_size-1])
timecheck[second] = True timecheck[second] = True
if datetime.strptime(given_day + " 151000", '%Y%m%d %H%M%S') < datetime.now(): if datetime.strptime(given_day + " 151000", '%Y%m%d %H%M%S') < datetime.now():
# 15:10:00 이후라면 모든 미체결 취소 # 주문 리스트를 가져온다.
self.cancelOrderList() orderList = self.requestOrderList()
# 15:10:00 이후라면 모든 미체결 취소한다.
self.cancelOrderList(orderList)
# 매도 가격을 가져온다. # 매도 가격을 가져온다.
selling_count, selling_price = self.getSellingPrice(final_price) selling_count, selling_price = self.getSellingPrice(final_price)
# 분석되 가격으로 매도 요청한다. # 분석되 가격으로 매도 요청한다.
if selling_count != 0 and selling_price !=0: if selling_count != 0 and selling_price !=0:
self.requestOrder("1", stock_code, selling_count, selling_price) orderNum = self.requestOrder(OrderType.sell, stock_code, selling_count, selling_price)
# 로그 출력
print("SELL", second, selling_count, selling_price) print("SELL", second, selling_count, selling_price)
break break

58
hts/OrderChecker.py Normal file
View File

@@ -0,0 +1,58 @@
import os
import pandas as pd
from datetime import datetime, timedelta
from OrderItem import OrderItem
class OrderChecker:
order_df = None # 매수/매도구분, orderNum, 금액, 시각
saveFileName = None
def __init__(self):
self.saveFileName = "./order/"+datetime.today().strftime("%Y%m%d")+".csv"
self.read(self.saveFileName)
return
def read(self, fileName):
if os.path.isfile(fileName):
self.order_df = pd.read_csv(fileName)
else:
self.order_df = None
def add(self, type, orderNum, count, price, orderList):
orderListToCancel = []
if self.order_df is None:
self.order_df = pd.DataFrame()
else:
# 두 시간 전
before_two_hour = datetime.now() - timedelta(hours=2)
# 두 시간 전 주문을 찾는다.
if len(orderList) > 0:
# 만약 두시간 전 주문을 찾는다.
orderNum_df = self.order_df.loc[self.order_df["datetime"] <= before_two_hour]
orderNumSet = set(list(orderNum_df["orderNum"]))
for item in orderList:
if item.orderNum in orderNumSet:
orderListToCancel.append(item)
# 해당 orderNum 제외하기
self.order_df = self.order_df.loc[self.order_df["orderNum"] != item.orderNum]
self.order_df = self.order_df.append({"type": type, "orderNum": orderNum, "count": count, "price": price, "datetime": datetime.now()}, ignore_index=True)
self.order_df.to_csv(self.saveFileName)
return orderListToCancel
if __name__ == "__main__":
orderChecker = OrderChecker()
a = pd.DataFrame(columns=["a", "b", "c", "d", "e"])
a = a.append({"a": 0, "b": 1, "c": 3, "d": 7, "e": 8}, ignore_index=True)
a = a.append({"a": 1, "b": 3, "c": 0, "d": 6, "e": 6}, ignore_index=True)
a = a.append({"a": 2, "b": 3, "c": 0, "d": 3, "e": 9}, ignore_index=True)
a = a.append({"a": 3, "b": 9, "c": 9, "d": 8, "e": 4}, ignore_index=True)
a = a.loc[a["c"] != 9]
print(a.tail())

25
hts/OrderItem.py Normal file
View File

@@ -0,0 +1,25 @@
from OrderType import OrderType
class OrderItem:
def __init__(self):
self.dicEx = {OrderType.buy: "매수", OrderType.sell: "매도", OrderType.none: "없음"}
self.orderNum = None
self.orderPrev = None
self.code = None # 종목코드
self.name = None # 종목명
self.orderDesc = None # 주문구분내용
self.amount = None # 주문수량
self.price = None # 주문단가
self.ContAmount = None # 체결수량
self.credit = None # 신용구분
self.modAvali = None # 정정취소 가능수량
self.buysell = None # 매매구분코드
self.creditdate = None # 대출일
self.orderFlagDesc = None # 주문호가구분코드내용
self.orderFlag = None # 주문호가구분코드
def debugPrint(self):
print(self.dicEx.get(self.buysell), self.code, self.orderNum, self.amount, self.price)

8
hts/OrderType.py Normal file
View File

@@ -0,0 +1,8 @@
from enum import Enum
# enum 주문 상태 세팅용
class OrderType(Enum):
none = "0" # None
sell = "1" # 매도
buy = "2" # 매수

View File

@@ -1,16 +1,16 @@
import os import os
from datetime import datetime, timedelta from datetime import datetime
import pandas as pd import pandas as pd
import plotly.graph_objects as go import plotly.graph_objects as go
from plotly import subplots from plotly import subplots
from BS import BS from BuySellChecker import BuySellChecker
class Simulation: class Simulation:
bs = None buySellChecker = None
def __init__(self): def __init__(self):
self.bs = BS() self.buySellChecker = BuySellChecker()
#self.connect() #self.connect()
return return
@@ -50,7 +50,7 @@ class Simulation:
bsLine['sell'] = [-1 for i in range(size)] bsLine['sell'] = [-1 for i in range(size)]
for i in range(6, size-5): for i in range(6, size-5):
buy, weight, sell = self.bs.getPriceAndWeight1(data, i) buy, weight, sell = self.buySellChecker.getPriceAndWeight1(data, i)
bsLine['buy'][i] = buy bsLine['buy'][i] = buy
bsLine['weight'][i] = weight bsLine['weight'][i] = weight
bsLine['sell'][i] = sell bsLine['sell'][i] = sell
@@ -97,6 +97,7 @@ class Simulation:
avg5 = go.Scatter(x=data['Date'], y=data["avg5"], name="avg5", line_color='#000000') avg5 = go.Scatter(x=data['Date'], y=data["avg5"], name="avg5", line_color='#000000')
candle_stick = go.Candlestick(x=data['Date'], open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], increasing_line_color='red', decreasing_line_color='blue') candle_stick = go.Candlestick(x=data['Date'], open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], increasing_line_color='red', decreasing_line_color='blue')
volume_line = go.Scatter(x=data['Date'], y=data["Volume"], mode='lines', name='Volume')
fast_k_line = go.Scatter(x=data['Date'], y=data["fast_k"], mode='lines', name='fast_k') fast_k_line = go.Scatter(x=data['Date'], y=data["fast_k"], mode='lines', name='fast_k')
slow_k_line = go.Scatter(x=data['Date'], y=data["slow_k"], mode='lines', name='slow_k') slow_k_line = go.Scatter(x=data['Date'], y=data["slow_k"], mode='lines', name='slow_k')
slow_d_line = go.Scatter(x=data['Date'], y=data["slow_d"], mode='lines', name='slow_d') slow_d_line = go.Scatter(x=data['Date'], y=data["slow_d"], mode='lines', name='slow_d')
@@ -105,6 +106,7 @@ class Simulation:
#candle_data = [candle_stick, bolinger_upper, bolinger_lower, buy_check, sell_check, avg1, avg2, avg5, avg10, avg20, avg30, avg40, avg50, avg60] #candle_data = [candle_stick, bolinger_upper, bolinger_lower, buy_check, sell_check, avg1, avg2, avg5, avg10, avg20, avg30, avg40, avg50, avg60]
candle_data = [candle_stick, bolinger_upper, bolinger_lower, avg5, buy_check, sell_check] candle_data = [candle_stick, bolinger_upper, bolinger_lower, avg5, buy_check, sell_check]
volume_data = [volume_line]
stochastic_data = [slow_k_line, slow_d_line] stochastic_data = [slow_k_line, slow_d_line]
rsi_data = [rsi_line, rsis_line] rsi_data = [rsi_line, rsis_line]
@@ -115,13 +117,15 @@ class Simulation:
fig.show() fig.show()
""" """
fig = subplots.make_subplots(rows=3, cols=1, subplot_titles=('캔들', "스토캐스틱", "RSI")) fig = subplots.make_subplots(rows=4, cols=1, subplot_titles=('캔들', "거래량", "스토캐스틱", "RSI"))
for trace in candle_data: for trace in candle_data:
fig.append_trace(trace, 1, 1) fig.append_trace(trace, 1, 1)
for trace in stochastic_data: for trace in volume_data:
fig.append_trace(trace, 2, 1) fig.append_trace(trace, 2, 1)
for trace in rsi_data: for trace in stochastic_data:
fig.append_trace(trace, 3, 1) fig.append_trace(trace, 3, 1)
for trace in rsi_data:
fig.append_trace(trace, 4, 1)
#fig.update_xaxes(nticks=5) #fig.update_xaxes(nticks=5)
#fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False) #fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False)
fig.update_layout(height=1800, title=stock_code + "_" + given_day) fig.update_layout(height=1800, title=stock_code + "_" + given_day)
@@ -142,7 +146,7 @@ class Simulation:
self.getCSV("./data/"+stock_code+"_"+given_day+".csv", given_day, result) self.getCSV("./data/"+stock_code+"_"+given_day+".csv", given_day, result)
# 분석을 통해서 볼린저밴드 상/하단을 계산한다. # 분석을 통해서 볼린저밴드 상/하단을 계산한다.
data = self.bs.analyze(result) data = self.buySellChecker.analyze(result)
# 사야 할 시점과 팔아야 할 시점을 체크한다. # 사야 할 시점과 팔아야 할 시점을 체크한다.
bsLine = self.checkTransaction(data) bsLine = self.checkTransaction(data)