init
This commit is contained in:
@@ -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...")
|
||||||
|
|||||||
@@ -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...")
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": []}
|
||||||
|
|
||||||
|
|||||||
59
stock/util/StockPredictor.py
Normal file
59
stock/util/StockPredictor.py
Normal 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
|
||||||
Reference in New Issue
Block a user