import os import time import shutil import matplotlib.pyplot as plt import datetime import sqlite3 import math from math import nan from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta from matplotlib import rc import pandas as pd import numpy as np from stock.analysis.JSDPattern_simulation import JSDPattern_simulation from hts.BuySell_Daily import BuySell_Daily rc('font', family='AppleGothic') plt.rcParams['axes.unicode_minus'] = False import plotly.graph_objs as go from plotly import subplots import plotly.io as po from stock.analysis.Common import Common from stock.util.TelegramBot import TelegramBot class AnalyzerSqlite: jSDPattern = None buySell_Daily = None topCompany = None fnguide = None bot = None common = None stockFileName = None analyzedFileName = None moving_avg = None def __init__(self, RESOURCE_PATH): self.common = Common() self.stockFileName = os.path.join(RESOURCE_PATH, 'stock.db') self.jSDPattern = JSDPattern_simulation(self.stockFileName) self.buySell_Daily = BuySell_Daily() self.stockFileName = self.stockFileName self.topCompany = self.getTopCompany(self.stockFileName, 2000) self.fnguide = self.readFnguide(self.stockFileName) self.bot = TelegramBot() return def getTopCompany(self, fnguideFileName, top): conn = sqlite3.connect(fnguideFileName) cursor = conn.cursor() sql = "select DISTINCT CODE, NAME from fnguide order by total_ownership_interest desc limit " + str(top) cursor.execute(sql) result = cursor.fetchall() top_company = {} for idx, item in enumerate(result): top_company[item[0]] = (idx+1, item[1]) cursor.close() conn.close() return top_company def readFnguide(self, fnguideFileName): conn = sqlite3.connect(fnguideFileName) cursor = conn.cursor() today = datetime.today() year1 = str(today.year - 1) + ".12.01" year2 = str(today.year - 2) + ".12.01" year3 = str(today.year - 3) + ".12.01" sql = "SELECT CODE, NAME, ymd, business_profits, business_profits_ratio, debt_ratio, ROA, ROE, EPS, BPS, DPS, PER, PBR FROM fnguide " sql += " WHERE (ymd=? or ymd=? or ymd=?) and type=''" sql += " order by code, ymd desc" cursor.execute(sql, (year1,year2,year3)) result = cursor.fetchall() fnguide = {} for item in result: if item[0] not in fnguide: fnguide[item[0]] = [] fnguide[item[0]].append( {'NAME': item[1], 'ymd': item[2], 'business_profits': item[3], 'business_profits_ratio': item[4], 'debt_ratio': item[5], 'ROA': item[6], 'ROE': item[7], 'EPS': item[8], 'BPS': item[9], 'DPS': item[10], 'PER': item[11], 'PBR': item[12]}) cursor.close() conn.close() return fnguide def cz(self, value): if value is None or math.isnan(value): return 0 return value def clear_BSLINE(self, BUY_LIST, sell_type=None): if sell_type is None or sell_type == '': BUY_LIST['avg_buy_price'] = 0 BUY_LIST['buy_count'] = 0 BUY_LIST['buy_list'].clear() else: BUY_LIST['avg_buy_price'] = 0 BUY_LIST['buy_count'] = 0 tmp_sell_type = sell_type.split(',') for i, buy_list in reversed(list(enumerate(BUY_LIST['buy_list']))): for t_sell_type in tmp_sell_type: if buy_list['buy_type'].strip() == t_sell_type.strip(): del BUY_LIST['buy_list'][i] break return def draw(self, stock_code, data, bsLine=None): # 어제 데이터는 지운다. #data = data.loc[pd.DatetimeIndex(data.index).day == int(given_day[6:])] buy_price_line, buy_count_line, buy_type, buy_count_line, sell_price_line, sell_count_line, sell_type = [], [], [], [], [], [], [] buy_sell_size, buy_colors, sell_colors, buy_colors = [], [], [], [] if bsLine is not None: buy_price_line = bsLine['buy_price'] buy_count_line = bsLine['buy_count'] sell_price_line = bsLine['sell_price'] sell_count_line = bsLine['sell_count'] buy_type = bsLine['buy_type'] sell_type = bsLine['sell_type'] for i in range(len(data)): if buy_price_line[i] < 1: buy_colors.append("#ffffff") buy_price_line[i] = nan buy_sell_size.append(0) else: buy_colors.append("#0C752E") buy_sell_size.append(14) for i in range(len(data)): if sell_price_line[i] < 1: sell_colors.append("#ffffff") sell_price_line[i] = nan else: sell_colors.append("#00ced1") volume_colors = [] for i in range(len(data)): if data['open'][i] > data['close'][i]: volume_colors.append("#FF0000") elif data['open'][i] < data['close'][i]: volume_colors.append("#FF0000") else: volume_colors.append("#000000") # 그래프를 설정한다. if bsLine is not None: buy_text_list, sell_text_list = [], [] for i in range(len(data['ymd'])): buy_text_list.append( "{}, {}, {} ({:,.2f})

