Merge remote-tracking branch 'origin/master'

This commit is contained in:
dsyoon
2022-08-05 00:38:39 +09:00
10 changed files with 265 additions and 125 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)
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) 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,22 +1,26 @@
import os import os
import shutil import shutil
import datetime
import time import time
from datetime import datetime
from stock.crawler.FnGuideCrawler import FnGuideCrawler from stock.crawler.FnGuideCrawler import FnGuideCrawler
from stock.crawler.MetaCrawler import MetaCrawler from stock.crawler.MetaCrawler import MetaCrawler
from stock.crawler.StockCrawler import StockCrawler from stock.crawler.StockCrawler import StockCrawler
from stock.analysis.AnalyzerSqlite import AnalyzerSqlite from stock.analysis.AnalyzerSqlite import AnalyzerSqlite
today = datetime.datetime.now().strftime("%Y-%m-%d") today = datetime.now().strftime("%Y-%m-%d")
# DB Browser for SQLite: http://hleecaster.com/python-sqlite3/ # DB Browser for SQLite: http://hleecaster.com/python-sqlite3/
PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__)))))))) PROJECT_HOME = os.path.join(os.path.dirname(__file__))
START_DATE = "1900.01.01" START_DATE = "1900.01.01"
start = time.time() start = time.time()
stockFileName = PROJECT_HOME + '/resources/stock.db' stockFileName = PROJECT_HOME + '/resources/stock.db'
week = datetime.today().weekday()
if week in (0, 1, 2, 3, 4):
# 재무제표는 3개월마다 다운로드를 한다. # 재무제표는 3개월마다 다운로드를 한다.
fnGuideCrawler = FnGuideCrawler(START_DATE) fnGuideCrawler = FnGuideCrawler(START_DATE)
@@ -46,7 +50,6 @@ stockCrawler.crawl_etf_stocks(stockFileName)
stockCrawler.crawl_stocks(stockFileName) stockCrawler.crawl_stocks(stockFileName)
#stockCrawler.crawl_special_stocks(stockFileName) #stockCrawler.crawl_special_stocks(stockFileName)
print("\n[종목 분석]") print("\n[종목 분석]")
# S: 분석까지 진행 # S: 분석까지 진행
inFileName = PROJECT_HOME + '/resources/stock.db' inFileName = PROJECT_HOME + '/resources/stock.db'
@@ -58,7 +61,7 @@ analyzerSqlite.analyzeGrouping("monthly")
analyzerSqlite = AnalyzerSqlite(PROJECT_HOME, stockFileName) analyzerSqlite = AnalyzerSqlite(PROJECT_HOME, stockFileName)
print("\n[종목 결정]") print("\n[종목 결정]")
day = datetime.datetime.today().strftime("%Y%m%d") day = datetime.today().strftime("%Y%m%d")
outPath = PROJECT_HOME + "/resources/analysis/" + day outPath = PROJECT_HOME + "/resources/analysis/" + day
if os.path.isdir(outPath): if os.path.isdir(outPath):
shutil.rmtree(outPath) shutil.rmtree(outPath)
@@ -67,8 +70,6 @@ print("print to Html...")
analyzerSqlite.findCandidate(outPath) analyzerSqlite.findCandidate(outPath)
# E: 분석까지 진행 # E: 분석까지 진행
print("time : %6.2f", (time.time() - start)) print("time : %6.2f", (time.time() - start))
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

@@ -2,9 +2,9 @@ import json
import os import os
import time import time
import shutil import shutil
from stockpredictor.analysis.Common import Common from stock.analysis.Common import Common
from stockpredictor.analysis.Stochastic import Stochastic from stock.analysis.Stochastic import Stochastic
from stockpredictor.analysis.BolingerBand import BolingerBand from stock.analysis.BolingerBand import BolingerBand
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import datetime import datetime
import sqlite3 import sqlite3

View File

