import os
import time
import shutil
import matplotlib.pyplot as plt
import datetime
import sqlite3
from datetime import datetime
from matplotlib import rc
import pandas as pd
import copy
rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
import plotly.graph_objs as go
from plotly import tools, subplots
import plotly.io as po
from stockpredictor.analysis.Common import Common
from stockpredictor.analysis.Stochastic import Stochastic
from stockpredictor.analysis.BolingerBand import BolingerBand
from stockpredictor.analysis.IchimokuCloud import IchimokuCloud
from stockpredictor.analysis.RSI import RSI
from stockpredictor.crawler.sQLite.MovingAverage import MovingAverage
class AnalyzerSqlite:
PROJECT_HOME = None
stochastic = None
bolingerBand = None
ichimokuCloud = None
rsi = None
topCompany = None
fnguide = None
common = None
stockFileName = None
analyzedFileName = None
moving_avg = None
def __init__(self, PROJECT_HOME, stockFileName):
self.PROJECT_HOME = PROJECT_HOME
self.stockFileName = stockFileName
self.common = Common()
self.stochastic = Stochastic()
self.bolingerBand = BolingerBand()
self.ichimokuCloud = IchimokuCloud()
self.rsi = RSI()
self.topCompany = self.getTopCompany(stockFileName, 2000)
self.fnguide = self.readFnguide(stockFileName)
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 draw(self, stock):
ymd = list(reversed(stock['ymd']))
open = list(reversed(stock['open']))
close = list(reversed(stock['close']))
high = list(reversed(stock['high']))
low = list(reversed(stock['low']))
volume = list(reversed(stock['volume']))
avg5 = list(reversed(stock['avg5']))
avg20 = list(reversed(stock['avg20']))
avg40 = list(reversed(stock['avg40']))
avg60 = list(reversed(stock['avg60']))
avg120 = list(reversed(stock['avg120']))
avg240 = list(reversed(stock['avg240']))
avg300 = list(reversed(stock['avg300']))
rsi = list(reversed(stock['rsi']))
rsis = list(reversed(stock['rsis']))
stochastic_slow_k = list(reversed(stock['stochastic_slow_k']))
stochastic_slow_d = list(reversed(stock['stochastic_slow_d']))
bolingerband_upper = list(reversed(stock['bolingerband_upper']))
bolingerband_lower = list(reversed(stock['bolingerband_lower']))
ichimokucloud_changeLine = list(reversed(stock['ichimokucloud_changeLine']))
ichimokucloud_baseLine = list(reversed(stock['ichimokucloud_baseLine']))
# general
candle_stick = go.Candlestick(x=ymd, open=open, high=high, low=low, close=close, increasing_line_color='red', decreasing_line_color='blue')
avg5 = go.Scatter(x=ymd, y=avg5, name="avg5", line_color='#000000')
avg20 = go.Scatter(x=ymd, y=avg20, name="avg20", line_color='#f84c43')
avg40 = go.Scatter(x=ymd, y=avg40, name="avg40", line_color='#8013ED')
avg60 = go.Scatter(x=ymd, y=avg60, name="avg60", line_color='#f89543')
avg120 = go.Scatter(x=ymd, y=avg120, name="avg120", line_color='#0ed604')
avg240 = go.Scatter(x=ymd, y=avg240, name="avg240", line_color='#FF00F7')
avg300 = go.Scatter(x=ymd, y=avg300, name="avg300", line_color='#00FF49')
bolinger_upper = go.Scatter(x=ymd, y=bolingerband_upper, name="upper", line_color='#8B4513')
bolinger_lower = go.Scatter(x=ymd, y=bolingerband_lower, name="lower", line_color='#8B4513')
changeLine = go.Scatter(x=ymd, y=ichimokucloud_changeLine, name="changeLine", line_color='#000000')
baseLine = go.Scatter(x=ymd, y=ichimokucloud_baseLine, name="baseLine", line_color='#FF0000')
candle_data = [candle_stick, avg5, avg20, avg40, avg60, avg120, avg240, avg300, bolinger_upper, bolinger_lower, changeLine, baseLine]
#candle_data = [candle_stick, bolinger_upper, bolinger_lower, changeLine, baseLine]
volume = go.Bar(x=ymd, y=volume, name="volume")
volume_data = [volume]
# stochastic
rsi = go.Scatter(x=ymd, y=rsi, name="rsi", line_color='#8B4513')
rsis = go.Scatter(x=ymd, y=rsis, name="rsis", line_color='#4169E1')
rsi_data = [rsi, rsis]
# stochastic
slow_k = go.Scatter(x=ymd, y=stochastic_slow_k, name="Slow%K", line_color='#8B4513')
slow_d = go.Scatter(x=ymd, y=stochastic_slow_d, name="Slow%D", line_color='#4169E1')
stochastic_data = [slow_k, slow_d]
fig = subplots.make_subplots(rows=4, cols=1,
subplot_titles=('차트', '거래량', 'rsi', 'Stochastic'),
row_heights=[1200, 500, 500, 500])
for trace in candle_data:
fig.append_trace(trace, 1, 1)
for trace in volume_data:
fig.append_trace(trace, 2, 1)
for trace in rsi_data:
fig.append_trace(trace, 3, 1)
for trace in stochastic_data:
fig.append_trace(trace, 4, 1)
fig.update_layout(height=2200, xaxis_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 makeDir(self, type):
if os.path.isdir(self.outPath + "/" + type):
os.rmdir(self.outPath + "/" + type)
os.mkdir(self.outPath + "/" + type)
return
def makeDirectory(self, outPath):
self.outPath = outPath
if os.path.isdir(outPath):
shutil.rmtree(outPath)
os.mkdir(outPath)
self.makeDir("weekly_20주선_40주선_상향돌파")
self.makeDir("weekly_종가_20주선_상향돌파")
self.makeDir("weekly_rsi_32이하")
self.makeDir("weekly_rsi_rsis_위로_올라옴")
self.makeDir("monthly_20월선_40월선_상향돌파")
self.makeDir("monthly_종가_20주선_상향돌파")
self.makeDir("monthly_rsi_32이하")
self.makeDir("monthly_rsi_rsis_위로_올라옴")
return
def writeFile(self, type, CODE, NAME, top, stock, state):
# 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(stock)
title = "%s (%s), %d %s 차트 (URL1, URL2)" % (NAME, CODE, stock['close'][0], state, CODE, CODE)
fig['layout'].update(title=title)
fileName = self.outPath + "/" + str(type)
fileName = "%s/%s_%s_%s_%s.html" % (fileName, top, NAME.replace(" ", ""), CODE, state)
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, TableName, CODE):
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
sql = 'SELECT ymd, close, open, high, low, volume, '
sql += ' avg5, avg10, avg20, avg40, avg60, avg120, avg200, avg240, avg300, '
sql += ' bolingerband_upper, bolingerband_lower, bolingerband_middle, '
sql += ' ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, '
sql += ' stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, '
sql += ' rsi, rsis '
sql += ' FROM ' + TableName + ' where CODE=? order by ymd desc limit 512'
cursor.execute(sql, (CODE,))
prices = cursor.fetchall()
cursor.close()
conn.close()
ymd = []
close, open, high, low, volume = [], [], [], [], []
avg5, avg10, avg20, avg40, avg60, avg120, avg200, avg240, avg300 = [], [], [], [], [], [], [], [], []
bolingerband_upper, bolingerband_lower, bolingerband_middle = [], [], []
ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2 = [], [], [], []
stochastic_fast_k, stochastic_slow_k, stochastic_slow_d = [], [], []
rsi, rsis = [], []
for price in prices:
ymd.append(price[0])
close.append(price[1])
open.append(price[2])
high.append(price[3])
low.append(price[4])
volume.append(price[5])
avg5.append(price[6])
avg10.append(price[7])
avg20.append(price[8])
avg40.append(price[9])
avg60.append(price[10])
avg120.append(price[11])
avg200.append(price[12])
avg240.append(price[13])
avg300.append(price[14])
bolingerband_upper.append(price[15])
bolingerband_lower.append(price[16])
bolingerband_middle.append(price[17])
ichimokucloud_changeLine.append(price[18])
ichimokucloud_baseLine.append(price[19])
ichimokucloud_leadingSpan1.append(price[20])
ichimokucloud_leadingSpan2.append(price[21])
stochastic_fast_k.append(price[22])
stochastic_slow_k.append(price[23])
stochastic_slow_d.append(price[24])
rsi.append(price[25])
rsis.append(price[26])
stock = {
"ymd": ymd,
"close": close, "open": open, "high": high, "low": low, "volume": volume,
"avg5": avg5, "avg10": avg10, "avg20": avg20, "avg40": avg40, "avg60": avg60, "avg120": avg120, "avg200": avg200, "avg300": avg300,
"avg240": avg240,
"bolingerband_upper": bolingerband_upper, "bolingerband_lower": bolingerband_lower,
"bolingerband_middle": bolingerband_middle,
"ichimokucloud_changeLine": ichimokucloud_changeLine, "ichimokucloud_baseLine": ichimokucloud_baseLine,
"ichimokucloud_leadingSpan1": ichimokucloud_leadingSpan1,
"ichimokucloud_leadingSpan2": ichimokucloud_leadingSpan2,
"stochastic_fast_k": stochastic_fast_k, "stochastic_slow_k": stochastic_slow_k, "stochastic_slow_d": stochastic_slow_d,
"rsi": rsi, "rsis": rsis
}
return stock
# 후보 찾기
def findCandidate(self, outPath):
self.makeDirectory(outPath)
stockTableName = 'stock'
stockAnalysisTableName = 'stock_analysis'
stockAnalysisWeeklyTableName = 'stock_analysis_weekly'
stockAnalysisMonthlyTableName = 'stock_analysis_monthly'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
items = cursor.fetchall()
cursor.close()
conn.close()
for idx, item in enumerate(items):
CODE = item[0]
NAME = item[1]
print (idx, CODE, NAME)
print("Analysis # :", idx, ", CODE: ", CODE, ", NAME: ", NAME)
top = "0"
if CODE in self.topCompany:
top = str(self.topCompany[CODE][0])
#stock_daily = self.getStockData(stockAnalysisTableName, CODE)
stock_weekly = self.getStockData(stockAnalysisWeeklyTableName, CODE)
stock_monthly = self.getStockData(stockAnalysisMonthlyTableName, CODE)
# 거래량이 100만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94)
if stock_weekly['volume'][0] > 100000 and stock_weekly['close'][0] > 1000:
# 종목 상태 체크 분석
status = ""
# [Weekly]
# 정배열 체크
temp_status = self.common.check_RightArrange(stock_weekly)
if temp_status != "":
status += temp_status
# 20주선이 40주 선을 상향 돌파함
if len(stock_weekly['close']) > 40:
if (stock_weekly['avg20'][1] is not None and stock_weekly['avg40'][1] is not None and
stock_weekly['avg20'][0] is not None and stock_weekly['avg40'][0] is not None):
if stock_weekly['avg20'][1] <= stock_weekly['avg40'][1] and stock_weekly['avg20'][0] > stock_weekly['avg40'][0]:
type = "weekly_20주선_40주선_상향돌파"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# 종가가 20주선을 상향 돌파함
if len(stock_weekly['close']) > 2:
if stock_weekly['close'][1] is not None and stock_weekly['avg20'][1] is not None and stock_weekly['close'][0] is not None and stock_weekly['avg20'][0] is not None:
if stock_weekly['close'][1] <= stock_weekly['avg20'][1] and stock_weekly['close'][0] > stock_weekly['avg20'][0]:
type = "weekly_종가_20주선_상향돌파"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# RSI가 32 이하인 경우 (30이 이하로 떨어지는 것 미리 확인)
if len(stock_monthly['close']) > 1:
if stock_weekly['rsi'][0] is not None:
if stock_weekly['rsi'][0] <= 32:
type = "weekly_rsi_32이하"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# rsi가 40 이하이고, rsis 아래에서 위로 올라올 때
if len(stock_weekly['close']) > 60:
if stock_weekly['rsi'][0] is not None and stock_weekly['rsis'][0] is not None and stock_weekly['rsi'][1] is not None and stock_weekly['rsis'][1] is not None:
if stock_weekly['rsi'][0] < 40:
if stock_weekly['rsi'][0] > stock_weekly['rsis'][0] and stock_weekly['rsi'][1] <= stock_weekly['rsis'][1]:
type = "weekly_rsi_rsis_위로_올라옴"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# [Monthly]
# 20주선이 40주 선을 상향 돌파함
if len(stock_monthly['close']) > 40:
if (stock_monthly['avg20'][1] is not None and stock_monthly['avg40'][1] is not None and
stock_monthly['avg20'][0] is not None and stock_monthly['avg40'][0] is not None):
if stock_monthly['avg20'][1] <= stock_monthly['avg40'][1] and stock_monthly['avg20'][0] > stock_monthly['avg40'][0]:
type = "monthly_20월선_40월선_상향돌파"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# 종가가 20주선을 상향 돌파함
if len(stock_monthly['close']) > 2:
if stock_monthly['close'][1] is not None and stock_monthly['avg20'][1] is not None and stock_monthly['close'][0] is not None and stock_monthly['avg20'][0] is not None:
if stock_monthly['close'][1] <= stock_monthly['avg20'][1] and stock_monthly['close'][0] > stock_monthly['avg20'][0]:
type = "monthly_종가_20주선_상향돌파"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# RSI가 32 이하인 경우 (30이 이하로 떨어지는 것 미리 확인)
if len(stock_monthly['close']) > 1:
if stock_monthly['rsi'][0] is not None:
if stock_monthly['rsi'][0] <= 32:
type = "monthly_rsi_32이하"
self.writeFile(type, CODE, NAME, top, stock_weekly, status)
# rsi가 rsis 아래에서 위로 올라올 때
if len(stock_monthly['close']) > 60:
if stock_monthly['rsi'][0] is not None and stock_monthly['rsis'][0] is not None and stock_monthly['rsi'][1] is not None and stock_monthly['rsis'][1] is not None:
if stock_monthly['rsi'][0] < 40:
if stock_monthly['rsi'][0] > stock_monthly['rsis'][0] and stock_monthly['rsi'][1] <= stock_monthly['rsis'][1]:
type = "monthly_rsi_rsis_위로_올라옴"
self.writeFile(type, CODE, NAME, top, stock_monthly, status)
return
def get_moving_average(self, stock):
q_5 = MovingAverage(5)
q_10 = MovingAverage(10)
q_20 = MovingAverage(20)
q_40 = MovingAverage(40)
q_60 = MovingAverage(60)
q_120 = MovingAverage(120)
q_200 = MovingAverage(200)
q_240 = MovingAverage(240)
q_300 = MovingAverage(300)
for i in range(len(stock)):
q_5.enqueue(stock[i]['close'])
q_10.enqueue(stock[i]['close'])
q_20.enqueue(stock[i]['close'])
q_40.enqueue(stock[i]['close'])
q_60.enqueue(stock[i]['close'])
q_120.enqueue(stock[i]['close'])
q_200.enqueue(stock[i]['close'])
q_240.enqueue(stock[i]['close'])
q_300.enqueue(stock[i]['close'])
stock[i]['avg5'] = q_5.avg()
stock[i]['avg10'] = q_10.avg()
stock[i]['avg20'] = q_20.avg()
stock[i]['avg40'] = q_40.avg()
stock[i]['avg60'] = q_60.avg()
stock[i]['avg120'] = q_120.avg()
stock[i]['avg200'] = q_200.avg()
stock[i]['avg240'] = q_240.avg()
stock[i]['avg300'] = q_300.avg()
return
def convertFormat(self, weekDict):
previous_close = 0
stock_price = []
for ts in weekDict['open']:
stock_price.append(
{
"ymd": ts.strftime("%Y.%m.%d"),
"close": weekDict['close'][ts],
"diff": weekDict['close'][ts] - previous_close,
"open": weekDict['open'][ts],
"high": weekDict['high'][ts],
"low": weekDict['low'][ts],
"volume": weekDict['volume'][ts],
"avg5": -1,
"avg10": -1,
"avg20": -1,
"avg40": -1,
"avg60": -1,
"avg120": -1,
"avg200": -1,
"avg240": -1,
"avg300": -1,
"bolingerband_upper": -1,
"bolingerband_lower": -1,
"bolingerband_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
}
)
previous_close = weekDict['close'][ts]
return stock_price
def analyzeAdditionalInfo(self, stock, cursor, type=None):
if type==None:
stockAnalysisTableName = 'stock_analysis'
else:
stockAnalysisTableName = 'stock_analysis_' + type
# 테이블 생성
cursor.execute("CREATE TABLE IF NOT EXISTS " + stockAnalysisTableName + " (CODE text, NAME text, ymd text, close REAL, diff REAL, open REAL, high REAL, low REAL, volume REAL, avg5 REAL, avg10 REAL, avg20 REAL, avg40 REAL, avg60 REAL, avg120 REAL, avg200 REAL, avg240 REAL, avg300 REAL, bolingerband_upper REAL, bolingerband_lower REAL, bolingerband_middle REAL, ichimokucloud_changeLine REAL, ichimokucloud_baseLine REAL, ichimokucloud_leadingSpan1 REAL, ichimokucloud_leadingSpan2 REAL, stochastic_fast_k REAL, stochastic_slow_k REAL, stochastic_slow_d REAL, rsi REAL, rsis REAL)")
# 키 생성
create_key = "CREATE INDEX IF NOT EXISTS " + stockAnalysisTableName + "_idx on " + stockAnalysisTableName + " (CODE, ymd) "
cursor.execute(create_key)
# 이동 평균 계산
stock["PRICE"] = sorted(stock["PRICE"], key=lambda x: x['ymd'])
self.get_moving_average(stock["PRICE"])
self.ichimokuCloud.analyze(stock)
self.stochastic.analyze(stock)
self.bolingerBand.analyze(stock)
self.rsi.analyze(stock)
sorted_stock = sorted(stock["PRICE"], key=lambda x: x['ymd'], reverse=True)
for price in sorted_stock:
cursor.execute('SELECT * FROM ' + stockAnalysisTableName + ' WHERE CODE=? and ymd=?', (stock['CODE'], price['ymd'],))
result = cursor.fetchone()
if result == None:
sql = "INSERT INTO " + stockAnalysisTableName + "(CODE, NAME, ymd, close, diff, open, high, low, volume, "
sql += " avg5, avg10, avg20, avg40, avg60, avg120, avg200, avg240, avg300, "
sql += " bolingerband_upper, bolingerband_lower, bolingerband_middle, "
sql += " ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2, "
sql += " stochastic_fast_k, stochastic_slow_k, stochastic_slow_d, "
sql += " rsi, rsis) "
sql += " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
cursor.execute(sql, (
stock["CODE"], stock["NAME"], price['ymd'], price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'],
price['avg5'], price['avg10'], price['avg20'], price['avg40'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'],
price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'],
price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'], price['ichimokucloud_leadingSpan1'],
price['ichimokucloud_leadingSpan2'],
price['stochastic_fast_k'], price['stochastic_slow_k'], price['stochastic_slow_d'],
price['rsi'], price['rsis'],))
else:
sql = "UPDATE " + stockAnalysisTableName + " SET close=?, diff=?, open=?, high=?, low=?, volume=?, "
sql += " avg5=?, avg10=?, avg20=?, avg40=?, avg60=?, avg120=?, avg200=?, avg240=?, avg300=?, "
sql += " bolingerband_upper=?, bolingerband_lower=?, bolingerband_middle=?, "
sql += " ichimokucloud_changeLine=?, ichimokucloud_baseLine=?, ichimokucloud_leadingSpan1=?, ichimokucloud_leadingSpan2=?, "
sql += " stochastic_fast_k=?, stochastic_slow_k=?, stochastic_slow_d=?, "
sql += " rsi=?, rsis=? "
sql += " WHERE CODE=? and ymd=?"
cursor.execute(sql,
(price['close'], price['diff'], price['open'], price['high'], price['low'], price['volume'],
price['avg5'], price['avg10'], price['avg20'], price['avg40'], price['avg60'], price['avg120'], price['avg200'], price['avg240'], price['avg300'],
price['bolingerband_upper'], price['bolingerband_lower'], price['bolingerband_middle'], price['ichimokucloud_changeLine'], price['ichimokucloud_baseLine'],
price['ichimokucloud_leadingSpan1'], price['ichimokucloud_leadingSpan2'],
price['stochastic_fast_k'], price['stochastic_slow_k'], price['stochastic_slow_d'],
price['rsi'], price['rsis'],
stock["CODE"], price['ymd'],))
break
return
def analyzeDaily(self):
stockTableName = 'stock'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
items = cursor.fetchall()
for rowid, item in enumerate(items):
stock = {"CODE": item[0], "NAME": item[1], "PRICE":[]}
print("Daily # :", rowid, ", CODE: ", stock['CODE'], ", NAME: ", stock['NAME'])
sql = 'SELECT ymd, close, diff, open, high, low, volume FROM ' + stockTableName + ' where CODE=? order by ymd desc '
#if result is not None:
# sql += ' limit 300'
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],
"avg5": -1,
"avg10": -1,
"avg20": -1,
"avg40": -1,
"avg60": -1,
"avg120": -1,
"avg200": -1,
"avg240": -1,
"avg300": -1,
"bolingerband_upper": -1,
"bolingerband_lower": -1,
"bolingerband_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})
self.analyzeAdditionalInfo(stock, cursor)
conn.commit()
cursor.close()
conn.close()
return
def analyzeGrouping(self, type):
stockTableName = 'stock'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
items = cursor.fetchall()
for rowid, item in enumerate(items):
stock = {"CODE": item[0], "NAME": item[1], "PRICE": []}
print(type, "# :", rowid, ", CODE: ", stock['CODE'], ", NAME: ", stock['NAME'])
sql = 'SELECT ymd, close, diff, open, high, low, volume FROM ' + stockTableName + ' where CODE=? order by ymd desc '
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],
"avg5": -1,
"avg10": -1,
"avg20": -1,
"avg40": -1,
"avg60": -1,
"avg120": -1,
"avg200": -1,
"avg240": -1,
"avg300": -1,
"bolingerband_upper": -1,
"bolingerband_lower": -1,
"bolingerband_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})
agg_dict = {'open': 'first',
'high': 'max',
'low': 'min',
'close': 'last',
'volume': 'sum'}
df = pd.DataFrame(stock['PRICE'])
df['ymd'] = pd.to_datetime(df['ymd'])
df.set_index('ymd', inplace=True)
if type == "weekly":
condition="W"
else:
condition='M'
df_group = df.resample(condition).agg(agg_dict)
df_group = df_group.dropna()
df_group.merge(df, )
stock['PRICE'] = self.convertFormat(df_group.to_dict())
self.analyzeAdditionalInfo(stock, cursor, type)
conn.commit()
cursor.close()
conn.close()
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__))))))
stockFileName = PROJECT_HOME + '/resources/stock.db'
analyzer = AnalyzerSqlite(PROJECT_HOME, stockFileName)
analyzer.analyzeDaily()
analyzer.analyzeGrouping("weekly")
analyzer.analyzeGrouping("monthly")
day = datetime.today().strftime("%Y%m%d")
# HTML 출력
outPath = PROJECT_HOME + "/resources/analysis/"+day
if os.path.isdir(outPath):
shutil.rmtree(outPath)
os.mkdir(outPath)
print("print to Html...")
analyzer.findCandidate(outPath)
print("time : %6.2f 초" % (time.time() - start))
print("done...")