This commit is contained in:
dsyoon
2021-04-26 00:46:47 +09:00
parent 5ec270bbb9
commit bcac177c61
3 changed files with 210 additions and 293 deletions

View File

@@ -3,17 +3,13 @@ import os
import time import time
import shutil import shutil
from stockpredictor.analysis.Common import Common from stockpredictor.analysis.Common import Common
from stockpredictor.analysis.MACD import MACD
from stockpredictor.analysis.RSI import RSI
from stockpredictor.analysis.Stochastic import Stochastic from stockpredictor.analysis.Stochastic import Stochastic
from stockpredictor.analysis.IchimokuCloud import IchimokuCloud
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import datetime import datetime
import sqlite3 import sqlite3
from datetime import datetime from datetime import datetime
from matplotlib import rc from matplotlib import rc
import math
rc('font', family='AppleGothic') rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False plt.rcParams['axes.unicode_minus'] = False
@@ -30,10 +26,7 @@ class Analyzer:
stocks = None stocks = None
candidate = None candidate = None
macd = None
rsi = None
stochastic = None stochastic = None
ichimokuCloud = None
common = None common = None
inFileName = None inFileName = None
@@ -51,10 +44,7 @@ class Analyzer:
self.common = Common() self.common = Common()
self.macd = MACD()
self.rsi = RSI()
self.stochastic = Stochastic() self.stochastic = Stochastic()
self.ichimokuCloud = IchimokuCloud()
self.readFnguide() self.readFnguide()
return return
@@ -97,57 +87,29 @@ class Analyzer:
if last_index > 300: if last_index > 300:
index = 300 # 최대 300일치 그래프 확인 index = 300 # 최대 300일치 그래프 확인
df_stock = pd.DataFrame(stock["PRICE"][len(stock["PRICE"]) - index:]) df_stock = pd.DataFrame(stock["PRICE"][len(stock["PRICE"]) - index:])
df_macd = pd.DataFrame(stock["MACD"][len(stock["MACD"]) - index:last_index+1])
df_stochastic = pd.DataFrame(stock["STOCHASTIC"][len(stock["STOCHASTIC"]) - index:last_index+1]) df_stochastic = pd.DataFrame(stock["STOCHASTIC"][len(stock["STOCHASTIC"]) - index:last_index+1])
df_rsi = pd.DataFrame(stock["RSI"][len(stock["RSI"]) - index:last_index+1])
df_ichimoku = pd.DataFrame(stock["ICHIMOKU"][len(stock["ICHIMOKU"]) - index:])
else: else:
index = last_index index = last_index
df_stock = pd.DataFrame(stock["PRICE"][:index+1]) df_stock = pd.DataFrame(stock["PRICE"][:index+1])
df_macd = pd.DataFrame(stock["MACD"][:index+1])
df_stochastic = pd.DataFrame(stock["STOCHASTIC"][:index+1]) df_stochastic = pd.DataFrame(stock["STOCHASTIC"][:index+1])
df_ichimoku = pd.DataFrame(stock["ICHIMOKU"][:index+1])
df_rsi = pd.DataFrame(stock["RSI"][:index+1])
# general # general
volume = go.Bar(x=df_stock.DATE, y=df_stock['volume'], name="volume") volume = go.Bar(x=df_stock.DATE, y=df_stock['volume'], name="volume")
volume_data = [volume] volume_data = [volume]
leadingSpan1 = go.Scatter(x=df_ichimoku.DATE, y=df_ichimoku['leadingSpan1'], name="선행스팬", line_color='#8B4513')
leadingSpan2 = go.Scatter(x=df_ichimoku.DATE, y=df_ichimoku['leadingSpan2'], name="후행스팬", line_color='#4169E1')
cnadle = go.Candlestick(x=df_stock.DATE, open=df_stock.open, high=df_stock.high, low=df_stock.low, close=df_stock.close, increasing_line_color= 'red', decreasing_line_color= 'blue')
ichimokuCloud_data = [leadingSpan1, leadingSpan2, cnadle]
# macd
macd = go.Scatter(x=df_macd.DATE, y=df_macd['macd'], name="MACD", line_color='#8B4513')
macd_signal = go.Scatter(x=df_macd.DATE, y=df_macd['macds'], name="MACD Signal", line_color='#4169E1')
oscillator = go.Bar(x=df_macd.DATE, y=df_macd['macdo'], name="oscillator")
macd_data = [macd, macd_signal, oscillator]
# stochastic # stochastic
slow_k = go.Scatter(x=df_stochastic.DATE, y=df_stochastic['slow_k'], name="Slow%K", line_color='#8B4513') slow_k = go.Scatter(x=df_stochastic.DATE, y=df_stochastic['slow_k'], name="Slow%K", line_color='#8B4513')
slow_d = go.Scatter(x=df_stochastic.DATE, y=df_stochastic['slow_d'], name="Slow%D", line_color='#4169E1') slow_d = go.Scatter(x=df_stochastic.DATE, y=df_stochastic['slow_d'], name="Slow%D", line_color='#4169E1')
stochastic_data = [slow_k, slow_d] stochastic_data = [slow_k, slow_d]
# rsi fig = subplots.make_subplots(rows=2, cols=1, subplot_titles=('거래량', 'Stochastic'))
rsi = go.Scatter(x=df_macd.DATE, y=df_rsi['rsi'], name="RSI", line_color='#8B4513')
rsi_signal = go.Scatter(x=df_macd.DATE, y=df_rsi['rsis'], name="RSI Signal", line_color='#4169E1')
rsi_data = [rsi, rsi_signal]
fig = subplots.make_subplots(rows=5, cols=1, subplot_titles=('MACD', 'Stochastic', 'RSI', '거래량', '일목균형표')) for trace in volume_data:
for trace in macd_data:
fig.append_trace(trace, 1, 1) fig.append_trace(trace, 1, 1)
for trace in stochastic_data: for trace in stochastic_data:
fig.append_trace(trace, 2, 1) fig.append_trace(trace, 2, 1)
for trace in rsi_data:
fig.append_trace(trace, 3, 1)
for trace in volume_data:
fig.append_trace(trace, 4, 1)
for trace in ichimokuCloud_data:
fig.append_trace(trace, 5, 1)
fig.update_layout(height=2000) fig.update_layout(height=800)
return fig return fig
@@ -157,63 +119,6 @@ class Analyzer:
return i-1 return i-1
return len(stock['PRICE']) - 1 return len(stock['PRICE']) - 1
def analyzeMACD(self):
conn = sqlite3.connect(self.inFileName)
cursor = conn.cursor()
# 기존 분석 데이터를 모두 지움
cursor.execute('update ' + self.tableName + ' set MACD = ""')
rowid = 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
while result != None:
stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2])}
results = self.macd.analyze(stock)
text = json.dumps(results, ensure_ascii=False)
cursor.execute("UPDATE " + self.tableName + " SET MACD=? WHERE CODE=?", (text, stock["CODE"]))
print("#analyzeMACD", rowid, stock['NAME'])
rowid += 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
return
def analyzeRSI(self):
conn = sqlite3.connect(self.inFileName)
cursor = conn.cursor()
# 기존 분석 데이터를 모두 지움
cursor.execute('update ' + self.tableName + ' set RSI = ""')
rowid = 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
while result != None:
prices = json.loads(result[2])
for price in prices:
del price['diff']
stock = {"CODE": result[0], "NAME": result[1], "PRICE": prices}
results = self.rsi.analyze(stock)
text = json.dumps(results, ensure_ascii=False)
cursor.execute("UPDATE " + self.tableName + " SET RSI=? WHERE CODE=?", (text, stock["CODE"]))
print("#analyzeRSI", rowid, stock['NAME'])
rowid += 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
return
def analyzeStochastic(self): def analyzeStochastic(self):
conn = sqlite3.connect(self.inFileName) conn = sqlite3.connect(self.inFileName)
cursor = conn.cursor() cursor = conn.cursor()
@@ -240,33 +145,7 @@ class Analyzer:
conn.close() conn.close()
return return
def analyzeIchimokuCloud(self): def analyzeFinalScore(self, last_index, STOCK, STOCHASTIC):
conn = sqlite3.connect(self.inFileName)
cursor = conn.cursor()
# 기존 분석 데이터를 모두 지움
cursor.execute('update ' + self.tableName + ' set ICHIMOKU = ""')
rowid = 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
while result != None:
stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2])}
results = self.ichimokuCloud.analyze(stock)
text = json.dumps(results, ensure_ascii=False)
cursor.execute("UPDATE " + self.tableName + " SET ICHIMOKU=? WHERE CODE=?", (text, stock["CODE"]))
print("#analyzeIchimokuCloud", rowid, stock['NAME'])
rowid += 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
return
def analyzeFinalScore(self, last_index, STOCK, MACD, STOCHASTIC, ICHIMOKU, RSI):
""" """
매수 조건 매수 조건
#0. 최소 매수 조건은 거래량은 20만건, 종가는 2천원 이상인 종목이어야 한다. #0. 최소 매수 조건은 거래량은 20만건, 종가는 2천원 이상인 종목이어야 한다.
@@ -290,40 +169,69 @@ class Analyzer:
if STOCK[i]['volume'] > 100000 and STOCK[i]['close'] > 2000: if STOCK[i]['volume'] > 100000 and STOCK[i]['close'] > 2000:
# 거래량이 100만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94) # 거래량이 100만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94)
# 5-20 # 정배열 체크
days20_line_buying1_status = self.common.check_days5_20_line_buying(STOCK, i) temp_status = self.common.check_RightArrange(STOCK, i)
if days20_line_buying1_status != "": if temp_status != "":
#if STOCHASTIC[i]['slow_k'] < 40: #if STOCHASTIC[i]['slow_k'] < 40:
status += days20_line_buying1_status status += temp_status
# 5-60 # 20
days60_line_buying1_status = self.common.check_days5_60_line_buying(STOCK, i) temp_status = self.common.check_Dolpa_Jiji(STOCK, i, '20')
if days60_line_buying1_status != "": if temp_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += days60_line_buying1_status
# 5-120
days120_line_buying1_status = self.common.check_days5_120_line_buying(STOCK, i)
if days120_line_buying1_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += days120_line_buying1_status
# 5-240
days240_line_buying1_status = self.common.check_days5_240_line_buying(STOCK, i)
if days240_line_buying1_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += days240_line_buying1_status
# 20-60
days60_line_buying2_status = self.common.check_days20_60_line_buying(STOCK, i)
if days60_line_buying2_status != "":
#if STOCHASTIC[i]['slow_k'] < 40: #if STOCHASTIC[i]['slow_k'] < 40:
status += days60_line_buying2_status status += temp_status
# 60
temp_status = self.common.check_Dolpa_Jiji(STOCK, i, '60')
if temp_status != "":
#if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 120
temp_status = self.common.check_Dolpa_Jiji(STOCK, i, '120')
if temp_status != "":
#if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 240
temp_status = self.common.check_Dolpa_Jiji(STOCK, i, '240')
if temp_status != "":
#if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 270일 최고가 돌파
temp_status = self.common.check_highest_270(STOCK, i)
if temp_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 20일선 지지 매수가 추천
temp_status = self.common.check_Dolpa_Jiji_20(STOCK, i)
if temp_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 단타 #1
temp_status = self.common.check_Danta1(STOCK, i)
if temp_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
# 단타 #2
temp_status = self.common.check_Danta2(STOCK, i)
if temp_status != "":
# if STOCHASTIC[i]['slow_k'] < 40:
status += temp_status
all_upper_cross_status = self.common.checkAllUpperCross(STOCK, i) all_upper_cross_status = self.common.checkAllUpperCross(STOCK, i)
if all_upper_cross_status != "": if all_upper_cross_status != "":
status += all_upper_cross_status status += all_upper_cross_status
# 1주일 동안 몇 10% 이상 오른 종목
w1Rate = self.common.check_W1Rate(STOCK, i)
if w1Rate != "":
status += w1Rate
# GOLDENCROSS#1은 바로 매수하지 않고, 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다. # GOLDENCROSS#1은 바로 매수하지 않고, 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다.
# GOLDENCROSS#2은 바로 매수 가능 # GOLDENCROSS#2은 바로 매수 가능
# GOLDENCROSS#3은 바로 매수 가능 # GOLDENCROSS#3은 바로 매수 가능
@@ -337,11 +245,6 @@ class Analyzer:
if bearmarket_buying_status != "": if bearmarket_buying_status != "":
status += bearmarket_buying_status status += bearmarket_buying_status
# BUYINGSTOCHASTIC#1은 바로 매수 가능
stochastic_buying_status = self.common.check_stochastic_buying(STOCK, STOCHASTIC, ICHIMOKU, i)
if stochastic_buying_status != "":
status += stochastic_buying_status
# STOCHASTIC # STOCHASTIC
stochastic_status = self.common.check_stochastic(STOCK, STOCHASTIC, i) stochastic_status = self.common.check_stochastic(STOCK, STOCHASTIC, i)
if stochastic_status != "": if stochastic_status != "":
@@ -376,51 +279,74 @@ class Analyzer:
if ((item_code in self.fnguide and not self.fnguide[item_code]) or (item_code == "KOSPI" or item_code == "KOSDAK") or result[3] == ''): if ((item_code in self.fnguide and not self.fnguide[item_code]) or (item_code == "KOSPI" or item_code == "KOSDAK") or result[3] == ''):
rowid += 1 rowid += 1
# 다음 종목을 가져옴 # 다음 종목을 가져옴
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,)) cursor.execute('SELECT CODE, NAME, PRICE, STOCHASTIC FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone() result = cursor.fetchone()
continue continue
result_3 = result[3] result_3 = result[3]
result_4 = result[4] if result[3] != result[3]:
result_5 = result[5] result_3 = result[3].replace("NaN", "0")
result_6 = result[6] if result[3]==None:
if result[3] != result[3]: result_3 = result[3].replace("NaN", "0") rowid += 1
if result[4] != result[4]: result_4 = result[4].replace("NaN", "0") cursor.execute('SELECT CODE, NAME, PRICE, STOCHASTIC FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
if result[5] != result[5]: result_5 = result[5].replace("NaN", "0") result = cursor.fetchone()
if result[6] != result[6]: result_6 = result[6].replace("NaN", "0") continue
stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2]), "MACD": json.loads(result_3), "STOCHASTIC": json.loads(result_4), "ICHIMOKU": json.loads(result_5), "RSI": json.loads(result_6)} stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2]), "STOCHASTIC": json.loads(result_3)}
last_index = self.get_last_index(stock) last_index = self.get_last_index(stock)
STOCK = stock['PRICE'] STOCK = stock['PRICE']
MACD = stock['MACD']
STOCHASTIC = stock['STOCHASTIC'] STOCHASTIC = stock['STOCHASTIC']
ICHIMOKU = stock['ICHIMOKU']
RSI = stock['RSI']
stochastic_score = STOCHASTIC[last_index]['slow_k'] stochastic_score = STOCHASTIC[last_index]['slow_k']
if stochastic_score < 50: if stochastic_score < 50:
macd_score = MACD[last_index]['macd']
rsi_score = RSI[last_index]['rsi']
ichimoku_score = ICHIMOKU[last_index]['ichimoku_buy']
# 종목 상태 체크 분석 # 종목 상태 체크 분석
state, buy_price = self.analyzeFinalScore(last_index, STOCK, MACD, STOCHASTIC, ICHIMOKU, RSI) state, buy_price = self.analyzeFinalScore(last_index, STOCK, STOCHASTIC)
if state != "": if state != "":
fig = self.draw(stock) fig = self.draw(stock)
title = "%s (%s), %s, buy_price (%d), stochastic(%.3f), rsi(%.3f), macd(%.3f), ichimoku(%d) 차트" % (item_name, item_code, state, buy_price, stochastic_score, rsi_score, macd_score, ichimoku_score) title = "%s (%s), %s, buy_price (%d), stochastic(%.3f) 차트" % (item_name, item_code, state, buy_price, stochastic_score)
fig['layout'].update(title=title) fig['layout'].update(title=title)
fileName = "%s/%s__%.3f__%.3f__%s_%s.html" % (outPath, state, stochastic_score, rsi_score, item_name.replace(" ", ""), item_code) fileName = "%s/%s__%.3f__%s_%s.html" % (outPath, state, stochastic_score, item_name.replace(" ", ""), item_code)
po.write_html(fig, file=fileName, auto_open=False) po.write_html(fig, file=fileName, auto_open=False)
else: else:
if (RSI[last_index]['rsi_buy'] == 1) and STOCK[last_index]['volume'] > 1000000: if STOCK[last_index]['volume'] > 1000000:
fig = self.draw(stock) fig = self.draw(stock)
title = "%s (%s) buy_price (%d), stochastic(%.3f), rsi(%.3f), macd(%.3f), ichimoku(%d) 차트"%(item_name, item_code, buy_price, stochastic_score, rsi_score, macd_score, ichimoku_score) title = "%s (%s) buy_price (%d), stochastic(%.3f) 차트"%(item_name, item_code, buy_price, stochastic_score)
fig['layout'].update(title=title) fig['layout'].update(title=title)
fileName = "%s/%.3f__%.3f__%s_%s.html"%(tmp_path, stochastic_score, rsi_score, item_name.replace(" ", ""), item_code) fileName = "%s/%.3f__%s_%s.html"%(tmp_path, stochastic_score, item_name.replace(" ", ""), item_code)
po.write_html(fig, file=fileName, auto_open=False) po.write_html(fig, file=fileName, auto_open=False)
"""
try:
stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2]), "STOCHASTIC": json.loads(result_3)}
last_index = self.get_last_index(stock)
STOCK = stock['PRICE']
STOCHASTIC = stock['STOCHASTIC']
stochastic_score = STOCHASTIC[last_index]['slow_k']
if stochastic_score < 50:
# 종목 상태 체크 분석
state, buy_price = self.analyzeFinalScore(last_index, STOCK, STOCHASTIC)
if state != "":
fig = self.draw(stock)
title = "%s (%s), %s, buy_price (%d), stochastic(%.3f) 차트" % (item_name, item_code, state, buy_price, stochastic_score)
fig['layout'].update(title=title)
fileName = "%s/%s__%.3f__%s_%s.html" % (outPath, state, stochastic_score, item_name.replace(" ", ""), item_code)
po.write_html(fig, file=fileName, auto_open=False)
else:
if STOCK[last_index]['volume'] > 1000000:
fig = self.draw(stock)
title = "%s (%s) buy_price (%d), stochastic(%.3f) 차트"%(item_name, item_code, buy_price, stochastic_score)
fig['layout'].update(title=title)
fileName = "%s/%.3f__%s_%s.html"%(tmp_path, stochastic_score, item_name.replace(" ", ""), item_code)
po.write_html(fig, file=fileName, auto_open=False)
except:
print ("error")
"""
rowid += 1 rowid += 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,)) cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
result = cursor.fetchone() result = cursor.fetchone()
@@ -434,7 +360,7 @@ class Analyzer:
cursor = conn.cursor() cursor = conn.cursor()
# 기존 분석 데이터를 모두 지움 # 기존 분석 데이터를 모두 지움
cursor.execute('update ' + self.tableName + ' set ICHIMOKU = "", MACD = "", STOCHASTIC = "", RSI = ""') cursor.execute('update ' + self.tableName + ' set STOCHASTIC = ""')
rowid = 1 rowid = 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,)) cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
@@ -443,17 +369,8 @@ class Analyzer:
stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2])} stock = {"CODE": result[0], "NAME": result[1], "PRICE": json.loads(result[2])}
try: try:
results_ICHIMOKU = self.ichimokuCloud.analyze(stock)
text_ICHIMOKU = json.dumps(results_ICHIMOKU, ensure_ascii=False)
results_MACD = self.macd.analyze(stock)
text_MACD = json.dumps(results_MACD, ensure_ascii=False)
results_STOCHASTIC = self.stochastic.analyze(stock) results_STOCHASTIC = self.stochastic.analyze(stock)
text_STOCHASTIC = json.dumps(results_STOCHASTIC, ensure_ascii=False) text_STOCHASTIC = json.dumps(results_STOCHASTIC, ensure_ascii=False)
results_RSI = self.rsi.analyze(stock)
text_RSI = json.dumps(results_RSI, ensure_ascii=False)
except: except:
print("#", rowid, stock['NAME']) print("#", rowid, stock['NAME'])
rowid += 1 rowid += 1
@@ -461,7 +378,7 @@ class Analyzer:
result = cursor.fetchone() result = cursor.fetchone()
continue continue
cursor.execute("UPDATE " + self.tableName + " SET ICHIMOKU=?, MACD=?, STOCHASTIC=?, RSI=? WHERE CODE=?", (text_ICHIMOKU,text_MACD,text_STOCHASTIC,text_RSI, stock["CODE"])) cursor.execute("UPDATE " + self.tableName + " SET STOCHASTIC=? WHERE CODE=?", (text_STOCHASTIC, stock["CODE"]))
print("#", rowid, stock['NAME']) print("#", rowid, stock['NAME'])
rowid += 1 rowid += 1
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,)) cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
@@ -483,14 +400,8 @@ if __name__ == "__main__":
# 분석 & update DB # 분석 & update DB
""" """
#print ("analyze IchimokuCloud...")
analyzer.analyzeIchimokuCloud()
#print ("analyze MACD...")
analyzer.analyzeMACD()
#print ("analyze Stochastic...") #print ("analyze Stochastic...")
analyzer.analyzeStochastic() analyzer.analyzeStochastic()
#print ("analyze RSI...")
analyzer.analyzeRSI()
""" """
###analyzer.analyze() ###analyzer.analyze()

