This commit is contained in:
dosangyoon
2022-02-18 21:29:15 +09:00
parent 844f91bf7a
commit 5b2232e30f

View File

@@ -1,4 +1,3 @@
import json
import os
import time
import shutil
@@ -11,7 +10,6 @@ from matplotlib import rc
rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
import pandas as pd
import plotly.graph_objs as go
from plotly import tools, subplots
import plotly.io as po
@@ -31,6 +29,9 @@ class AnalyzerSqlite:
bolingerBand = None
ichimokuCloud = None
top500 = None
fnguide = None
common = None
stockFileName = None
fnguideFileName = None
@@ -38,8 +39,6 @@ class AnalyzerSqlite:
moving_avg = None
fnguide = {}
def __init__(self, PROJECT_HOME, stockFileName, fnguideFileName):
self.PROJECT_HOME = PROJECT_HOME
self.stockFileName = stockFileName
@@ -51,10 +50,29 @@ class AnalyzerSqlite:
self.bolingerBand = BolingerBand()
self.ichimokuCloud = IchimokuCloud()
self.top500 = self.getTop500(fnguideFileName)
self.fnguide = self.readFnguide(fnguideFileName)
return
def readFnguide(self, code):
conn = sqlite3.connect(self.fnguideFileName)
def getTop500(self, fnguideFileName):
conn = sqlite3.connect(fnguideFileName)
cursor = conn.cursor()
sql = "select DISTINCT CODE, NAME from fnguide order by total_ownership_interest desc limit 500"
cursor.execute(sql)
result = cursor.fetchall()
top500 = {}
for idx, item in enumerate(result):
top500[item[0]] = (idx+1, item[1])
cursor.close()
conn.close()
return top500
def readFnguide(self, fnguideFileName):
conn = sqlite3.connect(fnguideFileName)
cursor = conn.cursor()
today = datetime.today()
@@ -62,37 +80,34 @@ class AnalyzerSqlite:
year2 = str(today.year - 2) + ".12.01"
year3 = str(today.year - 3) + ".12.01"
sql = "SELECT business_profits, business_profits_ratio, debt_ratio, ROA, ROE, EPS, BPS, DPS, PER, PBR FROM fnguide "
sql += " WHERE code=? and (ymd=? or ymd=? or ymd=?) and type=''"
sql += " order by ymd desc"
cursor.execute(sql, (code,year1,year2,year3))
result = cursor.fetchone()
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()
business_profits, business_profits_ratio, debt_ratio, ROA, ROE, EPS, BPS, DPS, PER, PBR = [], [], [], [], [], [], [], [], [], []
fnguide = {}
for item in result:
business_profits.append(item[0])
business_profits_ratio.append(item[1])
debt_ratio.append(item[2])
ROA.append(item[3])
ROE.append(item[4])
EPS.append(item[5])
BPS.append(item[6])
DPS.append(item[7])
PER.append(item[8])
PBR.append(item[9])
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 {'business_profits': business_profits,
'business_profits_ratio': business_profits_ratio,
'debt_ratio': debt_ratio,
'ROA': ROA,
'ROE': ROE,
'EPS': EPS,
'BPS': BPS,
'DPS': DPS,
'PER': PER,
'PBR': PBR}
return fnguide
def draw(self, stock):
@@ -414,14 +429,26 @@ class AnalyzerSqlite:
return
def writeFile(self, type, CODE, NAME, stock, state):
fig = self.draw(stock)
title = "%s (%s), %d %s 차트 (<a href=\"https://alphasquare.co.kr/home/stock/financial-information?code=%s\">URL1</a>, <a href=\"https://www.tradingview.com/chart/jJ8zOXz0/?symbol=KRX:%s\">URL2</a>)" % (NAME, CODE, stock['close'][0], state, CODE, CODE)
fig['layout'].update(title=title)
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
fileName = self.outPath + "/" + str(type)
fileName = "%s/%s_%s_%s.html" % (fileName, NAME.replace(" ", ""), CODE, state)
po.write_html(fig, file=fileName, auto_open=False)
if check:
fig = self.draw(stock)
title = "%s (%s), %d %s 차트 (<a href=\"https://alphasquare.co.kr/home/stock/financial-information?code=%s\">URL1</a>, <a href=\"https://www.tradingview.com/chart/jJ8zOXz0/?symbol=KRX:%s\">URL2</a>)" % (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):
@@ -464,6 +491,10 @@ class AnalyzerSqlite:
NAME = item[1]
print (idx, CODE, NAME)
top = "0"
if CODE in self.top500:
top = str(self.top500[CODE][0])
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
@@ -545,27 +576,27 @@ class AnalyzerSqlite:
# 0_스토케스틱이 10 미만
if len(close) > 5 and stochastic_score is not None and stochastic_score < 10:
type = "참고_0_스토케스틱이 10 미만"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 0_bolingerband 하단
if len(close) > 60 and bolingerband_lower[0] is not None and close[0] < bolingerband_lower[0]:
type = "참고_0_bolingerband 하단"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 0_260일 위치 에너지가 10% 미만
if len(close) > 5 and positionalEnergy1 is not None and positionalEnergy1 < 0.1:
type = "참고_0_260일 위치 에너지가 10% 미만"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 0_260일 가격 반토막 이상
if len(close) > 5 and positionalEnergy2 is not None and positionalEnergy2 < 0.5:
type = "참고_0_260일 가격 반토막 이상"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 0_종가가 240일선 아래라면 매수한다.
if close[0] < avg240[0]:
type = "참고_0_240일선 아래"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_기준선 위 전환선 올라옴
if len(close) > 50:
@@ -576,7 +607,7 @@ class AnalyzerSqlite:
ichimokucloud_changeLine[4] <= ichimokucloud_baseLine[4]) and
volume[0] > volume[1]):
type = "참고_1_기준선 위 전환선 올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# "1_기준선 위 120일선 올라옴"
if len(close) > 50:
@@ -587,7 +618,7 @@ class AnalyzerSqlite:
avg120[4] <= ichimokucloud_baseLine[4]) and
volume[0] > volume[1]):
type = "참고_1_기준선 위 120일선 올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# "1_기준선 위 200일선 올라옴"
if len(close) > 50:
@@ -598,7 +629,7 @@ class AnalyzerSqlite:
avg200[4] <= ichimokucloud_baseLine[4]) and
volume[0] > volume[1]):
type = "참고_1_기준선 위 200일선 올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# "1_기준선 위 240일선 올라옴"
if len(close) > 50:
@@ -609,59 +640,59 @@ class AnalyzerSqlite:
avg240[4] <= ichimokucloud_baseLine[4]) and
volume[0] > volume[1]):
type = "참고_1_기준선 위 240일선 올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_종가가 200일선 돌파
if len(close) > 5 and close[0] >= avg200[0] and close[1] < avg200[1] and close[2] < avg200[2] and close[3] < avg200[3] and close[4] < avg200[4]:
type = "참고_1_200일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_종가가 240일선 돌파
if len(close) > 5 and close[0] >= avg240[0] and close[1] < avg240[1] and close[2] < avg240[2] and close[3] < avg240[3] and close[4] < avg240[4]:
type = "참고_1_240일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_20일선 돌파
temp_status = self.common.check_Dolpa_Jiji(stock, '20')
if temp_status != "":
type = "참고_1_20일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_60일선 돌파
temp_status = self.common.check_Dolpa_Jiji(stock, '60')
if temp_status != "":
type = "참고_1_60일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_골든크로스
golden_cross_status = self.common.check_golded_cross(stock)
if golden_cross_status != "":
type = "참고_1_GoldenCross"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_거래량 5배 이상
if len(volume)>2 and volume[0] > volume[1]*10:
type = "참고_1_거래량 10배 이상"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_bolingerband 하단 돌파 상승
if (len(close) > 60 and (bolingerband_lower[0] is not None and bolingerband_lower[1] is not None) and
close[0] > bolingerband_lower[0] and close[1] < bolingerband_lower[1]):
type = "참고_1_bolingerband 하단 돌파 상승"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_정배열
right_arrange = self.common.check_RightArrange(stock)
if right_arrange != "":
type = "참고_1_정배열"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
# 1_모든 라인 돌파
if (len(close) > 50 and
close[0] > max(open[0], avg5[0], avg20[0], avg60[0], avg120[0], avg240[0], bolingerband_upper[0], ichimokucloud_changeLine[0], ichimokucloud_baseLine[0]) and
open[0] < max(open[0], avg5[0], avg20[0], avg60[0], avg120[0], avg240[0], bolingerband_upper[0], ichimokucloud_changeLine[0], ichimokucloud_baseLine[0])):
type = "참고_1_모든 라인 돌파"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
### 코스피 지수 기준 숏 전략:
# 캔들이 전환선 붕괴시키면 1을 매수한다.
@@ -674,33 +705,33 @@ class AnalyzerSqlite:
if (len(close) > 50 and close[1] < ichimokucloud_changeLine[1] and ichimokucloud_changeLine[0] < close[0]):
type = "1_캔들_전환선_위로_올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 50 and close[1] < ichimokucloud_baseLine[1] and ichimokucloud_baseLine[0] < close[0]):
type = "2_캔들_기준선_위로_올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 50 and close[0] < close[26] and close[25] < close[0]):
type = "3_후행스팬_캔들_위로_올라옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 50 and close[1] > ichimokucloud_changeLine[1] and ichimokucloud_changeLine[0] > close[0]):
type = "-1_캔들_전환선_아래로_내려옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 50 and close[1] > ichimokucloud_baseLine[1] and ichimokucloud_baseLine[0] > close[0]):
type = "-2_캔들_기준선_아래로_내려옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 50 and close[0] > close[26] and close[25] > close[0]):
type = "-3_후행스팬_캔들_아래로_내려옴"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > 2 and close[1] < close[0] and open[0] < close[0] and
self.checkVolume(volume[1], volume[0])):
type = "1_거래량_상승"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
if (len(close) > covid_low_ymd_index and
close[0] > close[covid_low_ymd_index]*0.8 and close[0] < close[covid_low_ymd_index]*1.1):
type = "1_코로나_근접"
self.writeFile(type, CODE, NAME, stock, state)
self.writeFile(type, CODE, NAME, top, stock, state)
return
@@ -759,6 +790,7 @@ class AnalyzerSqlite:
stock = {"CODE": item[0], "NAME": item[1], "PRICE":[]}
print("# :", rowid, ", CODE: ", stock['CODE'], ", NAME: ", stock['NAME'])
sql = 'SELECT ymd, close, diff, open, high, low, volume FROM ' + stockTableName + ' where CODE=? order by ymd'
cursor.execute(sql, (stock['CODE'],))
items = cursor.fetchall()