This commit is contained in:
dsyoon
2022-08-03 22:40:23 +09:00
parent 41e23641a8
commit ce26ef5623
5 changed files with 139 additions and 32 deletions

View File

@@ -6,6 +6,7 @@ import os
from hts.HTS import HTS from hts.HTS import HTS
from stock.util.Stock2Vector import Stock2Vector from stock.util.Stock2Vector import Stock2Vector
from stock.util.StockPredictor import StockPredictor
from hts.BuySellChecker import BuySellChecker from hts.BuySellChecker import BuySellChecker
class Simulation (HTS): class Simulation (HTS):
@@ -16,6 +17,7 @@ class Simulation (HTS):
super().__init__(RESOURCE_PATH) super().__init__(RESOURCE_PATH)
self.stock2Vector = Stock2Vector(RESOURCE_PATH) self.stock2Vector = Stock2Vector(RESOURCE_PATH)
self.stockPredictor = StockPredictor()
self.buySellChecker = BuySellChecker() self.buySellChecker = BuySellChecker()
self.RESOURCE_PATH = RESOURCE_PATH self.RESOURCE_PATH = RESOURCE_PATH
#self.connect() #self.connect()
@@ -126,23 +128,23 @@ class Simulation (HTS):
return return
def analyzeAutoMode(self, data):
return data, None
def simulate(self, stock_code, today, type="rule"): def simulate(self, stock_code, today, method="rule"):
LAST_DATA = self.stock2Vector.getLastData(stock_code, today)
result = self.stock2Vector.getRealTime(stock_code, today, LAST_DATA) if method == "ml":
LAST_DATA = self.stock2Vector.getLastData(stock_code, today, n=10)
result = self.stock2Vector.getRealTime(stock_code, today, LAST_DATA)
df, minmax_df = self.stock2Vector.preprocessData(result)
bsLine, data = self.stockPredictor.predict(df, minmax_df, isRealTime=False)
else:
LAST_DATA = self.stock2Vector.getLastData(stock_code, today)
result = self.stock2Vector.getRealTime(stock_code, today, LAST_DATA)
if type == "rule":
# 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다. # 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다.
data = self.buySellChecker.analyze(result) data = self.buySellChecker.analyze(result)
# 사야 할 시점과 팔아야 할 시점을 체크한다. # 사야 할 시점과 팔아야 할 시점을 체크한다.
bsLine, data = self.buySellChecker.checkTransaction(data, stock_code, isRealTime=False) bsLine, data = self.buySellChecker.checkTransaction(data, stock_code, isRealTime=False)
elif type == "auto":
data, bsLine = self.analyzeAutoMode(result)
else:
data, bsLine = None, None
if data is not None: if data is not None:
# 그래프를 그린다. # 그래프를 그린다.
@@ -159,13 +161,13 @@ if __name__ == "__main__":
stock_codes = { stock_codes = {
# 252670 # 252670
# 122630 # 122630
"122630": ['20220729'], "122630": ['20220803'],
} }
for stock_code in stock_codes: for stock_code in stock_codes:
simulation = Simulation(RESOURCE_PATH) simulation = Simulation(RESOURCE_PATH)
for given_day in stock_codes[stock_code]: for given_day in stock_codes[stock_code]:
simulation.simulate(stock_code, given_day) simulation.simulate(stock_code, given_day, method='ml')
print ("done...") print ("done...")

View File