View File

@@ -229,124 +229,127 @@ class Common:
return "STOCHASTIC#2_" return "STOCHASTIC#2_"
return "" return ""
def check_days5_20_line_buying(self, stock, i): def check_highest_270(self, stock, i):
""" # 270일 기준으로 최고가를 기록하는 순간 매수를 시도한다.
5일 선이 20일 선을 뚫고 올라온 순간 체크 # https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_27
5일선이 다시 20선 아래로 내려가는 순간 손걸한다. upper_index = 0
""" if len(stock) > 271:
if stock[i]['close'] == stock[i]['high']: top = 0
# 윗꼬리 없는 양봉이어야 한다. for idx in range(2, 271):
return "" # 최근 270일 중 최고가를 구한다.
if top < stock[-idx]['close']:
top = stock[-idx]['close']
if len(stock) > 61: if top < stock[i]['close']:
# 오늘 종가가 20일선을 뚫고 올라왔다. (20일선<오늘종가 and (어제종가<20 or 어제5일선<20)) return "highest_"
# 오늘 종가는 양봉이어야 한다.
# 어제부터 index1일까지 20일선이 5일선 위에 있었다.
# index1일부터 index2일까지 5일선이 20일선 위에 있었다.
# 이전 5일선이 20일선을 뚫었던 종가보다 오늘 뚫은 종가가 높거나 혹은 오늘 종가가 더 낮더라도 장대 양봉어어야 한다.
# 주봉의 20일 평균이 이전 주봉의 20일 평균 보다 높아야 한다.
if stock[i]['avg20'] < stock[i]['close'] and (stock[i-1]['close'] < stock[i]['avg20'] or stock[i-1]['avg5'] < stock[i]['avg20']):
if (stock[i-3]['avg5'] < stock[i-3]['avg20'] or stock[i-2]['avg5'] < stock[i-2]['avg20'] or stock[i-1]['avg5'] < stock[i-1]['avg20']):
#if (stock[i - 1]['avg5'] < stock[i - 1]['avg20']):
if stock[i]['open'] < stock[i]['close']:
index1 = -1
for j in range(1, 61):
if stock[i-j]['avg20'] < stock[i-j]['avg5']:
index1 = j
break
index2 = -1
for j in range(index1+1, 61):
if stock[i-j]['avg5'] < stock[i-j]['avg20']:
index2 = j
break
if (index2 != -1 and ((stock[i-index2]['close'] < stock[i]['close']) or (stock[i]['high']-stock[i]['close'] < stock[i]['open']-stock[i]['low']))):
# 주봉의 20일 평균이 이전 주봉의 20일 평균 보다 높아야 한다.
return "5-20_"
return "" return ""
def check_days5_60_line_buying(self, stock, i): def check_Dolpa_Jiji(self, stock, i, day='20'):
""" upper_index = 0
5일 선이 60일 선을 뚫고 올라온 순간 체크 if len(stock) > 5:
5일선이 다시 60선 아래로 내려가는 순간 손걸한다. for idx in range(1, 5):
""" # day선을 돌파하는 양봉이고, 종가가 최고가 보다 100 이내이어야 한다.
if stock[i]['close'] == stock[i]['high']: if stock[-idx]['open'] < stock[-idx]["avg"+day] < stock[-idx]['close'] and stock[-idx]['high'] - 100 <= stock[-idx]['close']:
# 윗꼬리 없는 양봉이어야 한다. upper_index = idx
return "" break
if upper_index != 0:
for cidx in range(1, upper_index):
# 해당일의 종가보다 현재의 시가가 높거나 같아야 하며, 현재가는 양봉이어야 한다.
if stock[-upper_index]['close'] <= stock[-cidx]['open'] and stock[-cidx]['open'] < stock[-cidx]['close']:
# 해당 기준일 선은 상승이어야 한다.
if stock[-upper_index]['avg'+day] < stock[-cidx]['avg'+day]:
return day + "_"
return ""
def check_Dolpa_Jiji_20(self, stock, i):
"""
top: 이전 5일선이 20일선 위에 있을 때 최고가
top일 체크 사항 (20일 < 5일선)
5일선이 20일 선으로 내려왔다가 다시 20일선 위로 올라왔고, top < 오늘 시가 + 100
top < 시가 < 종가 라면 다음날 매수한다.
# https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_80
"""
if len(stock) > 61: if len(stock) > 61:
# 오늘 5일선이 60일선 위에 올라왔다. if stock[i]['avg20'] < stock[i]['close'] and stock[i]['avg20'] < stock[i]['open']:
# 어제부터 index1일까지 60일선이 5일선 위에 있었다. if stock[i]['avg5'] < stock[i]['avg20']:
# index1일부터 index2일까지 5일선이 60일선 위에 있었다.
if stock[i]['avg60'] < stock[i]['avg5']:
if (stock[i - 3]['avg5'] < stock[i - 3]['avg60'] or stock[i - 2]['avg5'] < stock[i - 2]['avg60'] or stock[i - 1]['avg5'] < stock[i - 1]['avg60']):
#if (stock[i - 1]['avg5'] < stock[i - 1]['avg60']):
index1 = -1 index1 = -1
for j in range(1, 150): for j in range(1, 61):
if stock[i-j]['avg60'] < stock[i-j]['avg5']: if stock[i-j]['avg20'] < stock[i-j]['avg5']:
index1 = j index1 = j
break break
index2 = -1 top = 0
for j in range(index1+1, 150): for j in range(index1+1, 61):
if stock[i-j]['avg5'] < stock[i-j]['avg60']: if stock[i - j]['open'] < stock[i - j]['close']:
index2 = j if top < stock[i - j]['close']:
top = stock[i - j]['close']
else:
if top < stock[i - j]['open']:
top = stock[i - j]['open']
if stock[i-j]['avg5'] < stock[i-j]['avg20']:
break break
if (index2 != -1 and (stock[i-index2+1]['close'] < stock[i]['close'])): return "5-20_"
return "5-60_"
return "" return ""
def check_days20_60_line_buying(self, stock, i): def check_Danta1(self, stock, i):
""" """
20일 선이 60일 선을 뚫고 올라온 순간 체크 어제 상한가 혹은 상승양봉이 나온다.
20일선이 다시 60선 아래로 내려가는 순간 손걸한다. 오늘 상승 출발을 해야 하며 상승 음봉이 나온다
""" - 어제 종가 = 어제 상한가 < 종가 < 시가 < 상한가
if stock[i]['close'] == stock[i]['high']: https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_109
# 윗꼬리 없는 양봉이어야 한다.
return ""
if len(stock) > 151: 만약 다음날 시작초가가 오늘 종가보다 높게 상승으로 출발한다면 매수를 한다.
# 오늘 20일선이 60일선 위에 올라왔다. 손절가는 오늘 최저가이다.
# 어제부터 index1일까지 60일선이 20일선 위에 있었다. """
# index1일부터 index2일까지 20일선이 60일선 위에 있었다. if stock[i-1]['open'] < stock[i-1]['close'] == stock[i-1]['high']:
if stock[i]['avg60'] < stock[i]['avg20']: if stock[i-1]['close'] < stock[i]['close'] < stock[i]['open'] < stock[i]['high']:
if (stock[i - 3]['avg20'] < stock[i - 3]['avg60'] or stock[i - 2]['avg20'] < stock[i - 2]['avg60'] or stock[i - 1]['avg20'] < stock[i - 1]['avg60']): return "danta1_"
#if (stock[i - 1]['avg20'] < stock[i - 1]['avg60']):
index1 = -1
for j in range(1, 150):
if stock[i-j]['avg60'] < stock[i-j]['avg20']:
index1 = j
break
index2 = -1
for j in range(index1+1, 150):
if stock[i-j]['avg20'] < stock[i-j]['avg60']:
index2 = j
break
if (index2 != -1 and (stock[i-index2+1]['close'] < stock[i]['close'])):
return "20-60_"
return "" return ""
def check_days5_120_line_buying(self, stock, i): def check_Danta2(self, stock, i):
if stock[i]['close'] == stock[i]['high']: """
# 윗꼬리 없는 양봉이어야 한다. 쐐기, 수렴, 깃대 패턴 확인
return "" # https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_144
상단 추세선을 돌파하면 매수를 한다.
""" """
5일 선이 120일 선을 뚫고 올라온 순간 체크 price_10 = round(stock[i]["close"] / 10)
""" if stock[-i]["open"] < stock[-i]["close"]:
if stock[i-1]['close'] < stock[i-1]['avg120']: top = stock[-i]["close"]
if stock[i]['avg120'] < stock[i]['close']: bottom = stock[-i]["open"]
return "5-120_" else:
top = stock[-i]["open"]
bottom = stock[-i]["close"]
if len(stock) > 21:
for i in range(2, 21):
if stock[-i]["open"] < stock[-i]["close"]:
if top < stock[-i]["close"]:
top = stock[-i]["close"]
if stock[-i]["open"] < bottom:
bottom = stock[-i]["open"]
else:
if top < stock[-i]["open"]:
top = stock[-i]["open"]
if stock[-i]["close"] < bottom:
bottom = stock[-i]["close"]
if top - bottom < price_10:
return "danta2_"
return "" return ""
def check_days5_240_line_buying(self, stock, i): def check_RightArrange(self, stock, i):
if stock[i]['close'] == stock[i]['high']:
# 윗꼬리 없는 양봉이어야 한다.
return ""
""" """
5일 선이 240일 선을 뚫고 올라온 순간 체크 어제는 정배열이 아니었는데, 오늘은 정배열인 경우
""" """
if stock[i-1]['close'] < stock[i-1]['avg240']: if len(stock) > 2:
if stock[i]['avg240'] < stock[i]['close']: if (not (stock[i-1]["avg120"] < stock[i-1]["avg60"] < stock[i-1]["avg20"] < stock[i-1]["avg5"]) and
return "5-240_" (stock[i]["avg120"] < stock[i]["avg60"] < stock[i]["avg20"] < stock[i]["avg5"])):
return "arrange_"
return "" return ""
def check_W1Rate(self, stock, i):
if len(stock) > 5:
rate = round((stock[i]["close"] - stock[i-4]["close"]) / stock[i-4]["close"],2)
if rate >= 0.05:
return "1w("+str(rate)+")_"
return ""

