diff --git a/HTS_252670_daily.py b/HTS_252670_daily.py index bbef554..7dc59f8 100644 --- a/HTS_252670_daily.py +++ b/HTS_252670_daily.py @@ -2,7 +2,7 @@ import time import os from datetime import datetime -from hts.DailyStatus import DailyStatus +from stock.analysis.DailyStatus import DailyStatus from hts.HTS import HTS from hts.OrderType import OrderType diff --git a/Simulation.py b/Simulation.py index b67d10e..3d4d9d9 100644 --- a/Simulation.py +++ b/Simulation.py @@ -1,4 +1,3 @@ -import numpy as np from math import nan import pandas as pd import plotly.graph_objects as go @@ -9,6 +8,7 @@ from hts.HTS import HTS from stock.util.Stock2Vector import Stock2Vector from stock.util.LabelChecker import LabelChecker from stock.util.StockPredictor import StockPredictor +from stock.analysis.DailyStatus import DailyStatus from hts.BuySellChecker import BuySellChecker class Simulation (HTS): @@ -163,36 +163,24 @@ class Simulation (HTS): return - def simulate(self, stock_code, today, method="rule"): + def simulate(self, stock_codes:dict=None): - if method == "answer": - #self.labelMaker.makeCandidate(stock_code, today, view=True) - self.labelChecker.showLabels(stock_code, today) + if stock_codes is not None: + for stock_code in stock_codes: + for given_day in stock_codes[stock_code]: + LAST_DATA = self.stock2Vector.getLastData(stock_code, given_day) + result = self.stock2Vector.getRealTime(stock_code, given_day, LAST_DATA) + + # 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다. + data = self.buySellChecker.analyze(result) + # 사야 할 시점과 팔아야 할 시점을 체크한다. + bsLine, data = self.buySellChecker.checkTransaction(data, stock_code, isRealTime=False) + + # 그래프를 그린다. + self.draw(stock_code, given_day, data, bsLine) else: - if method == "ml": - LAST_DATA = self.stock2Vector.getLastData(stock_code, today, n=3) - result = self.stock2Vector.getRealTime(stock_code, today, LAST_DATA) - X, Y = self.stock2Vector.getVectorData(result) - - predY = self.stockPredictor.predict(X, Y) - predY = np.argmax(predY, axis=1) - - # 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다. - data = self.buySellChecker.analyze(result) - # 사야 할 시점과 팔아야 할 시점을 체크한다. - bsLine, data = self.buySellChecker.checkTransactionML(data, stock_code, predY, isRealTime=False) - else: - LAST_DATA = self.stock2Vector.getLastData(stock_code, today) - result = self.stock2Vector.getRealTime(stock_code, today, LAST_DATA) - - # 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다. - data = self.buySellChecker.analyze(result) - # 사야 할 시점과 팔아야 할 시점을 체크한다. - bsLine, data = self.buySellChecker.checkTransaction(data, stock_code, isRealTime=False) - - if data is not None: - # 그래프를 그린다. - self.draw(stock_code, today, data, bsLine) + dailyStatus = DailyStatus(self.RESOURCE_PATH) + dailyStatus.checkEnvelope() return @@ -201,6 +189,8 @@ if __name__ == "__main__": PROJECT_HOME = os.getcwd() RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") + simulation = Simulation(RESOURCE_PATH) + # to check bying stock_codes = { "252670": [ @@ -208,24 +198,7 @@ if __name__ == "__main__": '20220908','20220913','20220914','20220915','20220916' ] } - """ - # 122630 - "252670": [ - '20220801', '20220802', '20220803', '20220804', '20220805', - '20220808', '20220809', '20220810', '20220811', '20220812', - '20220816', '20220817', '20220818', '20220819', '20220822', - '20220823', '20220824', '20220825', '20220826', '20220829', - '20220830', '20220831', - '20220901', '20220902', '20220905', '20220906','20220907', - '20220908' - ], - """ - - method = "rule" # "rule", "ml", "answer" - for stock_code in stock_codes: - simulation = Simulation(RESOURCE_PATH) - - for given_day in stock_codes[stock_code]: - simulation.simulate(stock_code, given_day, method=method) + #simulation.simulate(stock_codes) + simulation.simulate() print ("done...") diff --git a/Simulation_Daily.py b/Simulation_Daily.py deleted file mode 100644 index d1739be..0000000 --- a/Simulation_Daily.py +++ /dev/null @@ -1,388 +0,0 @@ -import numpy as np -from math import nan -import shutil -import sqlite3 -import pandas as pd -import plotly.graph_objects as go -from plotly import subplots -import plotly.io as po -import os -from datetime import datetime - -from hts.HTS import HTS -from hts.DailyStatus import DailyStatus -from hts.BuySellChecker import BuySellChecker - -class Simulation (HTS): - buySellChecker = None - stockPredictor = None - dailyStatus = None - - def __init__(self, RESOURCE_PATH): - super().__init__(RESOURCE_PATH) - - self.RESOURCE_PATH = RESOURCE_PATH - - self.buySellChecker = BuySellChecker() - - self.dailyStatus = DailyStatus(RESOURCE_PATH) - return - - def draw(self, stock_code, given_day, data, bsLine): - if bsLine is None: - return - - # 어제 데이터는 지운다. - buy_line = bsLine['buy'] - buy_weight_line = bsLine['buy_weight'] - sell_line = bsLine['sell'] - - buy_size = [] - buy_colors = [] - for i in range(len(buy_line)): - if buy_line[i] < 0: - buy_colors.append("#ffffff") - buy_line[i] = nan - buy_size.append(0) - else: - buy_colors.append("#B2028C") - buy_size.append(10 + (0.1 * buy_weight_line[i])) - - sell_colors = [] - for i in range(len(sell_line)): - if sell_line[i] < 0: - sell_colors.append("#ffffff") - sell_line[i] = nan - else: - sell_colors.append("#00ced1") - - # 그래프를 설정한다. - buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) - sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) - envelope_upper = go.Scatter(x=data['ymd'], y=data["envelope_upper"], name="upper", line_color='#000000') - envelope_middle = go.Scatter(x=data['ymd'], y=data["envelope_middle"], name="upper", line_color='#927786') - envelope_lower = go.Scatter(x=data['ymd'], y=data["envelope_lower"], name="lower", line_color='#000000') - - avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') - avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') - avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') - candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) - - macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') - macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') - - # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') - slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') - slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') - - rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') - rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') - - disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') - disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') - disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') - - candle_data = [candle_stick, avg5, avg20, avg60, envelope_upper, envelope_middle, envelope_lower, buy_check, sell_check] - disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] - macd_data = [macd_line, macd_s_line] - stochastic_data = [slow_k_line, slow_d_line] - rsi_data = [rsi_line, rsis_line] - - # 그래프를 그린다. - """ - fig = go.Figure(data=candle_data) - fig.update_layout(title=stock_code + "_" + given_day) - fig.show() - """ - - fig = subplots.make_subplots( - rows=5, cols=1, - subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), - #specs=[[{}], [{}], [{}], [{}], [{}], [{}]], - shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, - row_heights=[200, 200, 200, 200, 750] - ) - for trace in macd_data: - fig.append_trace(trace, 1, 1) - for trace in rsi_data: - fig.append_trace(trace, 2, 1) - for trace in stochastic_data: - fig.append_trace(trace, 3, 1) - for trace in disparity_data: - fig.append_trace(trace, 4, 1) - for trace in candle_data: - fig.append_trace(trace, 5, 1) - - - #fig.update_xaxes(nticks=5) - #fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False) - - df = pd.DataFrame(bsLine) - df = df.fillna(-1) - buy_count = len(df.loc[df["buy"] > 0]) - sell_count = len(df.loc[df["sell"] > 0]) - - fig.update_layout(height=1700, title=stock_code + "_" + given_day + "_" + str(buy_count)+","+str(sell_count)) - #fig.update_layout(title=stock_code + "_" + given_day + "_" + str(buy_count) + "," + str(sell_count)) - fig.show() - - return - - def writeFile(self, dailyDirName, stock_code, stock_name, given_day, data, bsLine): - if bsLine is None: - return - - # 어제 데이터는 지운다. - buy_line = bsLine['buy'] - buy_weight_line = bsLine['buy_weight'] - sell_line = bsLine['sell'] - - buy_size = [] - buy_colors = [] - for i in range(len(buy_line)): - if buy_line[i] < 0: - buy_colors.append("#ffffff") - buy_line[i] = nan - buy_size.append(0) - else: - buy_colors.append("#B2028C") - buy_size.append(10 + (0.1 * buy_weight_line[i])) - - sell_colors = [] - for i in range(len(sell_line)): - if sell_line[i] < 0: - sell_colors.append("#ffffff") - sell_line[i] = nan - else: - sell_colors.append("#00ced1") - - # 그래프를 설정한다. - buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) - sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) - envelope_upper = go.Scatter(x=data['ymd'], y=data["envelope_upper"], name="upper", line_color='#000000') - envelope_middle = go.Scatter(x=data['ymd'], y=data["envelope_middle"], name="upper", line_color='#927786') - envelope_lower = go.Scatter(x=data['ymd'], y=data["envelope_lower"], name="lower", line_color='#000000') - - avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') - avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') - avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') - candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) - - macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') - macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') - - # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') - slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') - slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') - - rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') - rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') - - disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') - disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') - disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') - - candle_data = [candle_stick, avg5, avg20, avg60, envelope_upper, envelope_middle, envelope_lower, buy_check, sell_check] - disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] - macd_data = [macd_line, macd_s_line] - stochastic_data = [slow_k_line, slow_d_line] - rsi_data = [rsi_line, rsis_line] - - # 그래프를 그린다. - """ - fig = go.Figure(data=candle_data) - fig.update_layout(title=stock_code + "_" + given_day) - fig.show() - """ - - fig = subplots.make_subplots( - rows=5, cols=1, - subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), - #specs=[[{}], [{}], [{}], [{}], [{}], [{}]], - shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, - row_heights=[200, 200, 200, 200, 750] - ) - for trace in macd_data: - fig.append_trace(trace, 1, 1) - for trace in rsi_data: - fig.append_trace(trace, 2, 1) - for trace in stochastic_data: - fig.append_trace(trace, 3, 1) - for trace in disparity_data: - fig.append_trace(trace, 4, 1) - for trace in candle_data: - fig.append_trace(trace, 5, 1) - - - #fig.update_xaxes(nticks=5) - #fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False) - - df = pd.DataFrame(bsLine) - df = df.fillna(-1) - buy_count = len(df.loc[df["buy"] > 0]) - sell_count = len(df.loc[df["sell"] > 0]) - - fig.update_layout(height=1700, title=stock_code + "_" + given_day + "_" + str(buy_count)+","+str(sell_count)) - #fig.update_layout(title=stock_code + "_" + given_day + "_" + str(buy_count) + "," + str(sell_count)) - #fig.show() - - fileName = "%s/%s_%s.html" % (dailyDirName, stock_code, stock_name.replace(" ", "")) - po.write_html(fig, file=fileName, auto_open=False) - - return - - def getData(self, today, stock): - close = stock['PRICE'][len(stock['PRICE']) - 1]["close"] - open = stock['PRICE'][len(stock['PRICE']) - 1]["open"] - high = stock['PRICE'][len(stock['PRICE']) - 1]["high"] - low = stock['PRICE'][len(stock['PRICE']) - 1]["low"] - volume = stock['PRICE'][len(stock['PRICE']) - 1]["volume"] - - stock['PRICE'].append( - { - "ymd": today, - "close": close, - "diff": stock['PRICE'][len(stock['PRICE']) - 1]["close"] - close, - "open": open, - "high": high, - "low": low, - "volume": volume, - "avg3": -1, - "avg4": -1, - "avg5": -1, - "avg6": -1, - "avg10": -1, - "avg12": -1, - "avg20": -1, - "avg36": -1, - "avg40": -1, - "avg48": -1, - "avg60": -1, - "avg120": -1, - "avg200": -1, - "avg240": -1, - "avg300": -1, - "disparity_avg5": -1, - "disparity_avg10": -1, - "disparity_avg20": -1, - "disparity_avg60": -1, - "disparity_avg120": -1, - "bolingerband_upper": -1, - "bolingerband_lower": -1, - "bolingerband_middle": -1, - "envelope_upper": -1, - "envelope_lower": -1, - "envelope_middle": -1, - "ichimokucloud_changeLine": -1, - "ichimokucloud_baseLine": -1, - "ichimokucloud_leadingSpan1": -1, - "ichimokucloud_leadingSpan2": -1, - "stochastic_fast_k": -1, - "stochastic_slow_k": -1, - "stochastic_slow_d": -1, - "rsi": -1, - "rsis": -1, - "macd": -1, - "macds": -1, - "macdo": -1, - } - ) - - return - - def simulate(self, stock_code=None, isRealTime=False): - if not isRealTime: - n = 200 - else: - n = 200 - - if stock_code is not None: - stock = self.dailyStatus.getLastData(stock_code, n) - - today = datetime.today().strftime('%Y%m%d') - self.getData(today, stock) - analyzed_day = 60 - data = self.dailyStatus.analyze(stock, analyzed_day) - # 분석일 데이터만 활용한다 (이전 데이터는 제거) - data.drop(data.index[:analyzed_day], inplace=True) - - # print logs - for i in range(len(data.index)): - print (i, data.index[i], data['macd'][i], data['slow_k'][i], data['gradients_low'][i], data['gradients_avg5'][i], data['gradients_avg20'][i], data['gradients_avg60'][i], data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity'][i], data['disparity_type'][i]) - - bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, isRealTime=False) - - # 그래프를 그린다. - self.draw(stock_code, today, data, bsLine) - else: - stockTableName = 'stock' - PROJECT_HOME = os.path.join(os.path.dirname(__file__)) - stockFileName = PROJECT_HOME + '/resources/stock.db' - - conn = sqlite3.connect(stockFileName) - cursor = conn.cursor() - cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code') - items = cursor.fetchall() - cursor.close() - conn.close() - - today = datetime.today().strftime('%Y%m%d') - dailyDirName = os.path.join(RESOURCE_PATH, 'analysis', today, 'daily') - if os.path.exists(dailyDirName): - shutil.rmtree(dailyDirName) - - dailyDirName = os.path.join(RESOURCE_PATH, 'analysis', today) - if not os.path.isdir(dailyDirName): - os.mkdir(dailyDirName) - dailyDirName = os.path.join(dailyDirName, 'daily') - if not os.path.isdir(dailyDirName): - os.mkdir(dailyDirName) - - for idx, item in enumerate(items): - stock_code = item[0] - stock_name = item[1] - print(idx, stock_code, stock_name) - print("Analysis # :", idx, ", CODE: ", stock_code, ", NAME: ", stock_name) - - stock = self.dailyStatus.getLastData(stock_code, n) - - today = datetime.today().strftime('%Y%m%d') - self.getData(today, stock) - analyzed_day = 60 - data = self.dailyStatus.analyze(stock, analyzed_day) - # 분석일 데이터만 활용한다 (이전 데이터는 제거) - data.drop(data.index[:analyzed_day], inplace=True) - - # print logs - # for i in range(len(data.index)): - # print (i, data.index[i], data['macd'][i], data['slow_k'][i], data['gradients_low'][i], data['gradients_avg5'][i], data['gradients_avg20'][i], data['gradients_avg60'][i], data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity'][i], data['disparity_type'][i]) - - bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, isRealTime=False) - - # 그래프를 그린다. - - if len(data.index) > 10 and max(bsLine['buy'][len(bsLine['buy'])-2:]) > 0: - self.writeFile(dailyDirName, stock_code, stock_name, today, data, bsLine) - - return - -if __name__ == "__main__": - - PROJECT_HOME = os.getcwd() - RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") - - simulation = Simulation(RESOURCE_PATH) - - # to check buying - #stock_codes = ["252670", "122630"] - #stock_codes = ["051600", "139130", "066570", "000990"] - stock_codes = ["102950"] - - """ - for stock_code in stock_codes: - simulation.simulate(stock_code) - """ - - simulation.simulate() - print ("done...") - diff --git a/StockCrawler.py b/StockCrawler.py index 779b34b..173a647 100644 --- a/StockCrawler.py +++ b/StockCrawler.py @@ -7,6 +7,7 @@ from stock.crawler.FnGuideCrawler import FnGuideCrawler from stock.crawler.MetaCrawler import MetaCrawler from stock.crawler.StockCrawler import StockCrawler from stock.analysis.AnalyzerSqlite import AnalyzerSqlite +from stock.analysis.DailyStatus import DailyStatus today = datetime.now().strftime("%Y-%m-%d") @@ -16,7 +17,8 @@ PROJECT_HOME = os.getcwd() START_DATE = "2000.01.01" start = time.time() -stockFileName = PROJECT_HOME + '/resources/stock.db' +RESOURCE_PATH = os.path.join(PROJECT_HOME, 'resources') +stockFileName = os.path.join(RESOURCE_PATH, 'stock.db') week = datetime.today().weekday() @@ -71,9 +73,13 @@ if week in (0, 1, 2, 3, 4): # 0:월, 1:화, 2:수, 3:목, 4:금, 5:토, 6:일 if os.path.isdir(outPath): shutil.rmtree(outPath) os.mkdir(outPath) - print("print to Html...") - analyzerSqlite.findCandidate(outPath) + print("print to Html...") + # envelopes를 이용한 daily check + dailyStatus = DailyStatus(RESOURCE_PATH) + dailyStatus.checkEnvelope() + + analyzerSqlite.findCandidate(outPath) print("time : %6.2f 초", (time.time() - start)) print ("done...") diff --git a/hts/BuySellChecker.py b/hts/BuySellChecker.py index 8b46b8a..7ae4e59 100644 --- a/hts/BuySellChecker.py +++ b/hts/BuySellChecker.py @@ -1071,12 +1071,27 @@ class BuySellChecker: bsLine['sell'] = [-1 for i in range(size)] bsLine['sell_weight'] = [-1 for i in range(size)] + gap_interval = 60 + gap_state = False for i in range(size): if isRealTime: if i < size - 1: continue if i > 10: + # 만약 전일 저가와 오늘 종의 차이가 1만원이 넘으면 향후 60일은 분석하지 않는다. + if data['low'][i-1] - data['high'][i] > 10000: + gap_state = True + gap_interval -= 1 + continue + if gap_state: + if gap_interval <= 0: + gap_state = False + gap_interval = 60 + else: + gap_interval -= 1 + continue + if data['disparity'][i] < 2: check = True for l in range(i-3, i): diff --git a/hts/DailyStatus.py b/hts/DailyStatus.py deleted file mode 100644 index 4966c1a..0000000 --- a/hts/DailyStatus.py +++ /dev/null @@ -1,356 +0,0 @@ -import os.path -import pandas as pd -import platform -if platform.system().lower().find("window") >= 0 and platform.architecture()[0] != "64bit" : - import win32com.client - -import sqlite3 -from sklearn.linear_model import LinearRegression -from sklearn.preprocessing import StandardScaler, MinMaxScaler - -from stock.analysis.AnalyzerSqlite import AnalyzerSqlite -class DailyStatus: - tableName = None - dbFileName = None - RESOURCE_PATH = None - analyzerSqlite = None - - def __init__(self, RESOURCE_PATH): - self.RESOURCE_PATH = RESOURCE_PATH - self.tableName = 'stock' - self.dbFileName = "stock.db" - self.analyzerSqlite = AnalyzerSqlite(os.path.join(self.RESOURCE_PATH, self.dbFileName)) - return - - def getDBData(self, stock_code, day, result): - conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) - cursor = conn.cursor() - - cursor.execute('SELECT ymd, close, open, high, low, envelope_upper, envelope_lower, envelope_middle, rsi, rsis, macd, macds, stochastic_slow_k, stochastic_slow_d FROM ' + self.tableName + ' WHERE CODE=? and ymd=? order by ymd', (stock_code, day,)) - db_result = cursor.fetchall() - for rows in db_result: - ymd = rows[0] - close = rows[1] - open = rows[2] - high = rows[3] - low = rows[4] - envelope_upper = rows[5] - envelope_lower = rows[6] - envelope_middle = rows[7] - rsi = 0 if rows[8] is None else rows[8] - rsis = 0 if rows[9] is None else rows[9] - macd = rows[10] - macds = rows[11] - stochastic_slow_k = 0 if rows[12] is None else rows[12] - stochastic_slow_d = 0 if rows[13] is None else rows[13] - - result["ymd"].append(ymd) - result["open"].append(int(open)) - result["close"].append(int(close)) - result["high"].append(int(high)) - result["low"].append(int(low)) - result["envelope_upper"].append(int(envelope_upper)) - result["envelope_lower"].append(int(envelope_lower)) - result["envelope_middle"].append(int(envelope_middle)) - result["rsi"].append(int(rsi)) - result["rsis"].append(int(rsis)) - result["macd"].append(int(macd)) - result["macds"].append(int(macds)) - result["slow_k"].append(int(stochastic_slow_k)) - result["slow_d"].append(int(stochastic_slow_d)) - - return - - def isValidYMD(self, stock_code, day): - conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) - cursor = conn.cursor() - - cursor.execute('SELECT ymd, count(*) as cnt FROM ' + self.tableName + ' WHERE CODE=? and ymd=?', (stock_code, day,)) - db_result = cursor.fetchone() - if db_result[1] > 0: - return True - return False - - def getLastData(self, stock_code, limit=350): - stockTableName = 'stock' - - conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) - cursor = conn.cursor() - - stock = {"CODE": stock_code, "NAME": "", "PRICE": []} - - sql = 'SELECT ymd, close, diff, open, high, low, volume FROM ' + stockTableName + ' where CODE=? order by ymd desc ' - sql += ' limit ' + str(limit) - cursor.execute(sql, (stock['CODE'],)) - items = cursor.fetchall() - - items_reverse = reversed(items) - for item in items_reverse: - stock['PRICE'].append( - { - "ymd": item[0], - "close": item[1], - "diff": item[2], - "open": item[3], - "high": item[4], - "low": item[5], - "volume": item[6], - "avg3": -1, - "avg4": -1, - "avg5": -1, - "avg6": -1, - "avg10": -1, - "avg12": -1, - "avg20": -1, - "avg36": -1, - "avg40": -1, - "avg48": -1, - "avg60": -1, - "avg120": -1, - "avg200": -1, - "avg240": -1, - "avg300": -1, - "disparity_avg5": -1, - "disparity_avg10": -1, - "disparity_avg20": -1, - "disparity_avg60": -1, - "disparity_avg120": -1, - "bolingerband_upper": -1, - "bolingerband_lower": -1, - "bolingerband_middle": -1, - "envelope_upper": -1, - "envelope_lower": -1, - "envelope_middle": -1, - "ichimokucloud_changeLine": -1, - "ichimokucloud_baseLine": -1, - "ichimokucloud_leadingSpan1": -1, - "ichimokucloud_leadingSpan2": -1, - "stochastic_fast_k": -1, - "stochastic_slow_k": -1, - "stochastic_slow_d": -1, - "rsi": -1, - "rsis": -1, - "macd": -1, - "macds": -1, - "macdo": -1, - } - ) - - conn.commit() - cursor.close() - conn.close() - - return stock - - def analyze (self, stock, days=120): - stock["PRICE"] = sorted(stock["PRICE"], key=lambda x: x['ymd']) - self.analyzerSqlite.get_moving_average(stock["PRICE"]) - - # 이동 평균을 이용한 이격도 계산 - self.analyzerSqlite.get_disparity(stock["PRICE"]) - - self.analyzerSqlite.ichimokuCloud.analyze(stock) - self.analyzerSqlite.stochastic.analyze(stock) - self.analyzerSqlite.bolingerBand.analyze(stock) - self.analyzerSqlite.envelope.analyze(stock) - self.analyzerSqlite.rsi.analyze(stock) - self.analyzerSqlite.macd.analyze(stock) - - result = { - "ymd": [], - "open": [], - "close": [], - "high": [], - "low": [], - "avg3": [], - "avg4": [], - "avg5": [], - "avg6": [], - "avg10": [], - "avg12": [], - "avg20": [], - "avg36": [], - "avg40": [], - "avg48": [], - "avg60": [], - "avg120": [], - "avg200": [], - "avg240": [], - "avg300": [], - "disparity_avg5": [], - "disparity_avg20": [], - "disparity_avg60": [], - "disparity_avg120": [], - "disparity": [], - "disparity_type": [], - "envelope_upper": [], - "envelope_lower": [], - "envelope_middle": [], - "rsi": [], - "rsis": [], - "macd": [], - "macds": [], - "slow_k": [], - "slow_d": [], - "buy": [], - "sell": [], - } - for item in stock['PRICE']: - result["ymd"].append(item['ymd']) - result["open"].append(item['open']) - result["close"].append(item['close']) - result["high"].append(item['high']) - result["low"].append(item['low']) - result["avg3"].append(item['avg3']) - result["avg4"].append(item['avg4']) - result["avg5"].append(item['avg5']) - result["avg6"].append(item['avg6']) - result["avg10"].append(item['avg10']) - result["avg12"].append(item['avg12']) - result["avg20"].append(item['avg20']) - result["avg36"].append(item['avg36']) - result["avg40"].append(item['avg40']) - result["avg48"].append(item['avg48']) - result["avg60"].append(item['avg60']) - result["avg120"].append(item['avg120']) - result["avg200"].append(item['avg200']) - result["avg240"].append(item['avg240']) - result["avg300"].append(item['avg300']) - result["disparity_avg5"].append(item['disparity_avg5']) - result["disparity_avg20"].append(item['disparity_avg20']) - result["disparity_avg60"].append(item['disparity_avg60']) - result["disparity_avg120"].append(item['disparity_avg120']) - result['disparity'].append(max(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60']) - min(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60'])) - if item['disparity_avg60'] < item['disparity_avg20'] < item['disparity_avg5']: - result['disparity_type'].append(1) - elif item['disparity_avg5'] < item['disparity_avg20'] < item['disparity_avg60']: - result['disparity_type'].append(-1) - else: - result['disparity_type'].append(0) - result["envelope_upper"].append(item['envelope_upper']) - result["envelope_lower"].append(item['envelope_lower']) - result["envelope_middle"].append(item['envelope_middle']) - result["rsi"].append(item['rsi']) - result["rsis"].append(item['rsis']) - result["macd"].append(item['macd']) - result["macds"].append(item['macds']) - result["slow_k"].append(item['stochastic_slow_k']) - result["slow_d"].append(item['stochastic_slow_d']) - result["buy"].append(-1) - result["sell"].append(-1) - - data = pd.DataFrame(result) - df_final_time = pd.DatetimeIndex(result['ymd']) - data.index = df_final_time - - data = data.astype( - { - 'open': 'int', - 'high': 'int', - 'low': 'int', - 'close': 'int', - 'avg3': 'float', - 'avg4': 'float', - 'avg5': 'float', - 'avg6': 'float', - 'avg10': 'float', - 'avg12': 'float', - 'avg20': 'float', - 'avg36': 'float', - 'avg40': 'float', - 'avg48': 'float', - 'avg60': 'float', - 'avg120': 'float', - 'avg200': 'float', - 'avg240': 'float', - 'avg300': 'float', - 'disparity_avg5': 'float', - 'disparity_avg20': 'float', - 'disparity_avg60': 'float', - 'disparity_avg120': 'float', - 'buy': 'int', - 'sell': 'int', - 'slow_k': 'float', - 'slow_d': 'float', - 'macd': 'float', - 'macds': 'float', - 'envelope_upper': 'float', - 'envelope_lower': 'float', - 'envelope_middle': 'float', - 'rsi': 'float', - 'rsis': 'float' - } - ) - - scaler = StandardScaler() - low_df = pd.DataFrame(data['low']) - low_df.index = [c for c in range(len(low_df))] - low_std = scaler.fit_transform(data['low'].values.reshape(-1, 1)) - low_std = pd.DataFrame(low_std, columns=['low_std']) - - min_df = pd.DataFrame({'open': data['open'].to_list(), 'close': data['close'].to_list()}) - min_df['min_std'] = min_df.min(axis=1) - min_df.index = [c for c in range(len(min_df))] - min_std = scaler.fit_transform(min_df['min_std'].values.reshape(-1, 1)) - min_std = pd.DataFrame(min_std, columns=['min_std']) - - line_fitter = LinearRegression() - size = len(data["close"]) - gradients_low = [] - gradients_avg5 = [] - gradients_avg20 = [] - gradients_avg60 = [] - - for i in range(size): - coef_low = -999 - coef_avg5 = -999 - coef_avg20 = -999 - coef_avg60 = -999 - - if i > 0: - l = days if i >= days else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(low_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_low = line_fitter.coef_[0][0] - - l = 5 if i >= 5 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg5 = line_fitter.coef_[0][0] - - l = 20 if i >= 20 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg20 = line_fitter.coef_[0][0] - - l = 60 if i >= 60 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg60 = line_fitter.coef_[0][0] - - gradients_low.append(coef_low) - gradients_avg5.append(coef_avg5) - gradients_avg20.append(coef_avg20) - gradients_avg60.append(coef_avg60) - - gradients_low_df = pd.DataFrame(gradients_low, columns=['gradients_low']) - gradients_avg5_df = pd.DataFrame(gradients_avg5, columns=['gradients_avg5']) - gradients_avg20_df = pd.DataFrame(gradients_avg20, columns=['gradients_avg20']) - gradients_avg60_df = pd.DataFrame(gradients_avg60, columns=['gradients_avg60']) - - gradients_low_df.index = df_final_time - gradients_avg5_df.index = df_final_time - gradients_avg20_df.index = df_final_time - gradients_avg60_df.index = df_final_time - - data = data.merge(gradients_low_df, left_index=True, right_index=True) - data = data.merge(gradients_avg5_df, left_index=True, right_index=True) - data = data.merge(gradients_avg20_df, left_index=True, right_index=True) - data = data.merge(gradients_avg60_df, left_index=True, right_index=True) - - return data - diff --git a/stock/analysis/AnalyzerSqlite.py b/stock/analysis/AnalyzerSqlite.py index 935678a..792c8a7 100644 --- a/stock/analysis/AnalyzerSqlite.py +++ b/stock/analysis/AnalyzerSqlite.py @@ -13,7 +13,7 @@ rc('font', family='AppleGothic') plt.rcParams['axes.unicode_minus'] = False import plotly.graph_objs as go -from plotly import tools, subplots +from plotly import subplots import plotly.io as po from stock.analysis.Common import Common @@ -1027,7 +1027,8 @@ if __name__ == "__main__": start = time.time() PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__)))))) - stockFileName = PROJECT_HOME + '/resources/stock.db' + RESOURCE_PATH = os.path.join(PROJECT_HOME, 'resources') + stockFileName = os.path.join(RESOURCE_PATH, 'stock.db') analyzer = AnalyzerSqlite(stockFileName) #analyzer.analyzeDaily() diff --git a/stock/analysis/DailyStatus.py b/stock/analysis/DailyStatus.py new file mode 100644 index 0000000..bbb43aa --- /dev/null +++ b/stock/analysis/DailyStatus.py @@ -0,0 +1,703 @@ +import os.path +import pandas as pd +import platform +if platform.system().lower().find("window") >= 0 and platform.architecture()[0] != "64bit" : + import win32com.client + +import sqlite3 +import shutil +from math import nan +import plotly.graph_objects as go +from plotly import subplots +import plotly.io as po +from datetime import datetime +from sklearn.linear_model import LinearRegression +from sklearn.preprocessing import StandardScaler, MinMaxScaler + +from hts.HTS import HTS +from hts.BuySellChecker import BuySellChecker +from stock.analysis.AnalyzerSqlite import AnalyzerSqlite + +class DailyStatus (HTS): + tableName = None + dbFileName = None + RESOURCE_PATH = None + analyzerSqlite = None + + def __init__(self, RESOURCE_PATH): + super().__init__(RESOURCE_PATH) + + self.RESOURCE_PATH = RESOURCE_PATH + self.tableName = 'stock' + self.dbFileName = "stock.db" + + self.analyzerSqlite = AnalyzerSqlite(os.path.join(self.RESOURCE_PATH, self.dbFileName)) + self.buySellChecker = BuySellChecker() + + return + + def getDBData(self, stock_code, day, result): + conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) + cursor = conn.cursor() + + cursor.execute('SELECT ymd, close, open, high, low, envelope_upper, envelope_lower, envelope_middle, rsi, rsis, macd, macds, stochastic_slow_k, stochastic_slow_d FROM ' + self.tableName + ' WHERE CODE=? and ymd=? order by ymd', (stock_code, day,)) + db_result = cursor.fetchall() + for rows in db_result: + ymd = rows[0] + close = rows[1] + open = rows[2] + high = rows[3] + low = rows[4] + envelope_upper = rows[5] + envelope_lower = rows[6] + envelope_middle = rows[7] + rsi = 0 if rows[8] is None else rows[8] + rsis = 0 if rows[9] is None else rows[9] + macd = rows[10] + macds = rows[11] + stochastic_slow_k = 0 if rows[12] is None else rows[12] + stochastic_slow_d = 0 if rows[13] is None else rows[13] + + result["ymd"].append(ymd) + result["open"].append(int(open)) + result["close"].append(int(close)) + result["high"].append(int(high)) + result["low"].append(int(low)) + result["envelope_upper"].append(int(envelope_upper)) + result["envelope_lower"].append(int(envelope_lower)) + result["envelope_middle"].append(int(envelope_middle)) + result["rsi"].append(int(rsi)) + result["rsis"].append(int(rsis)) + result["macd"].append(int(macd)) + result["macds"].append(int(macds)) + result["slow_k"].append(int(stochastic_slow_k)) + result["slow_d"].append(int(stochastic_slow_d)) + + return + + def isValidYMD(self, stock_code, day): + conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) + cursor = conn.cursor() + + cursor.execute('SELECT ymd, count(*) as cnt FROM ' + self.tableName + ' WHERE CODE=? and ymd=?', (stock_code, day,)) + db_result = cursor.fetchone() + if db_result[1] > 0: + return True + return False + + def getLastData(self, stock_code, limit=350): + stockTableName = 'stock' + + conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) + cursor = conn.cursor() + + stock = {"CODE": stock_code, "NAME": "", "PRICE": []} + + sql = 'SELECT ymd, close, diff, open, high, low, volume FROM ' + stockTableName + ' where CODE=? order by ymd desc ' + sql += ' limit ' + str(limit) + cursor.execute(sql, (stock['CODE'],)) + items = cursor.fetchall() + + items_reverse = reversed(items) + for item in items_reverse: + stock['PRICE'].append( + { + "ymd": item[0], + "close": item[1], + "diff": item[2], + "open": item[3], + "high": item[4], + "low": item[5], + "volume": item[6], + "avg3": -1, + "avg4": -1, + "avg5": -1, + "avg6": -1, + "avg10": -1, + "avg12": -1, + "avg20": -1, + "avg36": -1, + "avg40": -1, + "avg48": -1, + "avg60": -1, + "avg120": -1, + "avg200": -1, + "avg240": -1, + "avg300": -1, + "disparity_avg5": -1, + "disparity_avg10": -1, + "disparity_avg20": -1, + "disparity_avg60": -1, + "disparity_avg120": -1, + "bolingerband_upper": -1, + "bolingerband_lower": -1, + "bolingerband_middle": -1, + "envelope_upper": -1, + "envelope_lower": -1, + "envelope_middle": -1, + "ichimokucloud_changeLine": -1, + "ichimokucloud_baseLine": -1, + "ichimokucloud_leadingSpan1": -1, + "ichimokucloud_leadingSpan2": -1, + "stochastic_fast_k": -1, + "stochastic_slow_k": -1, + "stochastic_slow_d": -1, + "rsi": -1, + "rsis": -1, + "macd": -1, + "macds": -1, + "macdo": -1, + } + ) + + conn.commit() + cursor.close() + conn.close() + + return stock + + def analyze (self, stock, days=120): + stock["PRICE"] = sorted(stock["PRICE"], key=lambda x: x['ymd']) + self.analyzerSqlite.get_moving_average(stock["PRICE"]) + + # 이동 평균을 이용한 이격도 계산 + self.analyzerSqlite.get_disparity(stock["PRICE"]) + + self.analyzerSqlite.ichimokuCloud.analyze(stock) + self.analyzerSqlite.stochastic.analyze(stock) + self.analyzerSqlite.bolingerBand.analyze(stock) + self.analyzerSqlite.envelope.analyze(stock) + self.analyzerSqlite.rsi.analyze(stock) + self.analyzerSqlite.macd.analyze(stock) + + result = { + "ymd": [], + "open": [], + "close": [], + "high": [], + "low": [], + "avg3": [], + "avg4": [], + "avg5": [], + "avg6": [], + "avg10": [], + "avg12": [], + "avg20": [], + "avg36": [], + "avg40": [], + "avg48": [], + "avg60": [], + "avg120": [], + "avg200": [], + "avg240": [], + "avg300": [], + "disparity_avg5": [], + "disparity_avg20": [], + "disparity_avg60": [], + "disparity_avg120": [], + "disparity": [], + "disparity_type": [], + "envelope_upper": [], + "envelope_lower": [], + "envelope_middle": [], + "rsi": [], + "rsis": [], + "macd": [], + "macds": [], + "slow_k": [], + "slow_d": [], + "buy": [], + "sell": [], + } + for item in stock['PRICE']: + result["ymd"].append(item['ymd']) + result["open"].append(item['open']) + result["close"].append(item['close']) + result["high"].append(item['high']) + result["low"].append(item['low']) + result["avg3"].append(item['avg3']) + result["avg4"].append(item['avg4']) + result["avg5"].append(item['avg5']) + result["avg6"].append(item['avg6']) + result["avg10"].append(item['avg10']) + result["avg12"].append(item['avg12']) + result["avg20"].append(item['avg20']) + result["avg36"].append(item['avg36']) + result["avg40"].append(item['avg40']) + result["avg48"].append(item['avg48']) + result["avg60"].append(item['avg60']) + result["avg120"].append(item['avg120']) + result["avg200"].append(item['avg200']) + result["avg240"].append(item['avg240']) + result["avg300"].append(item['avg300']) + result["disparity_avg5"].append(item['disparity_avg5']) + result["disparity_avg20"].append(item['disparity_avg20']) + result["disparity_avg60"].append(item['disparity_avg60']) + result["disparity_avg120"].append(item['disparity_avg120']) + result['disparity'].append(max(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60']) - min(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60'])) + if item['disparity_avg60'] < item['disparity_avg20'] < item['disparity_avg5']: + result['disparity_type'].append(1) + elif item['disparity_avg5'] < item['disparity_avg20'] < item['disparity_avg60']: + result['disparity_type'].append(-1) + else: + result['disparity_type'].append(0) + result["envelope_upper"].append(item['envelope_upper']) + result["envelope_lower"].append(item['envelope_lower']) + result["envelope_middle"].append(item['envelope_middle']) + result["rsi"].append(item['rsi']) + result["rsis"].append(item['rsis']) + result["macd"].append(item['macd']) + result["macds"].append(item['macds']) + result["slow_k"].append(item['stochastic_slow_k']) + result["slow_d"].append(item['stochastic_slow_d']) + result["buy"].append(-1) + result["sell"].append(-1) + + data = pd.DataFrame(result) + df_final_time = pd.DatetimeIndex(result['ymd']) + data.index = df_final_time + + data = data.astype( + { + 'open': 'int', + 'high': 'int', + 'low': 'int', + 'close': 'int', + 'avg3': 'float', + 'avg4': 'float', + 'avg5': 'float', + 'avg6': 'float', + 'avg10': 'float', + 'avg12': 'float', + 'avg20': 'float', + 'avg36': 'float', + 'avg40': 'float', + 'avg48': 'float', + 'avg60': 'float', + 'avg120': 'float', + 'avg200': 'float', + 'avg240': 'float', + 'avg300': 'float', + 'disparity_avg5': 'float', + 'disparity_avg20': 'float', + 'disparity_avg60': 'float', + 'disparity_avg120': 'float', + 'buy': 'int', + 'sell': 'int', + 'slow_k': 'float', + 'slow_d': 'float', + 'macd': 'float', + 'macds': 'float', + 'envelope_upper': 'float', + 'envelope_lower': 'float', + 'envelope_middle': 'float', + 'rsi': 'float', + 'rsis': 'float' + } + ) + + scaler = StandardScaler() + low_df = pd.DataFrame(data['low']) + low_df.index = [c for c in range(len(low_df))] + low_std = scaler.fit_transform(data['low'].values.reshape(-1, 1)) + low_std = pd.DataFrame(low_std, columns=['low_std']) + + min_df = pd.DataFrame({'open': data['open'].to_list(), 'close': data['close'].to_list()}) + min_df['min_std'] = min_df.min(axis=1) + min_df.index = [c for c in range(len(min_df))] + min_std = scaler.fit_transform(min_df['min_std'].values.reshape(-1, 1)) + min_std = pd.DataFrame(min_std, columns=['min_std']) + + line_fitter = LinearRegression() + size = len(data["close"]) + gradients_low = [] + gradients_avg5 = [] + gradients_avg20 = [] + gradients_avg60 = [] + + for i in range(size): + coef_low = -999 + coef_avg5 = -999 + coef_avg20 = -999 + coef_avg60 = -999 + + if i > 0: + l = days if i >= days else i + x = pd.DataFrame([c for c in range(i - l, i + 1)]) + y = pd.DataFrame(low_std.values.tolist()[i - l:i + 1]) + line_fitter.fit(x.values.reshape(-1, 1), y) + coef_low = line_fitter.coef_[0][0] + + l = 5 if i >= 5 else i + x = pd.DataFrame([c for c in range(i - l, i + 1)]) + y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) + line_fitter.fit(x.values.reshape(-1, 1), y) + coef_avg5 = line_fitter.coef_[0][0] + + l = 20 if i >= 20 else i + x = pd.DataFrame([c for c in range(i - l, i + 1)]) + y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) + line_fitter.fit(x.values.reshape(-1, 1), y) + coef_avg20 = line_fitter.coef_[0][0] + + l = 60 if i >= 60 else i + x = pd.DataFrame([c for c in range(i - l, i + 1)]) + y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) + line_fitter.fit(x.values.reshape(-1, 1), y) + coef_avg60 = line_fitter.coef_[0][0] + + gradients_low.append(coef_low) + gradients_avg5.append(coef_avg5) + gradients_avg20.append(coef_avg20) + gradients_avg60.append(coef_avg60) + + gradients_low_df = pd.DataFrame(gradients_low, columns=['gradients_low']) + gradients_avg5_df = pd.DataFrame(gradients_avg5, columns=['gradients_avg5']) + gradients_avg20_df = pd.DataFrame(gradients_avg20, columns=['gradients_avg20']) + gradients_avg60_df = pd.DataFrame(gradients_avg60, columns=['gradients_avg60']) + + gradients_low_df.index = df_final_time + gradients_avg5_df.index = df_final_time + gradients_avg20_df.index = df_final_time + gradients_avg60_df.index = df_final_time + + data = data.merge(gradients_low_df, left_index=True, right_index=True) + data = data.merge(gradients_avg5_df, left_index=True, right_index=True) + data = data.merge(gradients_avg20_df, left_index=True, right_index=True) + data = data.merge(gradients_avg60_df, left_index=True, right_index=True) + + return data + + + def draw(self, stock_code, given_day, data, bsLine): + if bsLine is None: + return + + # 어제 데이터는 지운다. + buy_line = bsLine['buy'] + buy_weight_line = bsLine['buy_weight'] + sell_line = bsLine['sell'] + + buy_size = [] + buy_colors = [] + for i in range(len(buy_line)): + if buy_line[i] < 0: + buy_colors.append("#ffffff") + buy_line[i] = nan + buy_size.append(0) + else: + buy_colors.append("#B2028C") + buy_size.append(10 + (0.1 * buy_weight_line[i])) + + sell_colors = [] + for i in range(len(sell_line)): + if sell_line[i] < 0: + sell_colors.append("#ffffff") + sell_line[i] = nan + else: + sell_colors.append("#00ced1") + + # 그래프를 설정한다. + buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) + sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) + envelope_upper = go.Scatter(x=data['ymd'], y=data["envelope_upper"], name="upper", line_color='#000000') + envelope_middle = go.Scatter(x=data['ymd'], y=data["envelope_middle"], name="upper", line_color='#927786') + envelope_lower = go.Scatter(x=data['ymd'], y=data["envelope_lower"], name="lower", line_color='#000000') + + avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') + avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') + avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') + candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) + + macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') + macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') + + # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') + slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') + slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') + + rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') + rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') + + disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') + disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') + disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') + + candle_data = [candle_stick, avg5, avg20, avg60, envelope_upper, envelope_middle, envelope_lower, buy_check, sell_check] + disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] + macd_data = [macd_line, macd_s_line] + stochastic_data = [slow_k_line, slow_d_line] + rsi_data = [rsi_line, rsis_line] + + # 그래프를 그린다. + """ + fig = go.Figure(data=candle_data) + fig.update_layout(title=stock_code + "_" + given_day) + fig.show() + """ + + fig = subplots.make_subplots( + rows=5, cols=1, + subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), + #specs=[[{}], [{}], [{}], [{}], [{}], [{}]], + shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, + row_heights=[200, 200, 200, 200, 750] + ) + for trace in macd_data: + fig.append_trace(trace, 1, 1) + for trace in rsi_data: + fig.append_trace(trace, 2, 1) + for trace in stochastic_data: + fig.append_trace(trace, 3, 1) + for trace in disparity_data: + fig.append_trace(trace, 4, 1) + for trace in candle_data: + fig.append_trace(trace, 5, 1) + + + #fig.update_xaxes(nticks=5) + #fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False) + + df = pd.DataFrame(bsLine) + df = df.fillna(-1) + buy_count = len(df.loc[df["buy"] > 0]) + sell_count = len(df.loc[df["sell"] > 0]) + + fig.update_layout(height=1700, title=stock_code + "_" + given_day + "_" + str(buy_count)+","+str(sell_count)) + #fig.update_layout(title=stock_code + "_" + given_day + "_" + str(buy_count) + "," + str(sell_count)) + fig.show() + + return + + def writeFile(self, dailyDirName, stock_code, stock_name, given_day, data, bsLine): + if bsLine is None: + return + + # 어제 데이터는 지운다. + buy_line = bsLine['buy'] + buy_weight_line = bsLine['buy_weight'] + sell_line = bsLine['sell'] + + buy_size = [] + buy_colors = [] + for i in range(len(buy_line)): + if buy_line[i] < 0: + buy_colors.append("#ffffff") + buy_line[i] = nan + buy_size.append(0) + else: + buy_colors.append("#B2028C") + buy_size.append(10 + (0.1 * buy_weight_line[i])) + + sell_colors = [] + for i in range(len(sell_line)): + if sell_line[i] < 0: + sell_colors.append("#ffffff") + sell_line[i] = nan + else: + sell_colors.append("#00ced1") + + # 그래프를 설정한다. + buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) + sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) + envelope_upper = go.Scatter(x=data['ymd'], y=data["envelope_upper"], name="upper", line_color='#000000') + envelope_middle = go.Scatter(x=data['ymd'], y=data["envelope_middle"], name="upper", line_color='#927786') + envelope_lower = go.Scatter(x=data['ymd'], y=data["envelope_lower"], name="lower", line_color='#000000') + + avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') + avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') + avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') + candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) + + macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') + macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') + + # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') + slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') + slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') + + rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') + rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') + + disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') + disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') + disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') + + candle_data = [candle_stick, avg5, avg20, avg60, envelope_upper, envelope_middle, envelope_lower, buy_check, sell_check] + disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] + macd_data = [macd_line, macd_s_line] + stochastic_data = [slow_k_line, slow_d_line] + rsi_data = [rsi_line, rsis_line] + + # 그래프를 그린다. + """ + fig = go.Figure(data=candle_data) + fig.update_layout(title=stock_code + "_" + given_day) + fig.show() + """ + + fig = subplots.make_subplots( + rows=5, cols=1, + subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), + #specs=[[{}], [{}], [{}], [{}], [{}], [{}]], + shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, + row_heights=[200, 200, 200, 200, 750] + ) + for trace in macd_data: + fig.append_trace(trace, 1, 1) + for trace in rsi_data: + fig.append_trace(trace, 2, 1) + for trace in stochastic_data: + fig.append_trace(trace, 3, 1) + for trace in disparity_data: + fig.append_trace(trace, 4, 1) + for trace in candle_data: + fig.append_trace(trace, 5, 1) + + df = pd.DataFrame(bsLine) + df = df.fillna(-1) + buy_count = len(df.loc[df["buy"] > 0]) + sell_count = len(df.loc[df["sell"] > 0]) + + fig.update_layout(height=1700, title=stock_code + "_" + given_day + "_" + str(buy_count)+","+str(sell_count)) + title = "%s (%s) 차트 (URL1, URL2)" % (stock_name, stock_code, stock_code, stock_code) + fig['layout'].update(title=title) + + fileName = "%s/%s_%s.html" % (dailyDirName, stock_code, stock_name.replace(" ", "")) + po.write_html(fig, file=fileName, auto_open=False) + + return + + def getData(self, today, stock): + close = stock['PRICE'][len(stock['PRICE']) - 1]["close"] + open = stock['PRICE'][len(stock['PRICE']) - 1]["open"] + high = stock['PRICE'][len(stock['PRICE']) - 1]["high"] + low = stock['PRICE'][len(stock['PRICE']) - 1]["low"] + volume = stock['PRICE'][len(stock['PRICE']) - 1]["volume"] + + stock['PRICE'].append( + { + "ymd": today, + "close": close, + "diff": stock['PRICE'][len(stock['PRICE']) - 1]["close"] - close, + "open": open, + "high": high, + "low": low, + "volume": volume, + "avg3": -1, + "avg4": -1, + "avg5": -1, + "avg6": -1, + "avg10": -1, + "avg12": -1, + "avg20": -1, + "avg36": -1, + "avg40": -1, + "avg48": -1, + "avg60": -1, + "avg120": -1, + "avg200": -1, + "avg240": -1, + "avg300": -1, + "disparity_avg5": -1, + "disparity_avg10": -1, + "disparity_avg20": -1, + "disparity_avg60": -1, + "disparity_avg120": -1, + "bolingerband_upper": -1, + "bolingerband_lower": -1, + "bolingerband_middle": -1, + "envelope_upper": -1, + "envelope_lower": -1, + "envelope_middle": -1, + "ichimokucloud_changeLine": -1, + "ichimokucloud_baseLine": -1, + "ichimokucloud_leadingSpan1": -1, + "ichimokucloud_leadingSpan2": -1, + "stochastic_fast_k": -1, + "stochastic_slow_k": -1, + "stochastic_slow_d": -1, + "rsi": -1, + "rsis": -1, + "macd": -1, + "macds": -1, + "macdo": -1, + } + ) + + return + + def checkEnvelope(self, stock_codes:list=None, isRealTime=False): + if not isRealTime: + n = 200 + else: + n = 200 + + if stock_codes is not None: + for stock_code in stock_codes: + stock = self.getLastData(stock_code, n) + + today = datetime.today().strftime('%Y%m%d') + self.getData(today, stock) + analyzed_day = 60 + data = self.analyze(stock, analyzed_day) + # 분석일 데이터만 활용한다 (이전 데이터는 제거) + data.drop(data.index[:analyzed_day], inplace=True) + + # print logs + for i in range(len(data.index)): + print (i, data.index[i], data['macd'][i], data['slow_k'][i], data['gradients_low'][i], data['gradients_avg5'][i], data['gradients_avg20'][i], data['gradients_avg60'][i], data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity'][i], data['disparity_type'][i]) + + bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, isRealTime=False) + + # 그래프를 그린다. + self.draw(stock_code, today, data, bsLine) + else: + stockTableName = 'stock' + conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName)) + cursor = conn.cursor() + cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code') + items = cursor.fetchall() + cursor.close() + conn.close() + + today = datetime.today().strftime('%Y%m%d') + dailyDirName = os.path.join(self.RESOURCE_PATH, 'analysis', today, 'daily') + if os.path.exists(dailyDirName): + shutil.rmtree(dailyDirName) + + dailyDirName = os.path.join(self.RESOURCE_PATH, 'analysis', today) + if not os.path.isdir(dailyDirName): + os.mkdir(dailyDirName) + dailyDirName = os.path.join(dailyDirName, 'daily') + if not os.path.isdir(dailyDirName): + os.mkdir(dailyDirName) + + for idx, item in enumerate(items): + stock_code = item[0] + stock_name = item[1] + print(idx, stock_code, stock_name) + print("Analysis # :", idx, ", CODE: ", stock_code, ", NAME: ", stock_name) + + stock = self.getLastData(stock_code, n) + + today = datetime.today().strftime('%Y%m%d') + self.getData(today, stock) + analyzed_day = 60 + data = self.analyze(stock, analyzed_day) + # 분석일 데이터만 활용한다 (이전 데이터는 제거) + data.drop(data.index[:analyzed_day], inplace=True) + + # print logs + # for i in range(len(data.index)): + # print (i, data.index[i], data['macd'][i], data['slow_k'][i], data['gradients_low'][i], data['gradients_avg5'][i], data['gradients_avg20'][i], data['gradients_avg60'][i], data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity'][i], data['disparity_type'][i]) + + bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, isRealTime=False) + + # 그래프를 그린다. + + if len(data.index) > 10 and max(bsLine['buy'][len(bsLine['buy'])-2:]) > 0: + self.writeFile(dailyDirName, stock_code, stock_name, today, data, bsLine) + + return +