@@ -1,7 +1,6 @@
import os import os
import keras import keras
import numpy as np import numpy as np
from numpy import zeros, newaxis
import tensorflow as tf import tensorflow as tf
from stock.util.Stock2Vector import Stock2Vector from stock.util.Stock2Vector import Stock2Vector
from classification_models.keras import Classifiers from classification_models.keras import Classifiers
@@ -18,16 +17,17 @@ class StockTrainer:
def getDataset(self, stock_code): def getDataset(self, stock_code):
VECTOR_SIZE = 299 VECTOR_SIZE = 299
df, minmax_df = self.stock2Vector.makeTrainData(stock_code) result = self.stock2Vector.getTrainData(stock_code)
df, minmax_df = self.stock2Vector.preprocessData(result)
TOTAL_X, TOTAL_Y = [], [] TOTAL_X, TOTAL_Y = [], []
for key in df: for key in minmax_df:
if key == "date": if key == "date":
continue continue
elif key == "label": elif key == "label":
TOTAL_Y.append(df[key].tolist()) TOTAL_Y.append(minmax_df[key].tolist())
else: else:
TOTAL_X.append(df[key].tolist()) TOTAL_X.append(minmax_df[key].tolist())
SIZE_WIDTH = len(TOTAL_X[0]) SIZE_WIDTH = len(TOTAL_X[0])
SIZE_HEIGHT = len(TOTAL_X) SIZE_HEIGHT = len(TOTAL_X)
@@ -44,38 +44,37 @@ class StockTrainer:
Y.append([0, 1, 0]) Y.append([0, 1, 0])
else: else:
Y.append([0, 0, 1]) Y.append([0, 0, 1])
if i >= VECTOR_SIZE+10:
break
X = np.asarray(X) X = np.asarray(X)
Y = np.asarray(Y) Y = np.asarray(Y)
return X, Y return X, Y
def train(self, stock_code): def train(self, stock_code):
ResNet18, preprocess_input = Classifiers.get('inceptionresnetv2')
X, Y = self.getDataset(stock_code) X, Y = self.getDataset(stock_code)
# build model
n_classes = 3
Inceptionresnetv2, preprocess_input = Classifiers.get('inceptionresnetv2')
X = preprocess_input(X) X = preprocess_input(X)
n_classes = 3 # train
checkpoint_filename = os.path.join(self.RESOURCE_PATH, "model", "stock.ckpt")
# build model base_model = Inceptionresnetv2(input_shape=(299, 299, 3), include_top=False)
base_model = ResNet18(input_shape=(299, 299, 3), include_top=False)
x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output) x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
output = tf.keras.layers.Dense(n_classes, activation='softmax')(x) output = tf.keras.layers.Dense(n_classes, activation='softmax')(x)
model = keras.models.Model(inputs=[base_model.input], outputs=[output]) model = keras.models.Model(inputs=[base_model.input], outputs=[output])
# train
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy']) model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])
checkpoint_filename = os.path.join(self.RESOURCE_PATH, "model", "stock.ckpt")
chekpoint = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_filename, save_weights_only=True, verbose=1) chekpoint = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_filename, save_weights_only=True, verbose=1)
earlystop = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=3, mode="auto") earlystop = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=5, mode="auto")
if os.path.isfile(checkpoint_filename):
model.load_weights(checkpoint_filename)
model.fit(x=X, model.fit(x=X,
y=Y, y=Y,
epochs=10, batch_size=10000,
epochs=10000,
callbacks=[chekpoint, earlystop]) callbacks=[chekpoint, earlystop])
return return
@@ -95,5 +94,4 @@ if __name__ == "__main__":
stockTrainer = StockTrainer(RESOURCE_PATH) stockTrainer = StockTrainer(RESOURCE_PATH)
stockTrainer.train(stock_code) stockTrainer.train(stock_code)
print ("done...") print ("done...")

View File

@@ -634,7 +634,7 @@ class HTS:
"label": []} "label": []}
days = [] days = []
for i in range(1, 10): for i in range(1, 100):
last_day = (datetime.strptime(today, '%Y%m%d') - timedelta(i)).strftime('%Y%m%d') last_day = (datetime.strptime(today, '%Y%m%d') - timedelta(i)).strftime('%Y%m%d')
isValid = self.isValidYMD(stock_code, last_day) isValid = self.isValidYMD(stock_code, last_day)
if isValid: if isValid:
@@ -655,6 +655,7 @@ class HTS:
else: else:
result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []} result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []}
#### real time에서 아직 저장된 것이 없기 때문에 result는 아무것도 채워지지 않는다.
self.getDBData(stock_code, today, result) self.getDBData(stock_code, today, result)

