init
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user