" "avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}
" "avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}

" "loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}

" "laggingSpan_close_diff: {:.4f} ({:.4f})
" "laggingSpan_changeLine_diff: {:.4f} ({:.4f})
" "laggingSpan_baseLine_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan1_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan2_diff: {:.4f} ({:.4f})
" "laggingSpan_avg60_diff: {:.4f} ({:.4f})
" "laggingSpan_lower10_diff: {:.4f} ({:.4f})
" "laggingSpan_middle10_diff: {:.4f} ({:.4f})
" "laggingSpan_upper10_diff: {:.4f} ({:.4f})
" "laggingSpan_lower20_diff: {:.4f} ({:.4f})
" "laggingSpan_middle20_diff: {:.4f} ({:.4f})
" "laggingSpan_upper20_diff: {:.4f} ({:.4f})
" "baseLine_close_diff: {:.4f} ({:.4f})
" "changeLine_close_diff: {:.4f} ({:.4f})
" "changeLine_baseLine_diff: {:.4f} ({:.4f})
" "leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})
" .format(data['ymd'][i].strftime('%Y-%m-%d %H:%M'), buy_type[i], self.cz(buy_price_line[i]), self.cz(buy_price_line[i])*self.cz(buy_count_line[i]), self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]), self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]), self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]), self.cz(data['laggingSpan_changeLine_diff'][i]), self.cz(data['laggingSpan_changeLine_diff_rate'][i]), self.cz(data['laggingSpan_baseLine_diff'][i]), self.cz(data['laggingSpan_baseLine_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan1_diff'][i]), self.cz(data['laggingSpan_leadingSpan1_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan2_diff'][i]), self.cz(data['laggingSpan_leadingSpan2_diff_rate'][i]), self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]), self.cz(data['laggingSpan_lower10_diff'][i]), self.cz(data['laggingSpan_lower10_diff_rate'][i]), self.cz(data['laggingSpan_middle10_diff'][i]), self.cz(data['laggingSpan_middle10_diff_rate'][i]), self.cz(data['laggingSpan_upper10_diff'][i]), self.cz(data['laggingSpan_upper10_diff_rate'][i]), self.cz(data['laggingSpan_lower20_diff'][i]), self.cz(data['laggingSpan_lower20_diff_rate'][i]), self.cz(data['laggingSpan_middle20_diff'][i]), self.cz(data['laggingSpan_middle20_diff_rate'][i]), self.cz(data['laggingSpan_upper20_diff'][i]), self.cz(data['laggingSpan_upper20_diff_rate'][i]), self.cz(data['baseLine_close_diff'][i]), self.cz(data['baseLine_close_diff_rate'][i]), self.cz(data['changeLine_close_diff'][i]), self.cz(data['changeLine_close_diff_rate'][i]), self.cz(data['changeLine_baseLine_diff'][i]), self.cz(data['changeLine_baseLine_diff_rate'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i]) )) sell_text_list.append( "{}, {}, {} ({:,.2f})

" "avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}
" "avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}

" "loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}