View File

@@ -21,6 +21,7 @@ print("[KOSPI 상장기업 재무제표 다운로드]")
crawler.crawl_fnguide(inFnguideFileName) crawler.crawl_fnguide(inFnguideFileName)
""" """
crawler = MetaCrawler() crawler = MetaCrawler()
print("\n[환율 (USD, JPY, EUR, CNY), 원유 (WTI), 국제금]") print("\n[환율 (USD, JPY, EUR, CNY), 원유 (WTI), 국제금]")
inFileName = PROJECT_HOME + '/resources/meta_1.db' inFileName = PROJECT_HOME + '/resources/meta_1.db'
@@ -52,12 +53,13 @@ crawler = StockCrawler()
crawler.saveIndex("KOSPI", kospiFileName, outFileName) crawler.saveIndex("KOSPI", kospiFileName, outFileName)
crawler.saveIndex("KOSDAK", kosdakFileName, outFileName) crawler.saveIndex("KOSDAK", kosdakFileName, outFileName)
print("\n[종목 분석]") print("\n[종목 분석]")
# S: 분석까지 진행 # S: 분석까지 진행
inFileName = PROJECT_HOME + '/resources/stock.db' inFileName = PROJECT_HOME + '/resources/stock.db'
analyzer = Analyzer(PROJECT_HOME, inFileName, inFnguideFileName) analyzer = Analyzer(PROJECT_HOME, inFileName, inFnguideFileName)
analyzer.analyze() analyzer.analyze()
3
print("\n[종목 결정]") print("\n[종목 결정]")
day = datetime.datetime.today().strftime("%Y%m%d") day = datetime.datetime.today().strftime("%Y%m%d")
outPath = PROJECT_HOME + "/resources/analysis/" + day outPath = PROJECT_HOME + "/resources/analysis/" + day
@@ -68,6 +70,7 @@ print("print to Html...")
analyzer.analyzeToHtml(outPath) analyzer.analyzeToHtml(outPath)
# E: 분석까지 진행 # E: 분석까지 진행
print("time : %6.2f", (time.time() - start)) print("time : %6.2f", (time.time() - start))
print ("done...") print ("done...")