View File

@@ -153,6 +153,53 @@ class Stock2Vector(HTS):
return df, minmax_df return df, minmax_df
def getTrainData(self, stock_code):
tableName = 'hts'
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "hts.db"))
cursor = conn.cursor()
cursor.execute(
'SELECT ymd, hms, open, high, low, close, volume, label FROM ' + tableName + ' WHERE CODE=? and (ymd >= ? and ymd <= ?) order by ymd desc, hms ',
(stock_code, "20220721", "20220731"))
db_result = cursor.fetchall()
temp_result = []
for rows in db_result:
temp_result.append(
[rows[0], rows[1], rows[2], rows[3], rows[4], rows[5], rows[6], 0 if rows[7] is None else rows[7]])
temp_result.sort(key=lambda x: (x[0], x[1]))
result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []}
for rows in temp_result:
ymd = rows[0] # hts.날짜
hms = rows[1] # hts.시간
open = rows[2] # hts.시가
high = rows[3] # hts.고가
low = rows[4] # hts.저가
close = rows[5] # hts.종가
vol = rows[6] # hts.거래량
label = 0 if rows[7] is None else rows[7] # hts.매매구분
temp = datetime.strptime(str(ymd) + " " + str(hms).zfill(4) + "00", '%Y%m%d %H%M%S')
result["time"].append(temp)
result["open"].append(int(open))
result["close"].append(int(close))
result["high"].append(int(high))
result["low"].append(int(low))
result["vol"].append(int(vol))
result["label"].append(int(label))
return result
def preprocessData(self, result):
# 분석을 통해서 볼린저밴드 상/하단을 계산한다.
df = self.buySellChecker.getVectorFeature(result)
minmax_df1 = (df - df.min()) / (df.max() - df.min())
minmax_df2 = minmax_df1.drop(["date"], axis="columns")
minmax_df = minmax_df2.join(df['date'])
minmax_df = minmax_df.fillna(0)
return df, minmax_df
def makeTrainData(self, stock_code): def makeTrainData(self, stock_code):
result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []} result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []}

View File

@@ -0,0 +1,59 @@
import os
import keras
import numpy as np
from keras.applications.imagenet_utils import decode_predictions
from classification_models.keras import Classifiers
class StockPredictor:
RESOURCE_PATH = None
stock2Vector = None
def __init__(self):
return
def getDataset(self, df):
VECTOR_SIZE = 299
TOTAL_X, TOTAL_Y = [], []
for key in df:
if key == "date":
continue
elif key == "label":
TOTAL_Y.append(df[key].tolist())
else:
TOTAL_X.append(df[key].tolist())
SIZE_WIDTH = len(TOTAL_X[0])
SIZE_HEIGHT = len(TOTAL_X)
X = []
for i in range(VECTOR_SIZE, SIZE_WIDTH):
temp_X, temp_Y = np.zeros((VECTOR_SIZE, VECTOR_SIZE)), np.zeros(0)
for j in range(SIZE_HEIGHT):
temp_X[j][0:VECTOR_SIZE] = TOTAL_X[j][i - VECTOR_SIZE:i]
temp_X = np.stack([temp_X, temp_X, temp_X], axis=-1)
X.append(temp_X)
X = np.asarray(X[len(X)-1])
return X
def predict(self, df, minmax_df, isRealTime=False):
X = self.getDataset(df)
# build model
n_classes = 3
Inceptionresnetv2, preprocess_input = Classifiers.get('inceptionresnetv2')
X = preprocess_input(X)
base_model = Inceptionresnetv2(input_shape=(299, 299, 3), include_top=False)
model = keras.models.Model(inputs=[base_model.input])
checkpoint_filename = os.path.join(self.RESOURCE_PATH, "model", "stock.ckpt")
model.load_weights(checkpoint_filename)
y = model.predict(X)
# result
print(decode_predictions(y))
return