" "laggingSpan_close_diff: {:.4f} ({:.4f})
" "laggingSpan_changeLine_diff: {:.4f} ({:.4f})
" "laggingSpan_baseLine_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan1_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan2_diff: {:.4f} ({:.4f})
" "laggingSpan_avg60_diff: {:.4f} ({:.4f})
" "laggingSpan_lower10_diff: {:.4f} ({:.4f})
" "laggingSpan_middle10_diff: {:.4f} ({:.4f})
" "laggingSpan_upper10_diff: {:.4f} ({:.4f})
" "laggingSpan_lower20_diff: {:.4f} ({:.4f})
" "laggingSpan_middle20_diff: {:.4f} ({:.4f})
" "laggingSpan_upper20_diff: {:.4f} ({:.4f})
" "baseLine_close_diff: {:.4f} ({:.4f})
" "changeLine_close_diff: {:.4f} ({:.4f})
" "changeLine_baseLine_diff: {:.4f} ({:.4f})
" "leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})
" .format( data['ymd'][i].strftime('%Y-%m-%d %H:%M'), sell_type[i], self.cz(sell_price_line[i]), self.cz(sell_price_line[i])*self.cz(sell_count_line[i]), self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]), self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]), self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]), self.cz(data['laggingSpan_changeLine_diff'][i]), self.cz(data['laggingSpan_changeLine_diff_rate'][i]), self.cz(data['laggingSpan_baseLine_diff'][i]), self.cz(data['laggingSpan_baseLine_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan1_diff'][i]), self.cz(data['laggingSpan_leadingSpan1_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan2_diff'][i]), self.cz(data['laggingSpan_leadingSpan2_diff_rate'][i]), self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]), self.cz(data['laggingSpan_lower10_diff'][i]), self.cz(data['laggingSpan_lower10_diff_rate'][i]), self.cz(data['laggingSpan_middle10_diff'][i]), self.cz(data['laggingSpan_middle10_diff_rate'][i]), self.cz(data['laggingSpan_upper10_diff'][i]), self.cz(data['laggingSpan_upper10_diff_rate'][i]), self.cz(data['laggingSpan_lower20_diff'][i]), self.cz(data['laggingSpan_lower20_diff_rate'][i]), self.cz(data['laggingSpan_middle20_diff'][i]), self.cz(data['laggingSpan_middle20_diff_rate'][i]), self.cz(data['laggingSpan_upper20_diff'][i]), self.cz(data['laggingSpan_upper20_diff_rate'][i]), self.cz(data['baseLine_close_diff'][i]), self.cz(data['baseLine_close_diff_rate'][i]), self.cz(data['changeLine_close_diff'][i]), self.cz(data['changeLine_close_diff_rate'][i]), self.cz(data['changeLine_baseLine_diff'][i]), self.cz(data['changeLine_baseLine_diff_rate'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i]) )) buy_check = go.Scatter(x=data['ymd'], y=buy_price_line, mode='markers', name="buy_price", marker=dict(size=buy_sell_size, color=buy_colors, line_width=0), text=buy_text_list, hoverinfo="text") sell_check = go.Scatter(x=data['ymd'], y=sell_price_line, mode='markers', name="sell_price", marker=dict(size=14, color=sell_colors, line_width=0), text=sell_text_list, hoverinfo="text") volume_line = go.Bar(x=data['ymd'], y=data["volume"], marker_color=volume_colors, name='volume') avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#079118') avg10 = go.Scatter(x=data['ymd'], y=data["avg10"], name="avg10", line_color='grey') avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#d755e8') avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#099B92') avg90 = go.Scatter(x=data['ymd'], y=data["avg90"], name="avg90", line_color='#2a9c0c') avg120 = go.Scatter(x=data['ymd'], y=data["avg120"], name="avg120", line_color='#079118') avg240 = go.Scatter(x=data['ymd'], y=data["avg240"], name="avg240", line_color='#e68456') avg360 = go.Scatter(x=data['ymd'], y=data["avg360"], name="avg360", line_color='#e6b55c') avg480 = go.Scatter(x=data['ymd'], y=data["avg480"], name="avg480", line_color='#2a9c0c') avg720 = go.Scatter(x=data['ymd'], y=data["avg720"], name="avg720", line_color='#e75d53') avg1440 = go.Scatter(x=data['ymd'], y=data["avg1440"], name="avg1440", line_color='#2a9c0c') avg2880 = go.Scatter(x=data['ymd'], y=data["avg2880"], name="avg2880", line_color='#46406c') laggingSpan_0_8_limit = [0.8 for i in data['ymd']] laggingSpan_0_2_limit = [0.2 for i in data['ymd']] laggingSpan_0_limit = [0 for i in data['ymd']] laggingSpan__0_2_limit = [-0.2 for i in data['ymd']] laggingSpan__0_8_limit = [-0.8 for i in data['ymd']] laggingSpan_0_8_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_8_limit, line=dict(color='grey', width=1), name='laggingSpan_0_8_limit') laggingSpan_0_2_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_2_limit, line=dict(color='grey', width=1), name='laggingSpan_0_2_limit') laggingSpan_0_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_limit, line=dict(color='grey', width=1), name='laggingSpan_0_limit') laggingSpan__0_2_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan__0_2_limit, line=dict(color='grey', width=1), name='laggingSpan__0_2_limit') laggingSpan__0_8_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan__0_8_limit, line=dict(color='grey', width=1), name='laggingSpan__0_8_limit') laggingSpan_close_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_close_diff"], name="laggingSpan_close_diff", line_color='#079118') laggingSpan_changeLine_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_changeLine_diff"], name="laggingSpan_changeLine_diff", line_color='grey') laggingSpan_baseLine_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_baseLine_diff"], name="laggingSpan_baseLine_diff", line_color='#d755e8') laggingSpan_leadingSpan1_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_leadingSpan1_diff"], name="laggingSpan_leadingSpan1_diff", line_color='#d755e8') laggingSpan_leadingSpan2_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_leadingSpan2_diff"], name="laggingSpan_leadingSpan2_diff", line_color='#d755e8') laggingSpan_avg60_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff"], name="laggingSpan_avg60_diff", line_color='#d755e8') laggingSpan_lower10_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_lower10_diff"], name="laggingSpan_lower10_diff", line_color='#d755e8') laggingSpan_middle10_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_middle10_diff"], name="laggingSpan_middle10_diff", line_color='#d755e8') laggingSpan_upper10_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_upper10_diff"], name="laggingSpan_upper10_diff", line_color='#d755e8') laggingSpan_lower20_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_lower20_diff"], name="laggingSpan_lower20_diff", line_color='#d755e8') laggingSpan_middle20_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_middle20_diff"], name="laggingSpan_middle20_diff", line_color='#d755e8') laggingSpan_upper20_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_upper20_diff"], name="laggingSpan_upper20_diff", line_color='#d755e8') baseLine_close_diff = go.Scatter(x=data['ymd'], y=data["baseLine_close_diff"], name="baseLine_close_diff", line_color='#d755e8') changeLine_close_diff = go.Scatter(x=data['ymd'], y=data["changeLine_close_diff"], name="changeLine_close_diff", line_color='#d755e8') changeLine_baseLine_diff = go.Scatter(x=data['ymd'], y=data["changeLine_baseLine_diff"], name="changeLine_baseLine_diff", line_color='#d755e8') changeLine_leadingSpan1_diff = go.Scatter(x=data['ymd'], y=data["changeLine_leadingSpan1_diff"], name="changeLine_leadingSpan1_diff", line_color='#d755e8') leadingSpan1_leadingSpan2_diff = go.Scatter(x=data['ymd'], y=data["leadingSpan1_leadingSpan2_diff"], name="leadingSpan1_leadingSpan2_diff", line_color='#d755e8') laggingSpan_close_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_close_diff_rate"], name="laggingSpan_close_diff_rate", line_color='#d755e8') laggingSpan_changeLine_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_changeLine_diff_rate"], name="laggingSpan_changeLine_diff_rate", line_color='#d755e8') laggingSpan_baseLine_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_baseLine_diff_rate"], name="laggingSpan_baseLine_diff_rate", line_color='#d755e8') laggingSpan_leadingSpan1_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_leadingSpan1_diff_rate"], name="laggingSpan_leadingSpan1_diff_rate", line_color='#d755e8') laggingSpan_leadingSpan2_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_leadingSpan2_diff_rate"], name="laggingSpan_leadingSpan2_diff_rate", line_color='#d755e8') laggingSpan_avg60_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff_rate"], name="laggingSpan_avg60_diff_rate", line_color='#d755e8') laggingSpan_lower10_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_lower10_diff_rate"], name="laggingSpan_lower10_diff_rate", line_color='#d755e8') laggingSpan_middle10_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_middle10_diff_rate"], name="laggingSpan_middle10_diff_rate", line_color='#d755e8') laggingSpan_upper10_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_upper10_diff_rate"], name="laggingSpan_upper10_diff_rate", line_color='#d755e8') laggingSpan_lower20_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_lower20_diff_rate"], name="laggingSpan_lower20_diff_rate", line_color='#d755e8') laggingSpan_middle20_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_middle20_diff_rate"], name="laggingSpan_middle20_diff_rate", line_color='#d755e8') laggingSpan_upper20_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_upper20_diff_rate"], name="laggingSpan_upper20_diff_rate", line_color='#d755e8') baseLine_close_diff_rate = go.Scatter(x=data['ymd'], y=data["baseLine_close_diff_rate"], name="baseLine_close_diff_rate", line_color='#d755e8') changeLine_close_diff_rate = go.Scatter(x=data['ymd'], y=data["changeLine_close_diff_rate"], name="changeLine_close_diff_rate", line_color='#d755e8') changeLine_baseLine_diff_rate = go.Scatter(x=data['ymd'], y=data["changeLine_baseLine_diff_rate"], name="changeLine_baseLine_diff_rate", line_color='#d755e8') changeLine_leadingSpan1_diff_rate = go.Scatter(x=data['ymd'], y=data["changeLine_leadingSpan1_diff_rate"], name="changeLine_leadingSpan1_diff_rate", line_color='#d755e8') leadingSpan1_leadingSpan2_diff_rate = go.Scatter(x=data['ymd'], y=data["leadingSpan1_leadingSpan2_diff_rate"], name="leadingSpan1_leadingSpan2_diff_rate", line_color='#d755e8') changeLine = go.Scatter(x=data['ymd'], y=data["changeLine"], name="changeLine", line_color='#0196ff') baseLine = go.Scatter(x=data['ymd'], y=data["baseLine"], name="baseLine", line_color='#991515') laggingSpan = go.Scatter(x=data['ymd'], y=data["laggingSpan"], name="laggingSpan", line_color='#12A524') leadingSpan1 = go.Scatter(x=data['ymd'], y=data["leadingSpan1"], name="leadingSpan1", line_color='#008001') leadingSpan2 = go.Scatter(x=data['ymd'], y=data["leadingSpan2"], name="leadingSpan2", line_color='#830fd4') upper_10_Line = go.Scatter(x=data['ymd'], y=data["upper_10"], name="upper_10", line_color='#0196ff') lower_10_Line = go.Scatter(x=data['ymd'], y=data["lower_10"], name="lower_10", line_color='#991515') middle_10_line = go.Scatter(x=data['ymd'], y=data["middle_10"], name="middle_10", line_color='#12A524') upper_20_Line = go.Scatter(x=data['ymd'], y=data["upper_20"], name="upper_20", line_color='#0196ff') lower_20_Line = go.Scatter(x=data['ymd'], y=data["lower_20"], name="lower_20", line_color='#991515') middle_20_line = go.Scatter(x=data['ymd'], y=data["middle_20"], name="middle_20", line_color='#12A524') loc_240_k = go.Scatter(x=data['ymd'], y=data["loc_240_k"], name="loc_240_k", line_color='#0196ff') loc_240_d = go.Scatter(x=data['ymd'], y=data["loc_240_d"], name="loc_240_d", line_color='#991515') loc_240_s = go.Scatter(x=data['ymd'], y=data["loc_240_s"], name="loc_240_s", line_color='#12A524') new_high_9 = go.Scatter(x=data['ymd'], y=data["new_high_9"], name="new_high_9", line_color='#0196ff') new_high_26 = go.Scatter(x=data['ymd'], y=data["new_high_26"], name="new_high_26", line_color='#991515') new_high_33 = go.Scatter(x=data['ymd'], y=data["new_high_33"], name="new_high_33", line_color='#12A524') new_high_52 = go.Scatter(x=data['ymd'], y=data["new_high_52"], name="new_high_52", line_color='#099B92') new_low_9 = go.Scatter(x=data['ymd'], y=data["new_low_9"], name="new_low_9", line_color='#0196ff') new_low_26 = go.Scatter(x=data['ymd'], y=data["new_low_26"], name="new_low_26", line_color='#991515') new_low_33 = go.Scatter(x=data['ymd'], y=data["new_low_33"], name="new_low_33", line_color='#12A524') new_low_52 = go.Scatter(x=data['ymd'], y=data["new_low_52"], name="new_low_52", line_color='#099B92') slowk_up_limit = [80 for i in data['ymd']] slowk_middle_limit = [50 for i in data['ymd']] slowk_down_limit = [20 for i in data['ymd']] slowk_up_limit = go.Scatter(x=data['ymd'], y=slowk_up_limit, line=dict(color='grey', width=1), name='slowk_up_limit') slowk_middle_limit = go.Scatter(x=data['ymd'], y=slowk_middle_limit, line=dict(color='grey', width=1), name='slowk_middle_limit') slowk_down_limit = go.Scatter(x=data['ymd'], y=slowk_down_limit, line=dict(color='grey', width=1), name='slowk_down_limit') slowk_12 = go.Scatter(x=data['ymd'], y=data["slowk_12"], line=dict(color='#079118', width=2), name='slowk_12') slowd_12 = go.Scatter(x=data['ymd'], y=data["slowd_12"], line=dict(dash='dashdot', color='#079118', width=2), name='slowd_12') slowk_26 = go.Scatter(x=data['ymd'], y=data["slowk_26"], line=dict(color='grey', width=2), name='slowk_26') slowd_26 = go.Scatter(x=data['ymd'], y=data["slowd_26"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_26') slowk_52 = go.Scatter(x=data['ymd'], y=data["slowk_52"], line=dict(color='#d755e8', width=2), name='slowk_52') slowd_52 = go.Scatter(x=data['ymd'], y=data["slowd_52"], line=dict(dash='dashdot', color='#d755e8', width=2), name='slowd_52') text_list = [] for i in range(len(data['ymd'])): text_list.append( "{}

