init
This commit is contained in:
@@ -4,6 +4,7 @@ import time
|
||||
import shutil
|
||||
from stockpredictor.analysis.Common import Common
|
||||
from stockpredictor.analysis.Stochastic import Stochastic
|
||||
from stockpredictor.analysis.BolingerBand import BolingerBand
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime
|
||||
import sqlite3
|
||||
@@ -45,6 +46,7 @@ class Analyzer:
|
||||
self.common = Common()
|
||||
|
||||
self.stochastic = Stochastic()
|
||||
self.bolingerBand = BolingerBand()
|
||||
|
||||
self.readFnguide()
|
||||
return
|
||||
@@ -459,7 +461,7 @@ class Analyzer:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 기존 분석 데이터를 모두 지움
|
||||
cursor.execute('update ' + self.tableName + ' set STOCHASTIC = ""')
|
||||
cursor.execute('update ' + self.tableName + ' set STOCHASTIC = "", BOLINGERBAND = ""')
|
||||
|
||||
rowid = 1
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
@@ -470,6 +472,9 @@ class Analyzer:
|
||||
try:
|
||||
results_STOCHASTIC = self.stochastic.analyze(stock)
|
||||
text_STOCHASTIC = json.dumps(results_STOCHASTIC, ensure_ascii=False)
|
||||
|
||||
results_BolingerBand = self.bolingerBand.analyze(stock)
|
||||
text_BOLINGERBAND = json.dumps(results_BolingerBand, ensure_ascii=False)
|
||||
except:
|
||||
print("#", rowid, stock['NAME'])
|
||||
rowid += 1
|
||||
@@ -477,7 +482,7 @@ class Analyzer:
|
||||
result = cursor.fetchone()
|
||||
continue
|
||||
|
||||
cursor.execute("UPDATE " + self.tableName + " SET STOCHASTIC=? WHERE CODE=?", (text_STOCHASTIC, stock["CODE"]))
|
||||
cursor.execute("UPDATE " + self.tableName + " SET STOCHASTIC=?, BOLINGERBAND=? WHERE CODE=?", (text_STOCHASTIC, text_BOLINGERBAND, stock["CODE"]))
|
||||
print("#", rowid, stock['NAME'])
|
||||
rowid += 1
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
@@ -503,7 +508,7 @@ if __name__ == "__main__":
|
||||
analyzer.analyzeStochastic()
|
||||
"""
|
||||
|
||||
###analyzer.analyze()
|
||||
analyzer.analyze()
|
||||
|
||||
day = datetime.today().strftime("%Y%m%d")
|
||||
|
||||
|
||||
@@ -1,432 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
from stockpredictor.analysis.Common import Common
|
||||
from stockpredictor.analysis.Stochastic import Stochastic
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
|
||||
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
|
||||
|
||||
class Analyzer:
|
||||
tableName = 'stock'
|
||||
PROJECT_HOME = None
|
||||
|
||||
stocks = None
|
||||
candidate = None
|
||||
|
||||
stochastic = None
|
||||
|
||||
common = None
|
||||
inFileName = None
|
||||
fnguideFileName = None
|
||||
|
||||
fnguide = {}
|
||||
|
||||
def __init__(self, PROJECT_HOME, inFileName, fnguideFileName):
|
||||
self.PROJECT_HOME = PROJECT_HOME
|
||||
self.inFileName = inFileName
|
||||
self.fnguideFileName = fnguideFileName
|
||||
|
||||
self.stocks = []
|
||||
self.candidate = []
|
||||
|
||||
self.common = Common()
|
||||
|
||||
self.stochastic = Stochastic()
|
||||
|
||||
self.readFnguide()
|
||||
return
|
||||
|
||||
def readFnguide(self):
|
||||
conn = sqlite3.connect(self.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"
|
||||
|
||||
rowid = 1
|
||||
cursor.execute('SELECT * FROM fnguide WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
while result != None:
|
||||
data = json.loads(result[2])
|
||||
self.fnguide[result[0]] = True
|
||||
|
||||
if (year1 in data and year2 in data and year3 in data):
|
||||
if (data[year1]['영업이익'] < 0 and data[year2]['영업이익'] < 0 and data[year3]['영업이익'] < 0):
|
||||
# 3년 연속 영업이익이 적자이면 매수하지 않는다.
|
||||
self.fnguide[result[0]] = False
|
||||
if (data[year1]['영업이익'] < -100):
|
||||
# 전년 영억적자가 100억 이상이면 매수하지 않는다.
|
||||
self.fnguide[result[0]] = False
|
||||
|
||||
rowid += 1
|
||||
cursor.execute('SELECT * FROM fnguide WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return
|
||||
|
||||
def draw(self, stock):
|
||||
|
||||
last_index = self.get_last_index(stock)
|
||||
if last_index > 300:
|
||||
index = 300 # 최대 300일치 그래프 확인
|
||||
df_stock = pd.DataFrame(stock["PRICE"][len(stock["PRICE"]) - index:])
|
||||
df_stochastic = pd.DataFrame(stock["STOCHASTIC"][len(stock["STOCHASTIC"]) - index:last_index+1])
|
||||
else:
|
||||
index = last_index
|
||||
df_stock = pd.DataFrame(stock["PRICE"][:index+1])
|
||||
df_stochastic = pd.DataFrame(stock["STOCHASTIC"][:index+1])
|
||||
|
||||
# general
|
||||
volume = go.Bar(x=df_stock.DATE, y=df_stock['volume'], name="volume")
|
||||
volume_data = [volume]
|
||||
|
||||
# stochastic
|
||||
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')
|
||||
stochastic_data = [slow_k, slow_d]
|
||||
|
||||
fig = subplots.make_subplots(rows=2, cols=1, subplot_titles=('거래량', 'Stochastic'))
|
||||
|
||||
for trace in volume_data:
|
||||
fig.append_trace(trace, 1, 1)
|
||||
for trace in stochastic_data:
|
||||
fig.append_trace(trace, 2, 1)
|
||||
|
||||
fig.update_layout(height=800)
|
||||
|
||||
return fig
|
||||
|
||||
def get_last_index(self, stock):
|
||||
for i in range(0, len(stock['PRICE'])):
|
||||
if (stock['PRICE'][i]['close'] == 0 and stock['PRICE'][i]['open'] == 0 and stock['PRICE'][i]['volume'] == 0):
|
||||
return i-1
|
||||
return len(stock['PRICE']) - 1
|
||||
|
||||
def analyzeStochastic(self):
|
||||
conn = sqlite3.connect(self.inFileName)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 기존 분석 데이터를 모두 지움
|
||||
cursor.execute('update ' + self.tableName + ' set STOCHASTIC = ""')
|
||||
|
||||
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.stochastic.analyze(stock)
|
||||
text = json.dumps(results, ensure_ascii=False)
|
||||
cursor.execute("UPDATE " + self.tableName + " SET STOCHASTIC=? WHERE CODE=?", (text, stock["CODE"]))
|
||||
|
||||
print("#analyzeStochastic", 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, STOCHASTIC):
|
||||
"""
|
||||
매수 조건
|
||||
#0. 최소 매수 조건은 거래량은 20만건, 종가는 2천원 이상인 종목이어야 한다.
|
||||
#1. 골든크로스: 5일선, 20일선, 60일선, 120일선이 순서대로 나열되는 순간
|
||||
"""
|
||||
i = last_index
|
||||
buy_price = 0
|
||||
count = 0
|
||||
for idx in range(i, i-5, -1):
|
||||
if idx-1 < 0:
|
||||
break
|
||||
buy_price += STOCK[idx-1]['close'] - STOCK[idx]['low']
|
||||
count += 1
|
||||
if count == 0:
|
||||
buy_price = STOCK[i]['close']
|
||||
else:
|
||||
# 종가 - 최저가의 최근 3일 평균 가격을 산정한다.
|
||||
buy_price = round(STOCK[i]['close'] - (buy_price/count))
|
||||
|
||||
status = ""
|
||||
if STOCK[i]['volume'] > 100000 and STOCK[i]['close'] > 2000:
|
||||
# 거래량이 100만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94)
|
||||
|
||||
# 정배열 체크
|
||||
temp_status = self.common.check_RightArrange(STOCK, i)
|
||||
if temp_status != "":
|
||||
#if STOCHASTIC[i]['slow_k'] < 40:
|
||||
status += temp_status
|
||||
|
||||
# 20일선 돌파
|
||||
temp_status = self.common.check_Dolpa_Jiji(STOCK, i, '20')
|
||||
if temp_status != "":
|
||||
#if STOCHASTIC[i]['slow_k'] < 40:
|
||||
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)
|
||||
if all_upper_cross_status != "":
|
||||
status += all_upper_cross_status
|
||||
|
||||
# 1주일 동안 몇 10% 이상 오른 종목
|
||||
W1Rise = self.common.check_W1Rise(STOCK, i, 0.1)
|
||||
if W1Rise != "":
|
||||
status += W1Rise
|
||||
|
||||
# 1일 동안 몇 10% 이상 내리 종목
|
||||
W1Fall = self.common.check_D1Fall(STOCK, i, -0.1)
|
||||
if W1Fall != "":
|
||||
status += W1Fall
|
||||
|
||||
# GOLDENCROSS#1은 바로 매수하지 않고, 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다.
|
||||
# GOLDENCROSS#2은 바로 매수 가능
|
||||
# GOLDENCROSS#3은 바로 매수 가능
|
||||
golden_cross_status = self.common.check_golded_cross(STOCK, i)
|
||||
if golden_cross_status != "":
|
||||
status += golden_cross_status
|
||||
|
||||
# BUYINGBEARMARKET#1은 바로 매수 가능
|
||||
# BUYINGBEARMARKET#2은 바로 매수 가능
|
||||
bearmarket_buying_status = self.common.check_bearmarket_buying(STOCK, STOCHASTIC, i)
|
||||
if bearmarket_buying_status != "":
|
||||
status += bearmarket_buying_status
|
||||
|
||||
# STOCHASTIC
|
||||
stochastic_status = self.common.check_stochastic(STOCK, STOCHASTIC, i)
|
||||
if stochastic_status != "":
|
||||
status += stochastic_status
|
||||
|
||||
# YANGBONG
|
||||
if self.common.checkLongYangBongAfterUmBong(STOCK, i):
|
||||
# 어제 음봉 이후 장대양봉이었다면,
|
||||
status += 'YANGBONG_'
|
||||
|
||||
return status, buy_price
|
||||
|
||||
# 그래프 출력
|
||||
def analyzeToHtml(self, outPath):
|
||||
tmp_path = outPath + "/tmp"
|
||||
if os.path.isdir(tmp_path):
|
||||
os.rmdir(tmp_path)
|
||||
os.mkdir(tmp_path)
|
||||
|
||||
conn = sqlite3.connect(self.inFileName)
|
||||
cursor = conn.cursor()
|
||||
rowid = 1
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
while result != None:
|
||||
item_code = result[0]
|
||||
item_name = result[1]
|
||||
print("#html", rowid, item_name)
|
||||
|
||||
# 부실 기업은 매수하지 않고 그냥 넘긴다.
|
||||
# kospi 지수와 kosdak 지수도 그냥 넘긴다.
|
||||
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
|
||||
# 다음 종목을 가져옴
|
||||
cursor.execute('SELECT CODE, NAME, PRICE, STOCHASTIC FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
continue
|
||||
|
||||
result_3 = result[3]
|
||||
if result[3] != result[3]:
|
||||
result_3 = result[3].replace("NaN", "0")
|
||||
if result[3]==None:
|
||||
rowid += 1
|
||||
cursor.execute('SELECT CODE, NAME, PRICE, STOCHASTIC FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
continue
|
||||
|
||||
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)
|
||||
"""
|
||||
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
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return
|
||||
|
||||
def analyze(self):
|
||||
conn = sqlite3.connect(self.inFileName)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 기존 분석 데이터를 모두 지움
|
||||
cursor.execute('update ' + self.tableName + ' set STOCHASTIC = ""')
|
||||
|
||||
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])}
|
||||
|
||||
try:
|
||||
results_STOCHASTIC = self.stochastic.analyze(stock)
|
||||
text_STOCHASTIC = json.dumps(results_STOCHASTIC, ensure_ascii=False)
|
||||
except:
|
||||
print("#", rowid, stock['NAME'])
|
||||
rowid += 1
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
continue
|
||||
|
||||
cursor.execute("UPDATE " + self.tableName + " SET STOCHASTIC=? WHERE CODE=?", (text_STOCHASTIC, stock["CODE"]))
|
||||
print("#", rowid, stock['NAME'])
|
||||
rowid += 1
|
||||
cursor.execute('SELECT * FROM ' + self.tableName + ' WHERE rowid=?', (rowid,))
|
||||
result = cursor.fetchone()
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
start = time.time()
|
||||
PROJECT_HOME = "../.."
|
||||
inFileName = PROJECT_HOME + '/resources/stock.db'
|
||||
inFnguideFileName = PROJECT_HOME + '/resources/fnguide.db'
|
||||
analyzer = Analyzer(PROJECT_HOME, inFileName, inFnguideFileName)
|
||||
|
||||
# 분석 & update DB
|
||||
"""
|
||||
#print ("analyze Stochastic...")
|
||||
analyzer.analyzeStochastic()
|
||||
"""
|
||||
|
||||
###analyzer.analyze()
|
||||
|
||||
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.analyzeToHtml(outPath)
|
||||
|
||||
|
||||
# 파일 출력
|
||||
#print("print to File...")
|
||||
#outFileName = PROJECT_HOME + '/resources/analysis/'+day+'.json'
|
||||
#analyzer.analyzeToFile(outFileName)
|
||||
|
||||
print("time : %6.2f 초", (time.time() - start))
|
||||
|
||||
print("done...")
|
||||
54
stockpredictor/analysis/BolingerBand.py
Normal file
54
stockpredictor/analysis/BolingerBand.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import pandas as pd
|
||||
from stockpredictor.analysis.Common import Common
|
||||
import plotly.graph_objs as go
|
||||
from plotly import tools, subplots
|
||||
import plotly.io as po
|
||||
|
||||
class BolingerBand:
|
||||
|
||||
common = None
|
||||
|
||||
def __init__(self):
|
||||
self.common = Common()
|
||||
return
|
||||
|
||||
def apply(self, df, n=10, m=6, t=6):
|
||||
# 입력받은 값이 dataframe이라는 것을 정의해줌
|
||||
df = pd.DataFrame(df)
|
||||
|
||||
max20 = df["close"].rolling(window=20).mean()
|
||||
stddev = df["close"].rolling(window=20).std()
|
||||
upper = max20 + (stddev * 2) # 상단 볼리저 밴드
|
||||
lower = max20 - (stddev * 2) # 하단 볼리저 밴드
|
||||
middle = (upper + lower ) / 2
|
||||
|
||||
# dataframe에 컬럼 추가
|
||||
#df = df.assign(fast_k=fast_k, slow_k=slow_k, slow_d=slow_d).dropna()
|
||||
df = df.assign(upper=upper, middle=middle, lower=lower)
|
||||
|
||||
return df
|
||||
|
||||
def analyze(self, stock):
|
||||
df = pd.DataFrame()
|
||||
df = df.from_dict(stock['PRICE'])
|
||||
df = self.apply(df)
|
||||
|
||||
for i in range(len(df.upper)):
|
||||
stock['PRICE'][i]['upper'] = df.upper.values[i]
|
||||
stock['PRICE'][i]['middle'] = df.middle.values[i]
|
||||
stock['PRICE'][i]['lower'] = df.lower.values[i]
|
||||
|
||||
# 0: 중립, 1: 매수, -1: 매도
|
||||
stock['PRICE'][i]['bolingerband_buy'] = 0
|
||||
|
||||
if i > 0:
|
||||
stock['PRICE'][i]['bolingerband_buy'] = self.common.getBolingerBandScore(stock['PRICE'], i)
|
||||
|
||||
results = []
|
||||
for day in stock['PRICE']:
|
||||
results.append({'DATE': day['DATE'],
|
||||
'upper': day['upper'],
|
||||
'middle': day['middle'],
|
||||
'lower': day['lower'],
|
||||
'bolingerband_buy': day['bolingerband_buy']})
|
||||
return results
|
||||
@@ -89,6 +89,9 @@ class Common:
|
||||
|
||||
return score
|
||||
|
||||
def getBolingerBandScore(self, stock, i):
|
||||
return 0
|
||||
|
||||
def getIchimokuCloudScore(self, stock, i):
|
||||
score = 0
|
||||
|
||||
|
||||
@@ -1,364 +0,0 @@
|
||||
|
||||
class Common:
|
||||
|
||||
# 상향
|
||||
def checkUpward(self, type, data):
|
||||
check = True
|
||||
if type != None:
|
||||
for i in range(len(data)-1):
|
||||
# 만약 이전이 이후보다 크다면, 상승이 아님
|
||||
if data[i][type] > data[i+1][type]:
|
||||
check = False
|
||||
break
|
||||
else:
|
||||
for i in range(len(data)-1):
|
||||
# 만약 이전이 이후보다 크다면, 상승이 아님
|
||||
if data[i] > data[i+1]:
|
||||
check = False
|
||||
break
|
||||
return check
|
||||
|
||||
# 하향
|
||||
def checkDownward(self, type, data):
|
||||
check = True
|
||||
for i in range(len(data)-1):
|
||||
# 만약 이전이 이후보다 작다면, 하락이 아님
|
||||
if data[i][type] < data[i+1][type]:
|
||||
check = False
|
||||
break
|
||||
return check
|
||||
|
||||
# 상향 돌파
|
||||
def checkUpwardBreakthrough(self, type1, type2, data):
|
||||
if (type1 in data[0] and type1 in data[1] and type1 in data[2] and
|
||||
type2 in data[0] and type2 in data[1] and type2 in data[2]):
|
||||
|
||||
if ((data[0][type1] < data[1][type1] < data[2][type1]) and
|
||||
(data[0][type1] < data[0][type2] and data[2][type1] > data[2][type2])):
|
||||
return True
|
||||
return False
|
||||
|
||||
# 하향 돌파
|
||||
def checkDownwardBreakthrough(self, type1, type2, data):
|
||||
if (type1 in data[0] and type1 in data[1] and type1 in data[2] and
|
||||
type2 in data[0] and type2 in data[1] and type2 in data[2]):
|
||||
|
||||
if ((data[0][type1] > data[1][type1] > data[2][type1]) and
|
||||
(data[0][type1] > data[0][type2] and data[2][type1] < data[2][type2])):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def getStochasticScore(self, stock, i):
|
||||
score = 0
|
||||
|
||||
if (stock[i - 1]['slow_k'] < stock[i]['slow_k'] and
|
||||
stock[i]['slow_d'] < stock[i]['slow_k']):
|
||||
if stock[i]['slow_k'] < 5:
|
||||
score = 8
|
||||
elif 5 <= stock[i]['slow_k'] < 10:
|
||||
score = 7
|
||||
elif 10 <= stock[i]['slow_k'] < 15:
|
||||
score = 6
|
||||
elif 15 <= stock[i]['slow_k'] < 20:
|
||||
score = 5
|
||||
elif 20 <= stock[i]['slow_k'] < 30:
|
||||
score = 4
|
||||
elif 30 <= stock[i]['slow_k'] < 40:
|
||||
score = 3
|
||||
elif 40 <= stock[i]['slow_k'] < 50:
|
||||
score = 2
|
||||
else:
|
||||
score = 1
|
||||
|
||||
if (stock[i - 1]['slow_k'] > stock[i]['slow_k'] and
|
||||
stock[i - 1]['slow_k'] > stock[i - 1]['slow_d'] and
|
||||
stock[i]['slow_k'] < stock[i]['slow_d']):
|
||||
if stock[i]['slow_k'] > 90:
|
||||
score = -6
|
||||
elif 90 >= stock[i]['slow_k'] > 80:
|
||||
score = -5
|
||||
elif 80 >= stock[i]['slow_k'] > 70:
|
||||
score = -4
|
||||
elif 70 >= stock[i]['slow_k'] > 60:
|
||||
score = -3
|
||||
elif 60 >= stock[i]['slow_k'] > 50:
|
||||
score = -2
|
||||
else:
|
||||
score = -1
|
||||
|
||||
return score
|
||||
|
||||
def getIchimokuCloudScore(self, stock, i):
|
||||
score = 0
|
||||
|
||||
if stock[i - 1]['leadingSpan1'] != 0 and stock[i - 1]['leadingSpan2'] != 0:
|
||||
|
||||
# 후행스팬 > 선행스펜 일때, 후행스펜 > 어제 주가 > 선행스팬 이고, 오늘 주가 > 후행스팬 < 선행스팬 이라면, 매수 2점
|
||||
if (stock[i - 1]['leadingSpan2'] > stock[i - 1]['leadingSpan1'] and stock[i]['leadingSpan2'] > stock[i]['leadingSpan1']):
|
||||
if (stock[i - 1]['leadingSpan2'] > stock[i - 1]['close'] > stock[i - 1]['leadingSpan1'] and
|
||||
stock[i]['close'] > stock[i]['leadingSpan2'] > stock[i - 1]['leadingSpan1']):
|
||||
score = 2
|
||||
|
||||
# 후행스팬 > 선행스펜 일때, 후행스펜 > 선행스팬 > 어제 주가 이고, 오늘 주가 > 후행스팬 < 선행스팬 이라면, 매수 4점
|
||||
if (stock[i - 1]['leadingSpan2'] > stock[i - 1]['leadingSpan1'] and stock[i]['leadingSpan2'] > stock[i]['leadingSpan1']):
|
||||
if (stock[i - 1]['leadingSpan2'] > stock[i - 1]['leadingSpan1'] > stock[i - 1]['close'] and
|
||||
stock[i]['close'] > stock[i]['leadingSpan2'] > stock[i - 1]['leadingSpan1']):
|
||||
score = 4
|
||||
|
||||
# 선행스팬 > 후행스팬 일때, 선행스팬 > 어제 주가 > 후행스팬 이고, 오늘 주가 > 선행스팬 < 후행스팬 이라면, 매수 1점
|
||||
if (stock[i - 1]['leadingSpan1'] > stock[i - 1]['leadingSpan2'] and stock[i]['leadingSpan1'] > stock[i]['leadingSpan2']):
|
||||
if (stock[i - 1]['leadingSpan1'] > stock[i - 1]['close'] > stock[i - 1]['leadingSpan2'] and
|
||||
stock[i]['close'] > stock[i]['leadingSpan1'] > stock[i - 1]['leadingSpan2']):
|
||||
score = 1
|
||||
|
||||
# 선행스팬 > 후행스팬 일때, 선행스팬 > 후행스팬 > 어제 주가 이고, 오늘 주가 > 선행스팬 < 후행스팬 이라면, 매수 3점
|
||||
if (stock[i - 1]['leadingSpan1'] > stock[i - 1]['leadingSpan2'] and stock[i]['leadingSpan1'] > stock[i]['leadingSpan2']):
|
||||
if (stock[i - 1]['leadingSpan1'] > stock[i - 1]['leadingSpan2'] > stock[i - 1]['close'] and
|
||||
stock[i]['close'] > stock[i]['leadingSpan1'] > stock[i - 1]['leadingSpan2']):
|
||||
score = 3
|
||||
|
||||
# 어제는 주가가 선행이나 후행스팬 위에 있었지만, 오늘은 두 스팬 모두 아래로 내려왔을 때 매도
|
||||
if (stock[i - 1]['close'] > stock[i - 1]['leadingSpan1'] or stock[i - 1]['close'] > stock[i - 1]['leadingSpan2']):
|
||||
if (stock[i]['close'] < stock[i]['leadingSpan1'] and stock[i]['close'] < stock[i]['leadingSpan2']):
|
||||
score = -1
|
||||
|
||||
return score
|
||||
|
||||
def checkLongYangBongAfterUmBong(self, stock, i):
|
||||
if i > 0:
|
||||
if stock[i-1]['open'] > stock[i-1]['close']: # 어제가 음봉인지 체크
|
||||
if stock[i]['open'] < stock[i]['close'] and stock[i]['close'] == stock[i]['high']: # 오늘 장대양봉인지 체크
|
||||
if stock[i-1]['volume']*2 < stock[i]['volume']: # 어제 거래량 보다 두배 이상일 때
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkAllUpperCross(self, stock, i):
|
||||
if i > 10:
|
||||
if stock[i]['avg5'] < stock[i]['close'] and stock[i]['avg20'] < stock[i]['close'] and stock[i]['avg60'] < stock[i]['close'] and stock[i]['avg120'] < stock[i]['close']:
|
||||
for j in range(1, 6):
|
||||
if stock[i-j]['close'] < stock[i-j]['avg5'] and stock[i-j]['close'] < stock[i-j]['avg20'] and stock[i-j]['close'] < stock[i-j]['avg60'] and stock[i-j]['close'] < stock[i-j]['avg120']:
|
||||
return "ALLUPPER_"
|
||||
return ""
|
||||
|
||||
def check_golded_cross(self, stock, i):
|
||||
if i > 1:
|
||||
# 60 -> 120
|
||||
# 오늘 지수는 120 < 60 < 20 < 5
|
||||
# 어제 지수는 60 < 120 이었다.
|
||||
# 60, 20, 5일선 모두 어제 보다 오늘이 더 높다 (상승중)
|
||||
# 5일과 20일선은 상승 중이며, 60일선이 120일 선을 뚫고 올라온 순간인지 체크함 (삼성전자 2021-07-29)
|
||||
# 이때 바로 매수하지 않는다.
|
||||
# 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다.
|
||||
if stock[i]['avg120'] < stock[i]['avg60'] < stock[i]['avg20'] < stock[i]['avg5']:
|
||||
if stock[i-1]['avg120'] > stock[i-1]['avg60']:
|
||||
if (stock[i-1]['avg60'] < stock[i]['avg60'] and stock[i-1]['avg20'] < stock[i]['avg20'] and stock[i-1]['avg5'] < stock[i]['avg5']):
|
||||
return "GOLDEN#1_"
|
||||
|
||||
# 20 -> 120: 5일과 20일, 60일선은 상승 중이며, 20일선이 120일 선을 뚫고 올라온 순간인지 체크 (SK 2021-12-09, 나노스 2021-02-04)
|
||||
# 어제는 60일선 < 20일선 < 120일선 < 5일선이지만, 오늘은 60일선 < 120일선 < 20일선 < 5일선
|
||||
# 이때 바로 매수하지 않는다.
|
||||
# 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다.
|
||||
if stock[i]['avg60'] < stock[i]['avg120'] < stock[i]['avg20'] < stock[i]['avg5']:
|
||||
if stock[i-1]['avg60'] < stock[i-1]['avg20'] < stock[i]['avg120'] < stock[i]['avg5']:
|
||||
if (stock[i-1]['avg60'] < stock[i]['avg60'] and stock[i-1]['avg20'] < stock[i]['avg20'] and stock[i-1]['avg5'] < stock[i]['avg5']):
|
||||
return "GOLDEN#2_"
|
||||
|
||||
# 20 -> 120: 5일과 20일, 60일선은 상승 중이며, 20일선이 120일 선을 뚫고 올라온 순간인지 체크 (갤럭시아머니트리 2021-02-08)
|
||||
# 어제는 60일선 < 120일선 < 5일선 < 20일선이지만, 오늘은 60일선 < 120일선 < 20일선 < 5일선
|
||||
if stock[i]['avg60'] < stock[i]['avg120'] < stock[i]['avg20'] < stock[i]['avg5']:
|
||||
if stock[i-1]['avg60'] < stock[i-1]['avg20'] < stock[i]['avg120'] < stock[i]['avg5']:
|
||||
if (stock[i-1]['avg60'] < stock[i]['avg60'] and stock[i-1]['avg20'] < stock[i]['avg20'] and stock[i-1]['avg5'] < stock[i]['avg5']):
|
||||
return "GOLDEN#3_"
|
||||
|
||||
return ""
|
||||
|
||||
def check_bearmarket_buying(self, stock, stochastic, i):
|
||||
if i > 1:
|
||||
# 5일선 상승 시점 확인 (SK 2020년 3월 24일)
|
||||
# 어제는 5일선 < 20일선 < 120일선 < 60일선이며, 오늘은 20일선 < 120일선 < 60일선
|
||||
# 어제와 오늘 모두 20일, 60일, 120일선은 모두 하락이다.
|
||||
# 어제 종가보다 오늘 종가가 높고, 종가는 5일선 위에 올라왔다.
|
||||
# 오늘 slow_k는 30 이하이며, 어제는 slow_d가 높았지만, 오늘은 slow_k가 더 높음
|
||||
if (stock[i-1]['avg5'] < stock[i-1]['avg20'] < stock[i-1]['avg120'] < stock[i]['avg60']) and (stock[i]['avg20'] < stock[i-1]['avg120'] < stock[i]['avg60']):
|
||||
if stock[i]['avg120'] < stock[i-1]['avg120'] and stock[i]['avg60'] < stock[i-1]['avg60'] and stock[i]['avg20'] < stock[i-1]['avg20']:
|
||||
if stock[i-1]['close'] <= stock[i]['close'] and stock[i]['avg5'] <= stock[i]['close']:
|
||||
if (stochastic[i]['slow_k'] < 30 and (stochastic[i-1]['slow_k'] < stochastic[i-1]['slow_d'] and stochastic[i]['slow_d'] < stochastic[i]['slow_k'])):
|
||||
return "BEARMARKET#1_"
|
||||
|
||||
# 5일선 상승 시점 확인 (원풍물산 2020년 3월 24일, NHN한국사이버결제 2018년 11월 2일)
|
||||
# 어제는 5일선 < 20일선 < 60일선 < 120일선이며, 오늘은 20일선 < 60일선 < 120일선
|
||||
# 어제와 오늘 모두 20일, 60일, 120일선은 모두 하락이다.
|
||||
# 어제 종가보다 오늘 종가가 높고, 종가는 5일선 위에 올라왔다.
|
||||
# 오늘 slow_k는 30 이하이며, 어제는 slow_d가 높았지만, 오늘은 slow_k가 더 높음
|
||||
if (stock[i-1]['avg5'] < stock[i-1]['avg20'] < stock[i-1]['avg60'] < stock[i]['avg120']) and (stock[i]['avg20'] < stock[i-1]['avg60'] < stock[i]['avg120']):
|
||||
if stock[i]['avg120'] < stock[i-1]['avg120'] and stock[i]['avg60'] < stock[i-1]['avg60'] and stock[i]['avg20'] < stock[i-1]['avg20']:
|
||||
if stock[i-1]['close'] <= stock[i]['close'] and stock[i]['avg5'] <= stock[i]['close']:
|
||||
if (stochastic[i]['slow_k'] < 30 and (stochastic[i-1]['slow_k'] < stochastic[i-1]['slow_d'] and stochastic[i]['slow_d'] < stochastic[i]['slow_k'])):
|
||||
return "BEARMARKET#2_"
|
||||
return ""
|
||||
|
||||
def check_stochastic(self, stock, stochastic, i):
|
||||
if i > 2:
|
||||
# 스토케스틱이 15 이하인 경우
|
||||
# 어제보다 slow_k가 상승했고, 오늘 slow_k가 slow_d 위에 있는 경우,
|
||||
if stochastic[i]['slow_k'] < 15:
|
||||
if stochastic[i-1]['slow_k'] < stochastic[i]['slow_k'] and stochastic[i]['slow_d'] < stochastic[i]['slow_k']:
|
||||
return "STOCHASTIC_"
|
||||
return ""
|
||||
|
||||
def check_stochastic_buying(self, stock, stochastic, ichimoku, i):
|
||||
if i > 3:
|
||||
# 삼성전자 2020년 11월 4일
|
||||
# 어제는 slow_K가 Slow_d 아래였지만, 오늘은 slow_K가 Slow_d 보다 높다.
|
||||
# 에제의 slow_k는 20보다 작고, 오늘의 slow_K는 30보다 작다
|
||||
# 1일전이나, 2, 3일전의 종가가 일목균형표 내의 선행스팬1 아래 존재하며,오늘 고가는 선행스팬1 위에 존재한다.
|
||||
# 그저께 시가보다 어제의 시가가, 어제의 시가보다는 오늘의 시가가 높다.
|
||||
if (stochastic[i-1]['slow_k'] < stochastic[i-1]['slow_d'] and stochastic[i]['slow_d'] < stochastic[i]['slow_k']):
|
||||
if (stochastic[i - 1]['slow_k'] < 20 and stochastic[i]['slow_k'] < 30):
|
||||
if ((stock[i-3]['close'] < ichimoku[i-3]['leadingSpan1'] or stock[i-2]['close'] < ichimoku[i-2]['leadingSpan1'] or stock[i-1]['close'] < ichimoku[i-1]['leadingSpan1']) and ichimoku[i-1]['leadingSpan1'] < stock[i-1]['high']):
|
||||
if stock[i-2]['open'] < stock[i-1]['open'] < stock[i]['open']:
|
||||
return "STOCHASTIC#1_"
|
||||
|
||||
# 스토케스틱이 15 이하인 경우
|
||||
# 어제보다 slow_k가 상승했고, 오늘 slow_k가 slow_d 위에 있는 경우,
|
||||
# 오늘 종가가 5일선 위에 있는 경우
|
||||
if stochastic[i]['slow_k'] < 15:
|
||||
if stochastic[i - 1]['slow_k'] < stochastic[i]['slow_k'] and stochastic[i]['slow_d'] < stochastic[i]['slow_k']:
|
||||
if stock[i]['avg5'] < stock[i]['close']:
|
||||
return "STOCHASTIC#2_"
|
||||
return ""
|
||||
|
||||
def check_highest_270(self, stock, i):
|
||||
# 270일 기준으로 최고가를 기록하는 순간 매수를 시도한다.
|
||||
# https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_27
|
||||
upper_index = 0
|
||||
if len(stock) > 271:
|
||||
top = 0
|
||||
for idx in range(2, 271):
|
||||
# 최근 270일 중 최고가를 구한다.
|
||||
if top < stock[-idx]['close']:
|
||||
top = stock[-idx]['close']
|
||||
|
||||
if top < stock[i]['close']:
|
||||
return "highest_"
|
||||
return ""
|
||||
|
||||
def check_Dolpa_Jiji(self, stock, i, day='20'):
|
||||
upper_index = 0
|
||||
if len(stock) > 5:
|
||||
for idx in range(1, 5):
|
||||
# day선을 돌파하는 양봉이고, 종가가 최고가 보다 100 이내이어야 한다.
|
||||
if stock[-idx]['open'] < stock[-idx]["avg"+day] < stock[-idx]['close'] and stock[-idx]['high'] - 100 <= stock[-idx]['close']:
|
||||
upper_index = idx
|
||||
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 stock[i]['avg20'] < stock[i]['close'] and stock[i]['avg20'] < stock[i]['open']:
|
||||
if stock[i]['avg5'] < stock[i]['avg20']:
|
||||
index1 = -1
|
||||
for j in range(1, 61):
|
||||
if stock[i-j]['avg20'] < stock[i-j]['avg5']:
|
||||
index1 = j
|
||||
break
|
||||
top = 0
|
||||
for j in range(index1+1, 61):
|
||||
if stock[i - j]['open'] < stock[i - j]['close']:
|
||||
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
|
||||
return "5-20_"
|
||||
return ""
|
||||
|
||||
def check_Danta1(self, stock, i):
|
||||
"""
|
||||
어제 상한가 혹은 상승양봉이 나온다.
|
||||
오늘 상승 출발을 해야 하며 상승 음봉이 나온다
|
||||
- 어제 종가 = 어제 상한가 < 종가 < 시가 < 상한가
|
||||
https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_109
|
||||
|
||||
만약 다음날 시작초가가 오늘 종가보다 높게 상승으로 출발한다면 매수를 한다.
|
||||
손절가는 오늘 최저가이다.
|
||||
"""
|
||||
if stock[i-1]['open'] < stock[i-1]['close'] == stock[i-1]['high']:
|
||||
if stock[i-1]['close'] < stock[i]['close'] < stock[i]['open'] < stock[i]['high']:
|
||||
return "danta1_"
|
||||
return ""
|
||||
|
||||
def check_Danta2(self, stock, i):
|
||||
"""
|
||||
쐐기, 수렴, 깃대 패턴 확인
|
||||
# https://docs.google.com/presentation/d/1MVuaeRNljqLCdn4dPZmvVdtl2Ab09Zwg/edit#slide=id.gc7b796e645_0_144
|
||||
|
||||
상단 추세선을 돌파하면 매수를 한다.
|
||||
"""
|
||||
price_10 = round(stock[i]["close"] / 10)
|
||||
if stock[-i]["open"] < stock[-i]["close"]:
|
||||
top = stock[-i]["close"]
|
||||
bottom = stock[-i]["open"]
|
||||
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 ""
|
||||
|
||||
def check_RightArrange(self, stock, i):
|
||||
"""
|
||||
어제는 정배열이 아니었는데, 오늘은 정배열인 경우
|
||||
"""
|
||||
if len(stock) > 2:
|
||||
if (not (stock[i-1]["avg120"] < stock[i-1]["avg60"] < stock[i-1]["avg20"] < stock[i-1]["avg5"]) and
|
||||
(stock[i]["avg120"] < stock[i]["avg60"] < stock[i]["avg20"] < stock[i]["avg5"])):
|
||||
return "arrange_"
|
||||
return ""
|
||||
|
||||
def check_W1Rise(self, stock, i, limit):
|
||||
if len(stock) > 5:
|
||||
rate = round((stock[i]["close"] - stock[i-4]["close"]) / stock[i-4]["close"],2)
|
||||
if rate >= limit:
|
||||
return "1w("+str(rate)+")_"
|
||||
return ""
|
||||
|
||||
def check_D1Fall(self, stock, i, limit):
|
||||
if len(stock) > 2:
|
||||
# 1000, 900, (900 - 1000) / 900 = -0.111
|
||||
# 1000, 800, (800 - 1000) / 800 = -0.25
|
||||
rate = round((stock[i]["close"] - stock[i-1]["close"]) / stock[i-1]["close"], 2)
|
||||
if rate <= limit:
|
||||
return "1d("+str(rate)+")_"
|
||||
return ""
|
||||
2
stockpredictor/crawler/pandas/Crawler.py
Normal file
2
stockpredictor/crawler/pandas/Crawler.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# https://grand-unified-engine.tistory.com/21
|
||||
# https://github.com/FinanceData/FinanceDataReader
|
||||
Reference in New Issue
Block a user