@@ -16,12 +16,12 @@ import plotly.graph_objs as go
from plotly import tools, subplots from plotly import tools, subplots
import plotly.io as po import plotly.io as po
from stockpredictor.analysis.Common import Common from stock.analysis.Common import Common
from stockpredictor.analysis.Stochastic import Stochastic from stock.analysis.Stochastic import Stochastic
from stockpredictor.analysis.BolingerBand import BolingerBand from stock.analysis.BolingerBand import BolingerBand
from stockpredictor.analysis.IchimokuCloud import IchimokuCloud from stock.analysis.IchimokuCloud import IchimokuCloud
from stockpredictor.analysis.RSI import RSI from stock.analysis.RSI import RSI
from stockpredictor.crawler.sQLite.MovingAverage import MovingAverage from stock.crawler.MovingAverage import MovingAverage
class AnalyzerSqlite: class AnalyzerSqlite:
PROJECT_HOME = None PROJECT_HOME = None
@@ -118,6 +118,7 @@ class AnalyzerSqlite:
high = list(reversed(stock['high'])) high = list(reversed(stock['high']))
low = list(reversed(stock['low'])) low = list(reversed(stock['low']))
volume = list(reversed(stock['volume'])) volume = list(reversed(stock['volume']))
avg3 = list(reversed(stock['avg3']))
avg4 = list(reversed(stock['avg4'])) avg4 = list(reversed(stock['avg4']))
avg5 = list(reversed(stock['avg5'])) avg5 = list(reversed(stock['avg5']))
avg6 = list(reversed(stock['avg6'])) avg6 = list(reversed(stock['avg6']))
@@ -142,6 +143,7 @@ class AnalyzerSqlite:
# general # general
candle_stick = go.Candlestick(x=ymd, open=open, high=high, low=low, close=close, increasing_line_color='red', decreasing_line_color='blue') candle_stick = go.Candlestick(x=ymd, open=open, high=high, low=low, close=close, increasing_line_color='red', decreasing_line_color='blue')
avg3 = go.Scatter(x=ymd, y=avg3, name="avg3", line_color='#085F1B')
avg4 = go.Scatter(x=ymd, y=avg4, name="avg4", line_color='#085F1B') avg4 = go.Scatter(x=ymd, y=avg4, name="avg4", line_color='#085F1B')
avg5 = go.Scatter(x=ymd, y=avg5, name="avg5", line_color='#000000') avg5 = go.Scatter(x=ymd, y=avg5, name="avg5", line_color='#000000')
avg6 = go.Scatter(x=ymd, y=avg6, name="avg6", line_color='#698D09') avg6 = go.Scatter(x=ymd, y=avg6, name="avg6", line_color='#698D09')
@@ -160,7 +162,7 @@ class AnalyzerSqlite:
changeLine = go.Scatter(x=ymd, y=ichimokucloud_changeLine, name="changeLine", line_color='#000000') changeLine = go.Scatter(x=ymd, y=ichimokucloud_changeLine, name="changeLine", line_color='#000000')
baseLine = go.Scatter(x=ymd, y=ichimokucloud_baseLine, name="baseLine", line_color='#FF0000') baseLine = go.Scatter(x=ymd, y=ichimokucloud_baseLine, name="baseLine", line_color='#FF0000')
candle_data = [candle_stick, avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg240, avg300, bolinger_upper, bolinger_lower, changeLine, baseLine] candle_data = [candle_stick, avg3, avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg240, avg300, bolinger_upper, bolinger_lower, changeLine, baseLine]
#candle_data = [candle_stick, bolinger_upper, bolinger_lower, changeLine, baseLine] #candle_data = [candle_stick, bolinger_upper, bolinger_lower, changeLine, baseLine]
volume = go.Bar(x=ymd, y=volume, name="volume") volume = go.Bar(x=ymd, y=volume, name="volume")
@@ -229,6 +231,9 @@ class AnalyzerSqlite:
os.mkdir(outPath) os.mkdir(outPath)
self.makeDir("final") self.makeDir("final")
self.makeDir("daily_3일선_10일선_상향돌파")
self.makeDir("daily_3일선_10일선_하향돌파")
self.makeDir("weekly_4주선_48주선_상향돌파") self.makeDir("weekly_4주선_48주선_상향돌파")
self.makeDir("weekly_종가_12주선_상향돌파") self.makeDir("weekly_종가_12주선_상향돌파")
self.makeDir("weekly_rsi_20이하") self.makeDir("weekly_rsi_20이하")
@@ -297,7 +302,7 @@ class AnalyzerSqlite:
cursor = conn.cursor() cursor = conn.cursor()
sql = 'SELECT ymd, close, open, high, low, volume, ' sql = 'SELECT ymd, close, open, high, low, volume, '
sql += ' avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300, ' sql += ' avg3, avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300, '
sql += ' bolingerband_upper, bolingerband_lower, bolingerband_middle, ' sql += ' bolingerband_upper, bolingerband_lower, bolingerband_middle, '
sql += ' ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, ' sql += ' ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, '
sql += ' stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, ' sql += ' stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, '
@@ -311,7 +316,7 @@ class AnalyzerSqlite:
ymd = [] ymd = []
close, open, high, low, volume = [], [], [], [], [] close, open, high, low, volume = [], [], [], [], []
avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300 = [], [], [], [], [], [], [], [], [], [], [], [], [], [] avg3, avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300 = [], [], [], [], [], [], [], [], [], [], [], [], [], [], []
bolingerband_upper, bolingerband_lower, bolingerband_middle = [], [], [] bolingerband_upper, bolingerband_lower, bolingerband_middle = [], [], []
ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2 = [], [], [], [] ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2 = [], [], [], []
stochastic_fast_k, stochastic_slow_k, stochastic_slow_d = [], [], [] stochastic_fast_k, stochastic_slow_k, stochastic_slow_d = [], [], []
@@ -324,37 +329,38 @@ class AnalyzerSqlite:
high.append(price[3]) high.append(price[3])
low.append(price[4]) low.append(price[4])
volume.append(price[5]) volume.append(price[5])
avg4.append(price[6]) avg3.append(price[6])
avg5.append(price[7]) avg4.append(price[7])
avg6.append(price[8]) avg5.append(price[8])
avg10.append(price[9]) avg6.append(price[9])
avg12.append(price[10]) avg10.append(price[10])
avg20.append(price[11]) avg12.append(price[11])
avg36.append(price[12]) avg20.append(price[12])
avg40.append(price[13]) avg36.append(price[13])
avg48.append(price[14]) avg40.append(price[14])
avg60.append(price[15]) avg48.append(price[15])
avg120.append(price[16]) avg60.append(price[16])
avg200.append(price[17]) avg120.append(price[17])
avg240.append(price[18]) avg200.append(price[18])
avg300.append(price[19]) avg240.append(price[19])
bolingerband_upper.append(price[20]) avg300.append(price[20])
bolingerband_lower.append(price[21]) bolingerband_upper.append(price[21])
bolingerband_middle.append(price[22]) bolingerband_lower.append(price[22])
ichimokucloud_changeLine.append(price[23]) bolingerband_middle.append(price[23])
ichimokucloud_baseLine.append(price[24]) ichimokucloud_changeLine.append(price[24])
ichimokucloud_leadingSpan1.append(price[25]) ichimokucloud_baseLine.append(price[25])
ichimokucloud_leadingSpan2.append(price[26]) ichimokucloud_leadingSpan1.append(price[26])
stochastic_fast_k.append(price[27]) ichimokucloud_leadingSpan2.append(price[27])
stochastic_slow_k.append(price[28]) stochastic_fast_k.append(price[28])
stochastic_slow_d.append(price[29]) stochastic_slow_k.append(price[29])
rsi.append(price[30]) stochastic_slow_d.append(price[30])
rsis.append(price[31]) rsi.append(price[31])
rsis.append(price[32])
stock = { stock = {
"ymd": ymd, "ymd": ymd,
"close": close, "open": open, "high": high, "low": low, "volume": volume, "close": close, "open": open, "high": high, "low": low, "volume": volume,
"avg4": avg4, "avg5": avg5, "avg6": avg6, "avg10": avg10, "avg12": avg12, "avg20": avg20, "avg36": avg36, "avg40": avg40, "avg48": avg48, "avg60": avg60, "avg120": avg120, "avg200": avg200, "avg300": avg300, "avg3": avg3, "avg4": avg4, "avg5": avg5, "avg6": avg6, "avg10": avg10, "avg12": avg12, "avg20": avg20, "avg36": avg36, "avg40": avg40, "avg48": avg48, "avg60": avg60, "avg120": avg120, "avg200": avg200, "avg300": avg300,
"avg240": avg240, "avg240": avg240,
"bolingerband_upper": bolingerband_upper, "bolingerband_lower": bolingerband_lower, "bolingerband_upper": bolingerband_upper, "bolingerband_lower": bolingerband_lower,
"bolingerband_middle": bolingerband_middle, "bolingerband_middle": bolingerband_middle,
@@ -408,6 +414,26 @@ class AnalyzerSqlite:
# 종목 상태 체크 분석 # 종목 상태 체크 분석
# [Dailly]
if (stock_daily['avg3'][0] >= stock_daily['avg10'][0] and
stock_daily['avg3'][1] <= stock_daily['avg10'][1] and
stock_daily['avg3'][2] <= stock_daily['avg10'][2] and
stock_daily['avg3'][3] <= stock_daily['avg10'][3]):
type = "daily_3일선_10일선_상향돌파"
final_status += " " + type
final_status_count += 1
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
if (stock_daily['avg3'][0] <= stock_daily['avg10'][0] and
stock_daily['avg3'][1] >= stock_daily['avg10'][1] and
stock_daily['avg3'][2] >= stock_daily['avg10'][2] and
stock_daily['avg3'][3] >= stock_daily['avg10'][3]):
type = "daily_3일선_10일선_하향돌파"
final_status += " " + type
final_status_count += 1
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# [Weekly] # [Weekly]
# 정배열 체크 # 정배열 체크
temp_status = self.common.check_RightArrange(stock_weekly) temp_status = self.common.check_RightArrange(stock_weekly)
@@ -564,6 +590,7 @@ class AnalyzerSqlite:
return return
def get_moving_average(self, stock): def get_moving_average(self, stock):
q_3 = MovingAverage(3)
q_4 = MovingAverage(4) q_4 = MovingAverage(4)
q_5 = MovingAverage(5) q_5 = MovingAverage(5)
q_6 = MovingAverage(6) q_6 = MovingAverage(6)
@@ -580,6 +607,7 @@ class AnalyzerSqlite:
q_300 = MovingAverage(300) q_300 = MovingAverage(300)
for i in range(len(stock)): for i in range(len(stock)):
q_3.enqueue(stock[i]['close'])
q_4.enqueue(stock[i]['close']) q_4.enqueue(stock[i]['close'])
q_5.enqueue(stock[i]['close']) q_5.enqueue(stock[i]['close'])
q_6.enqueue(stock[i]['close']) q_6.enqueue(stock[i]['close'])
@@ -595,6 +623,7 @@ class AnalyzerSqlite:
q_240.enqueue(stock[i]['close']) q_240.enqueue(stock[i]['close'])
q_300.enqueue(stock[i]['close']) q_300.enqueue(stock[i]['close'])
stock[i]['avg3'] = q_3.avg()
stock[i]['avg4'] = q_4.avg() stock[i]['avg4'] = q_4.avg()
stock[i]['avg5'] = q_5.avg() stock[i]['avg5'] = q_5.avg()
stock[i]['avg6'] = q_6.avg() stock[i]['avg6'] = q_6.avg()
@@ -625,6 +654,7 @@ class AnalyzerSqlite:
"high": weekDict['high'][ts], "high": weekDict['high'][ts],
"low": weekDict['low'][ts], "low": weekDict['low'][ts],
"volume": weekDict['volume'][ts], "volume": weekDict['volume'][ts],
"avg3": -1,
"avg4": -1, "avg4": -1,
"avg5": -1, "avg5": -1,
"avg6": -1, "avg6": -1,
@@ -664,7 +694,7 @@ class AnalyzerSqlite:
stockAnalysisTableName = 'stock_analysis_' + type stockAnalysisTableName = 'stock_analysis_' + type
# 테이블 생성 # 테이블 생성
cursor.execute("CREATE TABLE IF NOT EXISTS " + stockAnalysisTableName + " (CODE text, NAME text, ymd text, close REAL, diff REAL, open REAL, high REAL, low REAL, volume REAL, avg4 REAL, avg5 REAL, avg6 REAL, avg10 REAL, avg12 REAL, avg20 REAL, avg36 REAL, avg40 REAL, avg48 REAL, avg60 REAL, avg120 REAL, avg200 REAL, avg240 REAL, avg300 REAL, bolingerband_upper REAL, bolingerband_lower REAL, bolingerband_middle REAL, ichimokucloud_changeLine REAL, ichimokucloud_baseLine REAL, ichimokucloud_leadingSpan1 REAL, ichimokucloud_leadingSpan2 REAL, stochastic_fast_k REAL, stochastic_slow_k REAL, stochastic_slow_d REAL, rsi REAL, rsis REAL)") cursor.execute("CREATE TABLE IF NOT EXISTS " + stockAnalysisTableName + " (CODE text, NAME text, ymd text, close REAL, diff REAL, open REAL, high REAL, low REAL, volume REAL, avg3 REAL, avg4 REAL, avg5 REAL, avg6 REAL, avg10 REAL, avg12 REAL, avg20 REAL, avg36 REAL, avg40 REAL, avg48 REAL, avg60 REAL, avg120 REAL, avg200 REAL, avg240 REAL, avg300 REAL, bolingerband_upper REAL, bolingerband_lower REAL, bolingerband_middle REAL, ichimokucloud_changeLine REAL, ichimokucloud_baseLine REAL, ichimokucloud_leadingSpan1 REAL, ichimokucloud_leadingSpan2 REAL, stochastic_fast_k REAL, stochastic_slow_k REAL, stochastic_slow_d REAL, rsi REAL, rsis REAL)")
# 키 생성 # 키 생성
create_key = "CREATE INDEX IF NOT EXISTS " + stockAnalysisTableName + "_idx on " + stockAnalysisTableName + " (CODE, ymd) " create_key = "CREATE INDEX IF NOT EXISTS " + stockAnalysisTableName + "_idx on " + stockAnalysisTableName + " (CODE, ymd) "
@@ -685,16 +715,16 @@ class AnalyzerSqlite:
result = cursor.fetchone() result = cursor.fetchone()
if result == None: if result == None:
sql = "INSERT INTO " + stockAnalysisTableName + "(CODE, NAME, ymd, close, diff, open, high, low, volume, " sql = "INSERT INTO " + stockAnalysisTableName + "(CODE, NAME, ymd, close, diff, open, high, low, volume, "
sql += " avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300, " sql += " avg3, avg4, avg5, avg6, avg10, avg12, avg20, avg36, avg40, avg48, avg60, avg120, avg200, avg240, avg300, "
sql += " bolingerband_upper, bolingerband_lower, bolingerband_middle, " sql += " bolingerband_upper, bolingerband_lower, bolingerband_middle, "
sql += " ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, " sql += " ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, "
sql += " stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, " sql += " stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, "
sql += " rsi, rsis) " sql += " rsi, rsis) "
sql += " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" sql += " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
cursor.execute(sql, ( cursor.execute(sql, (
stock["CODE"], stock["NAME"], price['ymd'], price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'], stock["CODE"], stock["NAME"], price['ymd'], price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'],
price['avg4'], price['avg5'], price['avg6'], price['avg10'], price['avg12'], price['avg20'], price['avg36'], price['avg40'], price['avg48'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'], price['avg3'], price['avg4'], price['avg5'], price['avg6'], price['avg10'], price['avg12'], price['avg20'], price['avg36'], price['avg40'], price['avg48'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'],
price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'], price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'],
price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'], price['ichimokucloud_leadingSpan1'], price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'], price['ichimokucloud_leadingSpan1'],
price['ichimokucloud_leadingSpan2'], price['ichimokucloud_leadingSpan2'],
@@ -703,7 +733,7 @@ class AnalyzerSqlite:
else: else:
sql = "UPDATE " + stockAnalysisTableName + " SET close=?, diff=?, open=?, high=?, low=?, volume=?, " sql = "UPDATE " + stockAnalysisTableName + " SET close=?, diff=?, open=?, high=?, low=?, volume=?, "
sql += " avg4=?, avg5=?, avg6=?, avg10=?, avg12=?, avg20=?, avg36=?, avg40=?, avg48=?, avg60=?, avg120=?, avg200=?, avg240=?, avg300=?, " sql += " avg3=?, avg4=?, avg5=?, avg6=?, avg10=?, avg12=?, avg20=?, avg36=?, avg40=?, avg48=?, avg60=?, avg120=?, avg200=?, avg240=?, avg300=?, "
sql += " bolingerband_upper=?, bolingerband_lower=?, bolingerband_middle=?, " sql += " bolingerband_upper=?, bolingerband_lower=?, bolingerband_middle=?, "
sql += " ichimokucloud_changeLine=?, ichimokucloud_baseLine=?, ichimokucloud_leadingSpan1=?, ichimokucloud_leadingSpan2=?, " sql += " ichimokucloud_changeLine=?, ichimokucloud_baseLine=?, ichimokucloud_leadingSpan1=?, ichimokucloud_leadingSpan2=?, "
sql += " stochastic_fast_k=?, stochastic_slow_k=?, stochastic_slow_d=?, " sql += " stochastic_fast_k=?, stochastic_slow_k=?, stochastic_slow_d=?, "
@@ -712,7 +742,7 @@ class AnalyzerSqlite:
cursor.execute(sql, cursor.execute(sql,
(price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'], (price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'],
price['avg4'], price['avg5'], price['avg6'], price['avg10'], price['avg12'], price['avg20'], price['avg36'], price['avg40'], price['avg48'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'], price['avg3'], price['avg4'], price['avg5'], price['avg6'], price['avg10'], price['avg12'], price['avg20'], price['avg36'], price['avg40'], price['avg48'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'],
price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'], price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'], price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'], price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'],
price['ichimokucloud_leadingSpan1'], price['ichimokucloud_leadingSpan2'], price['ichimokucloud_leadingSpan1'], price['ichimokucloud_leadingSpan2'],
price['stochastic_fast_k'], price['stochastic_slow_k'], price['stochastic_slow_d'], price['stochastic_fast_k'], price['stochastic_slow_k'], price['stochastic_slow_d'],
@@ -752,6 +782,7 @@ class AnalyzerSqlite:
"high": item[4], "high": item[4],
"low": item[5], "low": item[5],
"volume": item[6], "volume": item[6],
"avg3": -1,
"avg4": -1, "avg4": -1,
"avg5": -1, "avg5": -1,
"avg6": -1, "avg6": -1,
@@ -815,6 +846,7 @@ class AnalyzerSqlite:
"high": item[4], "high": item[4],
"low": item[5], "low": item[5],
"volume": item[6], "volume": item[6],
"avg3": -1,
"avg4": -1, "avg4": -1,
"avg5": -1, "avg5": -1,
"avg6": -1, "avg6": -1,

View File

@@ -1,5 +1,5 @@
import pandas as pd import pandas as pd
from stockpredictor.analysis.Common import Common from stock.analysis.Common import Common
import plotly.graph_objs as go import plotly.graph_objs as go
from plotly import tools, subplots from plotly import tools, subplots
import plotly.io as po import plotly.io as po

View File

@@ -338,7 +338,7 @@ class StockCrawler:
continue continue
stock_data.append({ stock_data.append({
'CODE':item_code, 'NAME':us_stocks[item_code], 'ymd': ymd.strftime('%Y.%m.%d'), 'CODE':item_code, 'NAME':special_stocks[item_code], 'ymd': ymd.strftime('%Y.%m.%d'),
'close': round(stock['close'][ymd], 2), 'diff': round(diff, 2), 'open': round(stock['open'][ymd], 2), 'close': round(stock['close'][ymd], 2), 'diff': round(diff, 2), 'open': round(stock['open'][ymd], 2),
'high': round(stock['high'][ymd], 2), 'low': round(stock['low'][ymd], 2), 'volume': stock['volume'][ymd] 'high': round(stock['high'][ymd], 2), 'low': round(stock['low'][ymd], 2), 'volume': stock['volume'][ymd]
}) })
@@ -358,7 +358,7 @@ class StockCrawler:
conn.commit() conn.commit()
cursor.close() cursor.close()
conn.close() conn.close()
print(idx, item_code, us_stocks[item_code], (time.time() - start_time), "s") print(idx, item_code, special_stocks[item_code], (time.time() - start_time), "s")
start_time = time.time() start_time = time.time()
sleep(0.05) sleep(0.05)
@@ -400,9 +400,9 @@ class StockCrawler:
if date == lastDay: if date == lastDay:
lastPage = True lastPage = True
df = df.append(html[0], ignore_index=True) df = pd.concat((df, html[0]), ignore_index=True)
break break
df = df.append(html[0], ignore_index=True) df = pd.concat((df, html[0]), ignore_index=True)
df = df.dropna() df = df.dropna()
if (lastPage) or (len(df) < 1) or ("날짜" not in df) or (df.날짜[1]==''): if (lastPage) or (len(df) < 1) or ("날짜" not in df) or (df.날짜[1]==''):
print("\t- lastpage:", page) print("\t- lastpage:", page)

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