" "avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}
" "avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}

" "loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}

" "laggingSpan_close_diff: {:.4f} ({:.4f})
" "laggingSpan_changeLine_diff: {:.4f} ({:.4f})
" "laggingSpan_baseLine_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan1_diff: {:.4f} ({:.4f})
" "laggingSpan_leadingSpan2_diff: {:.4f} ({:.4f})
" "laggingSpan_avg60_diff: {:.4f} ({:.4f})
" "laggingSpan_lower10_diff: {:.4f} ({:.4f})
" "laggingSpan_middle10_diff: {:.4f} ({:.4f})
" "laggingSpan_upper10_diff: {:.4f} ({:.4f})
" "laggingSpan_lower20_diff: {:.4f} ({:.4f})
" "laggingSpan_middle20_diff: {:.4f} ({:.4f})
" "laggingSpan_upper20_diff: {:.4f} ({:.4f})
" "baseLine_close_diff: {:.4f} ({:.4f})
" "changeLine_close_diff: {:.4f} ({:.4f})
" "changeLine_baseLine_diff: {:.4f} ({:.4f})
" "leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})
" .format( data['ymd'][i].strftime('%Y-%m-%d %H:%M'), self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]), self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]), self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]), self.cz(data['laggingSpan_changeLine_diff'][i]), self.cz(data['laggingSpan_changeLine_diff_rate'][i]), self.cz(data['laggingSpan_baseLine_diff'][i]), self.cz(data['laggingSpan_baseLine_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan1_diff'][i]), self.cz(data['laggingSpan_leadingSpan1_diff_rate'][i]), self.cz(data['laggingSpan_leadingSpan2_diff'][i]), self.cz(data['laggingSpan_leadingSpan2_diff_rate'][i]), self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]), self.cz(data['laggingSpan_lower10_diff'][i]), self.cz(data['laggingSpan_lower10_diff_rate'][i]), self.cz(data['laggingSpan_middle10_diff'][i]), self.cz(data['laggingSpan_middle10_diff_rate'][i]), self.cz(data['laggingSpan_upper10_diff'][i]), self.cz(data['laggingSpan_upper10_diff_rate'][i]), self.cz(data['laggingSpan_lower20_diff'][i]), self.cz(data['laggingSpan_lower20_diff_rate'][i]), self.cz(data['laggingSpan_middle20_diff'][i]), self.cz(data['laggingSpan_middle20_diff_rate'][i]), self.cz(data['laggingSpan_upper20_diff'][i]), self.cz(data['laggingSpan_upper20_diff_rate'][i]), self.cz(data['baseLine_close_diff'][i]), self.cz(data['baseLine_close_diff_rate'][i]), self.cz(data['changeLine_close_diff'][i]), self.cz(data['changeLine_close_diff_rate'][i]), self.cz(data['changeLine_baseLine_diff'][i]), self.cz(data['changeLine_baseLine_diff_rate'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i]) )) 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', name='candle', text=text_list, hoverinfo="text" ) if bsLine is not None: candle_data = [avg5, avg10, avg20, avg60, avg90, avg120, avg240, avg360, avg480, avg720, avg1440, avg2880, buy_check, sell_check, candle_stick, changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2, upper_10_Line, lower_10_Line, middle_10_line, upper_20_Line, lower_20_Line, middle_20_line] else: candle_data = [avg5, avg10, avg20, avg60, avg90, avg120, avg240, avg360, avg480, avg720, avg1440, avg2880, candle_stick,changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2] volume_data = [volume_line] disparity_data = [laggingSpan_close_diff, laggingSpan_changeLine_diff, laggingSpan_baseLine_diff, laggingSpan_leadingSpan1_diff, laggingSpan_leadingSpan2_diff, laggingSpan_avg60_diff, laggingSpan_lower10_diff, laggingSpan_middle10_diff, laggingSpan_upper10_diff, laggingSpan_lower20_diff, laggingSpan_middle20_diff, laggingSpan_upper20_diff, baseLine_close_diff, changeLine_close_diff, changeLine_baseLine_diff, changeLine_leadingSpan1_diff, leadingSpan1_leadingSpan2_diff] loc_disparity_data = [laggingSpan_0_8_limit_line, laggingSpan_0_2_limit_line, laggingSpan_0_limit_line, laggingSpan__0_2_limit_line, laggingSpan__0_8_limit_line, laggingSpan_close_diff_rate, laggingSpan_changeLine_diff_rate, laggingSpan_baseLine_diff_rate, laggingSpan_leadingSpan1_diff_rate, laggingSpan_leadingSpan2_diff_rate, laggingSpan_avg60_diff_rate, laggingSpan_lower10_diff_rate, laggingSpan_middle10_diff_rate, laggingSpan_upper10_diff_rate, laggingSpan_lower20_diff_rate, laggingSpan_middle20_diff_rate, laggingSpan_upper20_diff_rate, baseLine_close_diff_rate, changeLine_close_diff_rate, changeLine_baseLine_diff_rate,changeLine_leadingSpan1_diff_rate, leadingSpan1_leadingSpan2_diff_rate, loc_240_k, loc_240_d, loc_240_s, new_high_9 ,new_high_26, new_high_33, new_high_52,new_low_9 ,new_low_26, new_low_33, new_low_52 ] stochastic_data = [ slowk_up_limit, slowk_middle_limit, slowk_down_limit, slowk_12, slowd_12, slowk_26, slowd_26, slowk_52, slowd_52 ] # 그래프를 그린다. """ fig = go.Figure(data=candle_data) fig.update_layout(title=stock_code) fig.show() """ fig = subplots.make_subplots( rows=5, cols=1, subplot_titles=("이격도", "이격도 위치", "캔들", "slowkd", "거래량"), shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, row_heights=[200, 200, 700, 200, 200] ) for trace in disparity_data: fig.append_trace(trace, 1, 1) for trace in loc_disparity_data: fig.append_trace(trace, 2, 1) for trace in candle_data: fig.append_trace(trace, 3, 1) for trace in stochastic_data: fig.append_trace(trace, 4, 1) for trace in volume_data: fig.append_trace(trace, 5, 1) #fig.update_xaxes(nticks=5) #fig.update_layout(height=2400, title=stock_code, xaxis_rangeslider_visible=False) df = pd.DataFrame(bsLine) df = df.fillna(-1) buy_count = 0 if bsLine is not None: buy_count = len(df.loc[df["buy_price"] > 0]) fig.update_layout(height=1400, title="{}, buy: {}번 ".format(stock_code, buy_count), xaxis_rangeslider_visible=False, xaxis2_rangeslider_visible=False, xaxis3_rangeslider_visible=False, xaxis4_rangeslider_visible=False ) # 화면으로 출력함 return fig def getPositionalEnergy(self, close): # 260 (= 52 * 5)일 중 가장 찾은 금액과 가장 높았던 금액 중 현재가의 위치 계산 top = close[0] bottom = close[0] for i in range(1, 260): if i >= len(close): break if top < close[i]: top = close[i] if bottom > close[i]: bottom = close[i] if top-close[0] == 0: energy1 = 100.0 else: energy1 = round((close[0]-bottom) / (top-close[0]), 2) energy2 = round((close[0] / top), 2) return energy1, energy2 def writeSummary(self, param): bull = list(param['bull']) bear = list(param['bear']) even = list(param['even']) ymd = [i for i in range(len(bull))] bull_line = go.Scatter(x=ymd, y=bull, name="bull", line_color='#FF33A2') bear_line = go.Scatter(x=ymd, y=bear, name="bear", line_color='#1469F4') even_line = go.Scatter(x=ymd, y=even, name="even", line_color='#8B4513') line_data = [bull_line, bear_line, even_line] fig = subplots.make_subplots( rows=1, cols=1, subplot_titles=("주식 상황"), shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, row_heights=[800] ) for trace in line_data: fig.append_trace(trace, 1, 1) fig.update_layout(height=810, xaxis_rangeslider_visible=False) sum = param['bull'][0] + param['bear'][0] + param['even'][0] title = "[Summary] bull: %d (%.2f), bear: %d (%.2f), even: %d (%.2f)" % (param['bull'][0], param['bull'][0]/sum, param['bear'][0], param['bear'][0]/sum, param['even'][0], param['even'][0]/sum) fig['layout'].update(title=title) #fileName = "%s/summary.html" % (self.outPath) #po.write_html(fig, file=fileName, auto_open=False) return def writeFile(self, outPath, CODE, NAME, top, stock, bsLine): # 3년 이내 한번이라도 영업이익이 났는지 체크를 함 fnguide = None if CODE in self.fnguide: fnguide = self.fnguide[CODE] check = True if fnguide: check = False for item in fnguide: if item['business_profits'] > 0: check = True if check: fig = self.draw(CODE, stock, bsLine) title = "%s (%s), 차트 (URL1, URL2, URL3)" % (NAME, CODE, CODE, CODE, CODE) fig['layout'].update(title=title) fileName = outPath + "/%s_%s_%s_%s.html" % (datetime.today().strftime("%Y%m%d"), top, NAME.replace(" ", ""), CODE) po.write_html(fig, file=fileName, auto_open=False) return def checkVolume(self, p_volume, volume): if 0 < p_volume <= 10000 and p_volume * 700 < volume: return True if 10000 < p_volume <= 50000 and p_volume * 40 < volume: return True if 50000 < p_volume <= 100000 and p_volume * 25 < volume: return True if 100000 < p_volume <= 200000 and p_volume * 15 < volume: return True if 200000 < p_volume <= 700000 and p_volume * 13 < volume: return True if 700000 < p_volume <= 1000000 and p_volume * 10 < volume: return True if 5000000 < p_volume <= 5000000 and p_volume * 5 < volume: return True if 5000000 < p_volume and p_volume * 4 < volume: return True return False def getStockData(self, CODE): data_daily, ci_daily = self.jSDPattern.getData(CODE, ymd=(datetime.now()+timedelta(days=1)).strftime('%Y%m%d'), get_days=1500) return data_daily, ci_daily def makeDir(self, dir_name): if os.path.isdir(self.outPath + "/" + dir_name): os.rmdir(self.outPath + "/" + dir_name) os.mkdir(self.outPath + "/" + dir_name) return def checkTransaction(self, ticker, data, ci): # 어제 오늘 데이터로 분석 bsLine = {} if data is not None and 'close' in data.columns: size = len(data["close"]) bsLine['buy_ymd'] = [None for i in range(size)] bsLine['buy_price'] = [0 for i in range(size)] bsLine['buy_count'] = [0 for i in range(size)] bsLine['buy_type'] = ['' for i in range(size)] bsLine['buy_cut'] = [None for i in range(size)] bsLine['sell_price'] = [0 for i in range(size)] bsLine['sell_count'] = [0 for i in range(size)] bsLine['sell_type'] = ['' for i in range(size)] bsLine['sell_cut'] = [0 for i in range(size)] size = ci start = 0 for i in range(start, size): # 매도 확인 sell_price, sell_count, sell_type = self.buySell_Daily.getSellPrice(ticker, data, i, bsLine) bsLine['sell_price'][i] = sell_price bsLine['sell_count'][i] = sell_count bsLine['sell_type'][i] = sell_type bsLine['sell_cut'][i] = 0 if sell_price < 1: buy_ymd, buy_price, buy_count, buy_type, buy_cut = self.buySell_Daily.getBuyPrice(ticker, data, i, bsLine) bsLine['buy_ymd'][i] = buy_ymd bsLine['buy_price'][i] = buy_price bsLine['buy_count'][i] = buy_count bsLine['buy_type'][i] = buy_type bsLine['buy_cut'][i] = buy_cut return bsLine # 후보 찾기 def findCandidates(self, outPath): buy_stock_list = [] stockTableName = 'stock' fnguideTableName = 'fnguide' conn = sqlite3.connect(self.stockFileName) cursor = conn.cursor() cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code') #cursor.execute('select CODE, NAME, max(ymd) as ymd from ' + fnguideTableName + ' where type != "E" group by 1 order by total_assets desc') items = cursor.fetchall() cursor.close() conn.close() for idx, item in enumerate(items): CODE = item[0] NAME = item[1] ticker = {'ticker_code': CODE, 'ticker_name': NAME, 'unit': 0, 'MAX_BUY': 10000, 'BUY_INFO': {'buy_list': []}} print("#", idx, ", CODE: ", CODE, ", NAME: ", NAME) stock_daily, ci = self.getStockData(CODE) bsLine = self.checkTransaction(ticker, stock_daily, ci) if bsLine['buy_ymd'][ci-1] is not None: top = "0" if CODE in self.topCompany: top = str(self.topCompany[CODE][0]) # 거래량이 10만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94) if stock_daily['volume'][ci-1] > 100000 and stock_daily['close'][ci-1] > 1000: # 종목 상태 체크 분석 self.writeFile(outPath, CODE, NAME, top, stock_daily, bsLine) buy_stock_list.append({'CODE': CODE, 'NAME': NAME}) buy_stock_str = '' for i, item in enumerate(buy_stock_list): buy_stock_str += str(i + 1) + ". " + item['CODE'] + "(" + item['NAME'] + ")\n" self.bot.sendMsg("{}".format(buy_stock_str)) return 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__)))))) RESOURCE_PATH = os.path.join(PROJECT_HOME, 'resources') analyzerSqlite = AnalyzerSqlite(RESOURCE_PATH) # HTML 출력 outPath = os.path.join(PROJECT_HOME, "resources", "analysis") if not os.path.isdir(outPath): os.mkdir(outPath) day = datetime.today().strftime("%Y%m%d") before_7_day = datetime.today() + relativedelta(days=-7) dayList = os.listdir(outPath) for dayDir in dayList: if dayDir[0] != '.' and dayDir < before_7_day.strftime("%Y%m%d"): if os.path.exists(os.path.join(outPath, dayDir)) and os.path.isdir(os.path.join(outPath, dayDir)): shutil.rmtree(os.path.join(outPath, dayDir)) outPath = os.path.join(outPath, day) if os.path.isdir(outPath): shutil.rmtree(outPath) os.mkdir(outPath) print("print to Html...") analyzerSqlite.findCandidates(outPath) print("time : %6.2f 초" % (time.time() - start)) print("done...")