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_avg60_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_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_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_avg60_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_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_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_avg60_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff"], name="laggingSpan_avg60_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_avg60_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff_rate"], name="laggingSpan_avg60_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_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') 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_avg60_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_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_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_avg60_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_avg60_diff_rate, leadingSpan1_leadingSpan2_diff_rate, loc_240_k, loc_240_d, loc_240_s, new_high_9 ,new_high_26, new_low_9 ,new_low_26] 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...")