This commit is contained in:
dosangyoon
2022-02-02 05:36:55 +09:00
parent 2d4f759ab6
commit 198169493b
15 changed files with 3260 additions and 315 deletions

View File

@@ -0,0 +1,712 @@
import json
import os
import time
import shutil
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
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.crawler.sQLite.MovingAverage import MovingAverage
class AnalyzerSqlite:
PROJECT_HOME = None
stochastic = None
bolingerBand = None
ichimokuCloud = None
common = None
stockFileName = None
fnguideFileName = None
analyzedFileName = None
moving_avg = None
fnguide = {}
def __init__(self, PROJECT_HOME, stockFileName, fnguideFileName):
self.PROJECT_HOME = PROJECT_HOME
self.stockFileName = stockFileName
self.fnguideFileName = fnguideFileName
self.common = Common()
self.stochastic = Stochastic()
self.bolingerBand = BolingerBand()
self.ichimokuCloud = IchimokuCloud()
return
def readFnguide(self, code):
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"
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()
business_profits, business_profits_ratio, debt_ratio, ROA, ROE, EPS, BPS, DPS, PER, PBR = [], [], [], [], [], [], [], [], [], []
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])
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}
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']))
avg60 = list(reversed(stock['avg60']))
avg120 = list(reversed(stock['avg120']))
avg240 = list(reversed(stock['avg240']))
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')
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='#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, avg60, avg120, avg240, bolinger_upper, bolinger_lower, changeLine, baseLine]
volume = go.Bar(x=ymd, y=volume, name="volume")
volume_data = [volume]
# 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=3, cols=1, subplot_titles=('차트', '거래량', 'Stochastic'))
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 stochastic_data:
fig.append_trace(trace, 3, 1)
fig.update_layout(height=1800, xaxis_rangeslider_visible=False)
return fig
def analyzeFinalScore(self, STOCK):
status = ""
if STOCK['volume'][0] > 100000 and STOCK['close'][0] > 1000:
# 거래량이 100만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94)
# 정배열 체크
temp_status = self.common.check_RightArrange(STOCK)
if temp_status != "":
status += temp_status
# 20일선 돌파
temp_status = self.common.check_Dolpa_Jiji(STOCK, '20')
if temp_status != "":
status += temp_status
# 60일선 돌파
temp_status = self.common.check_Dolpa_Jiji(STOCK, '60')
if temp_status != "":
status += temp_status
# 120일선 돌파
temp_status = self.common.check_Dolpa_Jiji(STOCK, '120')
if temp_status != "":
status += temp_status
# 240일선 돌파
temp_status = self.common.check_Dolpa_Jiji(STOCK, '240')
if temp_status != "":
status += temp_status
# 20일선 지지 매수가 추천
temp_status = self.common.check_Dolpa_Jiji_20(STOCK)
if temp_status != "":
status += temp_status
# 음봉인데 어제보다 종가가 더 높은 경우
# 이 경우 정배열 상태인지도 함께 체크를 한다.
higher_umbong_status = self.common.checkHigherUmbong(STOCK)
if higher_umbong_status != "":
status += higher_umbong_status
"""
# 단타 #1
temp_status = self.common.check_Danta1(STOCK)
if temp_status != "":
status += temp_status
# 단타 #2
temp_status = self.common.check_Danta2(STOCK)
if temp_status != "":
status += temp_status
all_upper_cross_status = self.common.checkAllUpperCross(STOCK)
if all_upper_cross_status != "":
status += all_upper_cross_status
# 1주일 동안 몇 10% 이상 오른 종목
W1Rise = self.common.check_W1Rise(STOCK, 0.1)
if W1Rise != "":
status += W1Rise
# 1일 동안 몇 10% 이상 내린 종목
W1Fall = self.common.check_D1Fall(STOCK, -0.1)
if W1Fall != "":
status += W1Fall
"""
# GOLDENCROSS#1은 바로 매수하지 않고, 이 시점 이후로 5일선이 20일선을 하방으로 뚫었다가 다시 20일선을 상방으로 뚫는 순간 매수를 시도한다.
# GOLDENCROSS#2은 바로 매수 가능
# GOLDENCROSS#3은 바로 매수 가능
golden_cross_status = self.common.check_golded_cross(STOCK)
if golden_cross_status != "":
status += golden_cross_status
"""
# BUYINGBEARMARKET#1은 바로 매수 가능
# BUYINGBEARMARKET#2은 바로 매수 가능
bearmarket_buying_status = self.common.check_bearmarket_buying(STOCK)
if bearmarket_buying_status != "":
status += bearmarket_buying_status
"""
# STOCHASTIC
stochastic_status = self.common.check_stochastic(STOCK)
if stochastic_status != "":
status += stochastic_status
# YANGBONG
"""
longYangBongAfterUmBong_status = self.common.checkLongYangBongAfterUmBong(STOCK)
# 어제 음봉 이후 장대양봉이었다면,
if longYangBongAfterUmBong_status != "":
status += longYangBongAfterUmBong_status
"""
# Doji
doji_status = self.common.checkDoji(STOCK)
# 하락 추세에서 도지가 나오면 매수
if doji_status != "":
status += doji_status
"""---------------------------------
# Gravestone
gravestone_status = self.common.checkGravestone(STOCK)
# 상승 추세에서 그레이브스톤이 나오면 매도
if gravestone_status != "":
status += gravestone_status
---------------------------------"""
"""
# Dragonfly
dragonfly_status = self.common.checkDragonfly(STOCK)
# 하락 추세에서 드레곤플라이가 나오면 매수
if dragonfly_status != "":
status += dragonfly_status
# Hammer
hammer_status = self.common.checkHammer(STOCK)
# 하락 추세에서 해머가 나오면 매수
if hammer_status != "":
status += hammer_status
"""
"""---------------------------------
# Hangingman
hangingman_status = self.common.checkHangingman(STOCK)
# 상승 추세에서 행잉맨이 나오면 매도
if hangingman_status != "":
status += hangingman_status
---------------------------------"""
"""
# 상승장악형 (Engulfing) - 다음 날도 양봉이라면 매수
engulfing_status = self.common.checkEngulfingHigh(STOCK)
# 하락 추세에서 상승장악형이 나오면 매수
if engulfing_status != "":
status += engulfing_status
"""
"""---------------------------------
# 하락장악형 (Engulfing)
engulfing_status = self.common.checkEngulfingLow(STOCK)
# 상승 추세에서 하락장악형이 나오면 매도
if engulfing_status != "":
status += engulfing_status
---------------------------------"""
"""
# 상승 포아형 (Harami)
harami_status = self.common.checkHaramiHigh(STOCK)
# 하락 추세에서 상승포아형이 나오면 매수
if harami_status != "":
status += harami_status
"""
"""---------------------------------
# 하락 포아형 (Harami)
harami_status = self.common.checkHaramiLow(STOCK)
# 상승 추세에서 하락포아형이 나오면 매도
if harami_status != "":
status += harami_status
---------------------------------"""
"""
# 관통형 (piercing)
piercing_status = self.common.checkPiercing(STOCK)
# 하락 추세에서 관통형이 나오면 매수
if piercing_status != "":
status += piercing_status
"""
"""---------------------------------
# 흑운형 (Dark-cloud)
darkcloud_status = self.common.checkDarkCloud(STOCK)
# 상승 추세에서 흑운형이 나오면 매도
if darkcloud_status != "":
status += darkcloud_status
---------------------------------"""
"""
# 샛별 (Morning start)
morningstar_status = self.common.checkMorningstar(STOCK)
# 하락 추세에서 샛별형이 나오면 매수
if morningstar_status != "":
status += morningstar_status
"""
"""---------------------------------
# 저녁별 (Evening start)
eveningstar_status = self.common.checkEveningstar(STOCK)
# 상승 추세에서 저녁별형이 나오면 매도
if eveningstar_status != "":
status += eveningstar_status
---------------------------------"""
return status
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("기준선 위 전환선")
self.makeDir("스토케스틱이 10 미만")
self.makeDir("bolingerband 하단 돌파")
self.makeDir("260일 위치 에너지가 10% 미만")
self.makeDir("260일 가격 반토막 이상")
self.makeDir("240일선 아래")
self.makeDir("240일선 돌파")
self.makeDir("20일선 돌파")
self.makeDir("60일선 돌파")
self.makeDir("거래량 5배 이상")
self.makeDir("정배열")
self.makeDir("GoldenCross")
return
def writeFile(self, type, CODE, NAME, stock, state):
fig = self.draw(stock)
title = "%s (%s), %d %s 차트" % (NAME, CODE, stock['close'][0], state)
fig['layout'].update(title=title)
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)
return
# 후보 찾기
def findCandidate(self, outPath):
self.makeDirectory(outPath)
stockTableName = 'stock'
stockAnalysisTableName = 'stock_analysis'
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)
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
sql = 'SELECT ymd, close, open, high, low, volume '
sql += ' FROM ' + stockTableName + ' where CODE=? order by ymd desc limit 260'
cursor.execute(sql, (CODE,))
prices = cursor.fetchall()
ymd_, close, open, high, low, volume = [], [], [], [], [], []
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])
sql = 'SELECT ymd, avg5, avg10, avg20, avg60, avg120, avg200, avg240, '
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 += ' FROM ' + stockAnalysisTableName + ' where CODE=? order by ymd desc limit 260'
cursor.execute(sql, (CODE,))
prices = cursor.fetchall()
cursor.close()
conn.close()
ymd = []
avg5, avg10, avg20, avg60, avg120, avg200, avg240 = [], [], [], [], [], [], []
bolingerband_upper, bolingerband_lower, bolingerband_middle = [], [], []
ichimokucloud_changeLine, ichimokucloud_baseLine, ichimokucloud_leadingSpan1, ichimokucloud_leadingSpan2 = [], [], [], []
stochastic_fast_k, stochastic_slow_k, stochastic_slow_d = [], [], []
for price in prices:
ymd.append(price[0])
avg5.append(price[1])
avg10.append(price[2])
avg20.append(price[3])
avg60.append(price[4])
avg120.append(price[5])
avg200.append(price[6])
avg240.append(price[7])
bolingerband_upper.append(price[8])
bolingerband_lower.append(price[8])
bolingerband_middle.append(price[10])
ichimokucloud_changeLine.append(price[11])
ichimokucloud_baseLine.append(price[12])
ichimokucloud_leadingSpan1.append(price[13])
ichimokucloud_leadingSpan2.append(price[14])
stochastic_fast_k.append(price[15])
stochastic_slow_k.append(price[16])
stochastic_slow_d.append(price[17])
stock = {
"ymd":ymd,
"close":close, "open":open, "high":high, "low":low, "volume":volume,
"avg5":avg5, "avg10":avg10, "avg20":avg20, "avg60":avg60, "avg120":avg120, "avg200":avg200, "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
}
stochastic_score = stochastic_slow_k[0]
if bolingerband_upper[0] == bolingerband_lower[0]:
bolingerband_score = 0
else:
bolingerband_score = round(((close[0]-bolingerband_lower[0])/(bolingerband_upper[0]-bolingerband_lower[0])), 2)
# 위치 에너지
positionalEnergy1, positionalEnergy2 = self.getPositionalEnergy(close)
if volume[0] > 100000 and close[0] > 1000:
# 종목 상태 체크 분석
state = self.analyzeFinalScore(stock)
if len(close) > 50:
if (ichimokucloud_changeLine[0] > ichimokucloud_baseLine[0] and
ichimokucloud_changeLine[1] < ichimokucloud_baseLine[1] and
ichimokucloud_changeLine[2] < ichimokucloud_baseLine[2]):
type = "기준선 위 전환선"
self.writeFile(type, CODE, NAME, stock, state)
# 스토케스틱이 10 미만
if len(close) > 5 and stochastic_score is not None and stochastic_score < 10:
type = "스토케스틱이 10 미만"
self.writeFile(type, CODE, NAME, stock, state)
# bolingerband 하단 돌파
if len(close) > 5 and bolingerband_score is not None and bolingerband_score < 0:
type = "bolingerband 하단 돌파"
self.writeFile(type, CODE, NAME, stock, state)
# 260일 위치 에너지가 10% 미만
if len(close) > 5 and positionalEnergy1 is not None and positionalEnergy1 < 0.1:
type = "260일 위치 에너지가 10% 미만"
self.writeFile(type, CODE, NAME, stock, state)
# 260일 가격 반토막 이상
if len(close) > 5 and positionalEnergy2 is not None and positionalEnergy2 < 0.5:
type = "260일 가격 반토막 이상"
self.writeFile(type, CODE, NAME, stock, state)
# 종가가 240일선 아래라면 매수한다.
if close[0] < avg240[0]:
type = "240일선 아래"
self.writeFile(type, CODE, NAME, stock, state)
# 종가가 240일선 돌파
if close[0] > avg240[0] and close[1] < avg240[1]:
type = "240일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
# 20일선 돌파
temp_status = self.common.check_Dolpa_Jiji(stock, '20')
if temp_status != "":
type = "20일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
# 60일선 돌파
temp_status = self.common.check_Dolpa_Jiji(stock, '60')
if temp_status != "":
type = "60일선 돌파"
self.writeFile(type, CODE, NAME, stock, state)
golden_cross_status = self.common.check_golded_cross(stock)
if golden_cross_status != "":
type = "GoldenCross"
self.writeFile(type, CODE, NAME, stock, state)
# 거래량 5배 이상
if volume[0] > volume[1]*5:
type = "거래량 5배 이상"
self.writeFile(type, CODE, NAME, stock, state)
right_arrange = self.common.check_RightArrange(stock)
if right_arrange != "":
type = "정배열"
self.writeFile(type, CODE, NAME, stock, state)
return
def get_moving_average(self, stock):
q_5 = MovingAverage(5)
q_10 = MovingAverage(10)
q_20 = MovingAverage(20)
q_60 = MovingAverage(60)
q_120 = MovingAverage(120)
q_200 = MovingAverage(200)
q_240 = MovingAverage(240)
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_60.enqueue(stock[i]['close'])
q_120.enqueue(stock[i]['close'])
q_200.enqueue(stock[i]['close'])
q_240.enqueue(stock[i]['close'])
stock[i]['avg5'] = q_5.avg()
stock[i]['avg10'] = q_10.avg()
stock[i]['avg20'] = q_20.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()
return
def analyze(self):
stockTableName = 'stock'
stockAnalysisTableName = 'stock_analysis'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
# 테이블 생성
cursor.execute("CREATE TABLE IF NOT EXISTS " + stockAnalysisTableName + " (CODE text, NAME text, ymd text, avg5 REAL, avg10 REAL, avg20 REAL, avg60 REAL, avg120 REAL, avg200 REAL, avg240 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)")
# 키 생성
create_key = "CREATE INDEX IF NOT EXISTS " + stockAnalysisTableName + "_idx on " + stockAnalysisTableName + " (CODE, ymd) "
cursor.execute(create_key)
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
items = cursor.fetchall()
cursor.close()
conn.close()
for rowid, item in enumerate(items):
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
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()
for item in items:
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,
"avg60": -1,
"avg120": -1,
"avg200": -1,
"avg240": -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})
# 이동 평균 계산
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)
for price in stock["PRICE"]:
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, avg5, avg10, avg20, avg60, avg120, avg200, avg240, "
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 += " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
cursor.execute(sql, (stock["CODE"], stock["NAME"], price['ymd'], price['avg5'], price['avg10'], price['avg20'], price['avg60'], price['avg120'], price['avg200'], price['avg240'],
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'],))
else:
break
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'
fnguideFileName = PROJECT_HOME + '/resources/fnguide.db'
analyzer = AnalyzerSqlite(PROJECT_HOME, stockFileName, fnguideFileName)
#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.findCandidate(outPath)
print("time : %6.2f" % (time.time() - start))
print("done...")

View File

@@ -12,18 +12,17 @@ class BolingerBand:
self.common = Common()
return
def apply(self, df, n=10, m=6, t=6):
def apply(self, df, n=20, t=2):
# 입력받은 값이 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) # 하단 볼리저 밴드
max20 = df["close"].rolling(window=n).mean()
stddev = df["close"].rolling(window=n).std()
upper = max20 + (stddev * t) # 상단 볼리저 밴드
lower = max20 - (stddev * t) # 하단 볼리저 밴드
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
@@ -34,21 +33,8 @@ class BolingerBand:
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]
stock['PRICE'][i]['bolingerband_upper'] = df.upper.values[i]
stock['PRICE'][i]['bolingerband_middle'] = df.middle.values[i]
stock['PRICE'][i]['bolingerband_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
return

View File

@@ -0,0 +1,560 @@
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 getBolingerBandScore(self, stock, i):
return 0
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
# YANGBONG
# 어제 음봉 이후 장대양봉이었다면, 매수
def checkLongYangBongAfterUmBong(self, stock, i):
if i > 0:
if stock[i-1]['close'] < stock[i-1]['open']: # 어제가 음봉인지 체크
if stock[i]['open'] < stock[i]['close'] and stock[i]['close'] == stock[i]['high']: # 오늘 장대양봉인지 체크
if stock[i-1]['volume']*2 < stock[i]['volume']: # 어제 거래량 보다 두배 이상일 때
return "UMYANG_"
return ""
def checkDoji(self, stock, i):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 도지인지 체크한다
if i > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i-2]['close'] < stock[i-2]['open'] and stock[i-1]['close'] < stock[i-1]['open']:
# 도지 체크
if stock[i]['open'] == stock[i]['close'] and stock[i]['low'] < stock[i]['close'] < stock[i]['high']:
return "DOJI_"
return ""
def checkGravestone(self, stock, i):
# 상승 추세이고, 어제 양봉이고, 오늘 그레이브스톤인지 체크한다
if i > 2:
# 상승 추세이고
if stock[i-2]['close'] < stock[i - 1]['close']:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
# 오늘 그레이브스톤인지 체크한다
if stock[i]['open'] == stock[i]['close'] == stock[i]['low'] and stock[i]['low'] < stock[i]['high']:
return "GRAVESTONE_"
return ""
# 하락 추세에서 드레곤플라이가 나오면 매수
def checkDragonfly(self, stock, i):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 드레곤플라이인지 체크한다
if i > 1:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 드레곤플라이인지 체크한다
if stock[i]['open'] == stock[i]['close'] == stock[i]['high'] and stock[i]['low'] < stock[i]['high']:
return "DRAGONEFLY_"
return ""
def checkHammer(self, stock, i):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 해머인지 체크한다
if i > 1:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 해머인지 체크한다
if stock[i]['open'] < stock[i]['close']:
if (stock[i]['close'] - stock[i]['open']) * 2 < stock[i]['open'] - stock[i]['low']:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['close'] < stock[i]['close'] - stock[i]['open']:
return "HAMMER_"
if stock[i]['close'] < stock[i]['open']:
if (stock[i]['open'] - stock[i]['close']) * 2 < stock[i]['close'] - stock[i]['low']:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['open'] < stock[i]['open'] - stock[i]['close']:
return "HAMMER_"
return ""
def checkHangingman(self, stock, i):
# 상승 추세이고, 어제 양봉이고, 오늘 행잉맨인지 체크한다
if i > 2:
# 상승 추세이고
if stock[i-2]['close'] < stock[i - 1]['close']:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
# 오늘 해머인지 체크한다
if stock[i]['open'] < stock[i]['close']:
if (stock[i]['close'] - stock[i]['open']) * 2 < stock[i]['open'] - stock[i]['low']:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['close'] < stock[i]['close'] - stock[i]['open']:
return "HANGINGMAN_"
if stock[i]['close'] < stock[i]['open']:
if (stock[i]['open'] - stock[i]['close']) * 2 < stock[i]['close'] - stock[i]['low']:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['open'] < stock[i]['open'] - stock[i]['close']:
return "HANGINGMAN_"
return ""
def checkEngulfingHigh(self, stock, i):
# 하락 추세에서 상승 장악형인지 체크
if i > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 상승장악형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i-1]['open'] < stock[i]['close'] and stock[i]['open'] < stock[i-1]['close']:
return "ENHIGH_"
return ""
def checkEngulfingLow(self, stock, i):
# 상승 추세에서 하락 장악형인지 체크
if i > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
# 오늘 하락장악형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['close'] < stock[i]['open'] and stock[i]['close'] < stock[i-1]['open']:
return "ENLOW_"
return ""
def checkHaramiHigh(self, stock, i):
# # 하락 추세에서 상승포아형인지 체크
if i > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 상승포아형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i-1]['close'] < stock[i]['low'] and stock[i]['high'] < stock[i-1]['open']:
return "HAHIGH_"
return ""
def checkHaramiLow(self, stock, i):
# 상승 추세에서 하락 포아형인지 체크
if i > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
# 오늘 하락포아형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['open'] < stock[i]['low'] and stock[i]['high'] < stock[i-1]['close']:
return "HALOW_"
return ""
def checkPiercing(self, stock, i):
# 하락 추세에서 관통형인지 체크
if i > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 관통형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i]['open'] < stock[i-1]['low'] and (stock[i-1]['close'] + stock[i-1]['open'])/2 < stock[i]['close'] < stock[i-1]['close']:
return "PIERCING_"
return ""
def checkDarkCloud(self, stock, i):
# 상승 추세에서 흑운형인지 체크
if i > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
# 오늘 흑운형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['high'] < stock[i]['open'] and stock[i-1]['open'] < stock[i]['close'] < (stock[i-1]['open'] + stock[i-1]['close'])/2:
return "DARKCLOUD_"
return ""
def checkMorningstar(self, stock, i):
# 하락 추세에서 샛별인지 체크
if i > 3:
# 하락 추세이고
if stock[i-1]['close'] < stock[i-2]['close']:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
# 오늘 샛별인지 체크
# 어제 갭 체크
if stock[i-1]['open'] < stock[i - 2]['close'] and stock[i-1]['close'] < stock[i - 2]['close']:
# 오늘 시가가 어제 종가보다 높으며 양봉
if stock[i-1]['close'] < stock[i]['open'] < stock[i]['close']:
return "MORNINGSTAR_"
return ""
def checkEveningstar(self, stock, i):
# 상승 추세에서 저녁별형인지 체크
if i > 3:
# 상승 추세이고
if stock[i-2]['close'] < stock[i-1]['close']:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
# 오늘 저녁별형인지 체크
# 어제 갭 체크
if stock[i-2]['close'] < stock[i-1]['open'] and stock[i-2]['close'] < stock[i-1]['close']:
# 오늘 시가가 어제 종가보다 낮으며 음봉
if stock[i]['close'] < stock[i-1]['open'] < stock[i-1]['close']:
return "EVENINGSTAR_"
return ""
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_Dolpa(self, stock, i, avg1, avg2):
upper_index = 0
if len(stock) > 2:
if stock[i-1]["avg"+avg1] < stock[i-1]["avg"+avg2] and stock[i]["avg"+avg1] > stock[i]["avg"+avg2]:
return avg1+"_"+avg2+"_"
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 checkHigherUmbong(self, stock, i):
# 음봉인데 어제보다 종가가 더 높은 경우
# 이 경우 정배열 상태인지도 함께 체크를 한다.
if len(stock) > 3:
# 어제는 거래량이 터진 양봉이다.
if stock[i-1]['open'] < stock[i-1]['close'] and 5*stock[i-2]['volume'] < stock[i-1]['volume']:
# 오늘은 음봉인데, 오늘 종가는 어제 시가보다는 높다
if stock[i]['close'] < stock[i]['open'] and stock[i-1]['open'] < stock[i]['close']:
return "HIGHERUMBONG_"
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 ""

View File

@@ -48,292 +48,212 @@ class Common:
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 getBolingerBandScore(self, stock, i):
return 0
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
# YANGBONG
# 어제 음봉 이후 장대양봉이었다면, 매수
def checkLongYangBongAfterUmBong(self, stock, i):
if i > 0:
if stock[i-1]['close'] < stock[i-1]['open']: # 어제가 음봉인지 체크
if stock[i]['open'] < stock[i]['close'] and stock[i]['close'] == stock[i]['high']: # 오늘 장대양봉인지 체크
if stock[i-1]['volume']*2 < stock[i]['volume']: # 어제 거래량 보다 두배 이상일 때
def checkLongYangBongAfterUmBong(self, stock):
if len(stock['close']) > 2:
if stock['close'][1] < stock['open'][1]: # 어제가 음봉인지 체크
if stock['open'][0] < stock['close'][0] and stock['close'][0] == stock['high'][0]: # 오늘 장대양봉인지 체크
if stock['volume'][1]*2 < stock['volume'][0]: # 어제 거래량 보다 두배 이상일 때
return "UMYANG_"
return ""
def checkDoji(self, stock, i):
def checkDoji(self, stock):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 도지인지 체크한다
if i > 2:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][2]:
# 그저께와 어제가 음봉인지 체크
if stock[i-2]['close'] < stock[i-2]['open'] and stock[i-1]['close'] < stock[i-1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 도지 체크
if stock[i]['open'] == stock[i]['close'] and stock[i]['low'] < stock[i]['close'] < stock[i]['high']:
if stock['open'][0] == stock['close'][0] and stock['low'][0] < stock['close'][0] < stock['high'][0]:
return "DOJI_"
return ""
def checkGravestone(self, stock, i):
def checkGravestone(self, stock):
# 상승 추세이고, 어제 양봉이고, 오늘 그레이브스톤인지 체크한다
if i > 2:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i-2]['close'] < stock[i - 1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 그레이브스톤인지 체크한다
if stock[i]['open'] == stock[i]['close'] == stock[i]['low'] and stock[i]['low'] < stock[i]['high']:
if stock['open'][0] == stock['close'][0] == stock['low'][0] and stock['low'][0] < stock['high'][0]:
return "GRAVESTONE_"
return ""
# 하락 추세에서 드레곤플라이가 나오면 매수
def checkDragonfly(self, stock, i):
def checkDragonfly(self, stock):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 드레곤플라이인지 체크한다
if i > 1:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][1]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 오늘 드레곤플라이인지 체크한다
if stock[i]['open'] == stock[i]['close'] == stock[i]['high'] and stock[i]['low'] < stock[i]['high']:
if stock['open'][0] == stock['close'][0] == stock['high'][0] and stock['low'][0] < stock['high'][0]:
return "DRAGONEFLY_"
return ""
def checkHammer(self, stock, i):
def checkHammer(self, stock):
# 하락 추세이고, 그저께, 어제 음봉이고, 오늘 해머인지 체크한다
if i > 1:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][1]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock[1]['close'] < stock[1]['open']:
# 오늘 해머인지 체크한다
if stock[i]['open'] < stock[i]['close']:
if (stock[i]['close'] - stock[i]['open']) * 2 < stock[i]['open'] - stock[i]['low']:
if stock['open'][0] < stock['close'][0]:
if (stock['close'][0] - stock['open'][0]) * 2 < stock['open'][0] - stock['low'][0]:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['close'] < stock[i]['close'] - stock[i]['open']:
if stock['high'][0] - stock['close'][0] < stock['close'][0] - stock['open'][0]:
return "HAMMER_"
if stock[i]['close'] < stock[i]['open']:
if (stock[i]['open'] - stock[i]['close']) * 2 < stock[i]['close'] - stock[i]['low']:
if stock['close'][0] < stock['open'][0]:
if (stock['open'][0] - stock['close'][0]) * 2 < stock['close'][0] - stock['low'][0]:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['open'] < stock[i]['open'] - stock[i]['close']:
if stock['high'][0] - stock['open'][0] < stock['open'][0] - stock['close'][0]:
return "HAMMER_"
return ""
def checkHangingman(self, stock, i):
def checkHangingman(self, stock):
# 상승 추세이고, 어제 양봉이고, 오늘 행잉맨인지 체크한다
if i > 2:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i-2]['close'] < stock[i - 1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 해머인지 체크한다
if stock[i]['open'] < stock[i]['close']:
if (stock[i]['close'] - stock[i]['open']) * 2 < stock[i]['open'] - stock[i]['low']:
if stock['open'][0] < stock['close'][0]:
if (stock['close'][0] - stock['open'][0]) * 2 < stock['open'][0] - stock['low'][0]:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['close'] < stock[i]['close'] - stock[i]['open']:
if stock['high'][0] - stock['close'][0] < stock['close'][0] - stock['open'][0]:
return "HANGINGMAN_"
if stock[i]['close'] < stock[i]['open']:
if (stock[i]['open'] - stock[i]['close']) * 2 < stock[i]['close'] - stock[i]['low']:
if stock['close'][0] < stock['open'][0]:
if (stock['open'][0] - stock['close'][0]) * 2 < stock['close'][0] - stock['low'][0]:
# 윗꼬리가 몸통보다 짧아야 한다.
if stock[i]['high'] - stock[i]['open'] < stock[i]['open'] - stock[i]['close']:
if stock['high'][0] - stock['open'][0] < stock['open'][0] - stock['close'][0]:
return "HANGINGMAN_"
return ""
def checkEngulfingHigh(self, stock, i):
def checkEngulfingHigh(self, stock):
# 하락 추세에서 상승 장악형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][2]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 오늘 상승장악형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i-1]['open'] < stock[i]['close'] and stock[i]['open'] < stock[i-1]['close']:
if stock['open'][0] < stock['close'][0]:
if stock['open'][1] < stock['close'][0] and stock['open'][0] < stock['close'][1]:
return "ENHIGH_"
return ""
def checkEngulfingLow(self, stock, i):
def checkEngulfingLow(self, stock):
# 상승 추세에서 하락 장악형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 하락장악형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['close'] < stock[i]['open'] and stock[i]['close'] < stock[i-1]['open']:
if stock['close'][0] < stock['open'][0]:
if stock['close'][1] < stock['open'][0] and stock['close'][0] < stock['open'][1]:
return "ENLOW_"
return ""
def checkHaramiHigh(self, stock, i):
def checkHaramiHigh(self, stock):
# # 하락 추세에서 상승포아형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][2]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 오늘 상승포아형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i-1]['close'] < stock[i]['low'] and stock[i]['high'] < stock[i-1]['open']:
if stock['open'][0] < stock['close'][0]:
if stock['close'][1] < stock['low'][0] and stock['high'][0] < stock['open'][1]:
return "HAHIGH_"
return ""
def checkHaramiLow(self, stock, i):
def checkHaramiLow(self, stock):
# 상승 추세에서 하락 포아형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 하락포아형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['open'] < stock[i]['low'] and stock[i]['high'] < stock[i-1]['close']:
if stock['close'][0] < stock['open'][0]:
if stock['open'][1] < stock['low'][0] and stock['high'][0] < stock['close'][1]:
return "HALOW_"
return ""
def checkPiercing(self, stock, i):
def checkPiercing(self, stock):
# 하락 추세에서 관통형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i - 1]['close'] < stock[i - 2]['close']:
if stock['close'][1] < stock['close'][2]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 오늘 관통형인지 체크
if stock[i]['open'] < stock[i]['close']:
if stock[i]['open'] < stock[i-1]['low'] and (stock[i-1]['close'] + stock[i-1]['open'])/2 < stock[i]['close'] < stock[i-1]['close']:
if stock['open'][0] < stock['close'][0]:
if stock['open'][0] < stock['low'][1] and (stock['close'][1] + stock['open'][1])/2 < stock['close'][0] < stock['close'][1]:
return "PIERCING_"
return ""
def checkDarkCloud(self, stock, i):
def checkDarkCloud(self, stock):
# 상승 추세에서 흑운형인지 체크
if i > 2:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i - 2]['close'] < stock[i - 1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i - 1]['open'] < stock[i - 1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 흑운형인지 체크
if stock[i]['close'] < stock[i]['open']:
if stock[i-1]['high'] < stock[i]['open'] and stock[i-1]['open'] < stock[i]['close'] < (stock[i-1]['open'] + stock[i-1]['close'])/2:
if stock['close'][0] < stock['open'][0]:
if stock['high'][1] < stock['open'][0] and stock['open'][1] < stock['close'][0] < (stock['open'][1] + stock['close'][1])/2:
return "DARKCLOUD_"
return ""
def checkMorningstar(self, stock, i):
def checkMorningstar(self, stock):
# 하락 추세에서 샛별인지 체크
if i > 3:
if len(stock['close']) > 2:
# 하락 추세이고
if stock[i-1]['close'] < stock[i-2]['close']:
if stock['close'][1] < stock['close'][2]:
# 그저께와 어제가 음봉인지 체크
if stock[i - 2]['close'] < stock[i - 2]['open'] and stock[i - 1]['close'] < stock[i - 1]['open']:
if stock['close'][2] < stock['open'][2] and stock['close'][1] < stock['open'][1]:
# 오늘 샛별인지 체크
# 어제 갭 체크
if stock[i-1]['open'] < stock[i - 2]['close'] and stock[i-1]['close'] < stock[i - 2]['close']:
if stock['open'][1] < stock['close'][2] and stock['close'][1] < stock['close'][2]:
# 오늘 시가가 어제 종가보다 높으며 양봉
if stock[i-1]['close'] < stock[i]['open'] < stock[i]['close']:
if stock['close'][1] < stock['open'][0] < stock['close'][0]:
return "MORNINGSTAR_"
return ""
def checkEveningstar(self, stock, i):
def checkEveningstar(self, stock):
# 상승 추세에서 저녁별형인지 체크
if i > 3:
if len(stock['close']) > 2:
# 상승 추세이고
if stock[i-2]['close'] < stock[i-1]['close']:
if stock['close'][2] < stock['close'][1]:
# 어제 양봉인지 체크
if stock[i-1]['open'] < stock[i-1]['close']:
if stock['open'][1] < stock['close'][1]:
# 오늘 저녁별형인지 체크
# 어제 갭 체크
if stock[i-2]['close'] < stock[i-1]['open'] and stock[i-2]['close'] < stock[i-1]['close']:
if stock['close'][2] < stock['open'][1] and stock['close'][2] < stock['close'][1]:
# 오늘 시가가 어제 종가보다 낮으며 음봉
if stock[i]['close'] < stock[i-1]['open'] < stock[i-1]['close']:
if stock['close'][0] < stock['open'][1] < stock['close'][1]:
return "EVENINGSTAR_"
return ""
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']:
def checkAllUpperCross(self, stock):
if len(stock['close']) > 10:
if stock['avg5'][0] < stock['close'][0] and stock['avg20'][0] < stock['close'][0] and stock['avg60'][0] < stock['close'][0] and stock['avg120'][0] < stock['close'][0]:
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']:
if stock['close'][j] < stock['avg5'][j] and stock['close'][j] < stock['avg20'][j] and stock['close'][j] < stock['avg60'][j] and stock['close'][j] < stock['avg120'][j]:
return "ALLUPPER_"
return ""
def check_golded_cross(self, stock, i):
if i > 1:
def check_golded_cross(self, stock):
if len(stock['close']) > 1:
# 60 -> 120
# 오늘 지수는 120 < 60 < 20 < 5
# 어제 지수는 60 < 120 이었다.
@@ -341,40 +261,40 @@ class Common:
# 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']):
if stock['avg120'][0] < stock['avg60'][0] < stock['avg20'][0] < stock['avg5'][0]:
if stock['avg120'][1] > stock['avg60'][1]:
if (stock['avg60'][1] < stock['avg60'][0] and stock['avg20'][1] < stock['avg20'][0] and stock['avg5'][1] < stock['avg5'][0]):
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']):
if stock['avg60'][0] < stock['avg120'][0] < stock['avg20'][0] < stock['avg5'][0]:
if stock['avg60'][1] < stock['avg20'][1] < stock['avg120'][0] < stock['avg5'][0]:
if (stock['avg60'][1] < stock['avg60'][0] and stock['avg20'][1] < stock['avg20'][0] and stock['avg5'][1] < stock['avg5'][0]):
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']):
if stock['avg60'][0] < stock['avg120'][0] < stock['avg20'][0] < stock['avg5'][0]:
if stock['avg60'][1] < stock['avg20'][1] < stock['avg120'][0] < stock['avg5'][0]:
if (stock['avg60'][1] < stock['avg60'][0] and stock['avg20'][1] < stock['avg20'][0] and stock['avg5'][1] < stock['avg5'][0]):
return "GOLDEN#3_"
return ""
def check_bearmarket_buying(self, stock, stochastic, i):
if i > 1:
def check_bearmarket_buying(self, stock):
if len(stock['close']) > 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'])):
if (stock['avg5'][1] < stock['avg20'][1] < stock['avg120'][1] < stock['avg60'][0]) and (stock['avg20'][0] < stock['avg120'][1] < stock['avg60'][0]):
if stock['avg120'][0] < stock['avg120'][1] and stock['avg60'][0] < stock['avg60'][1] and stock['avg20'][0] < stock['avg20'][1]:
if stock['close'][1] <= stock['close'][0] and stock['avg5'][0] <= stock['close'][0]:
if (stock['stochastic_slow_k'][0] < 30 and (stock['stochastic_slow_k'][1] < stock['stochastic_slow_d'][1] and stock['stochastic_slow_d'][0] < stock['stochastic_slow_k'][0])):
return "BEARMARKET#1_"
# 5일선 상승 시점 확인 (원풍물산 2020년 3월 24일, NHN한국사이버결제 2018년 11월 2일)
@@ -382,24 +302,24 @@ class Common:
# 어제와 오늘 모두 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'])):
if (stock['avg5'][1] < stock['avg20'][1] < stock['avg60'][1] < stock['avg120'][0]) and (stock['avg20'][0] < stock['avg60'][1] < stock['avg120'][0]):
if stock['avg120'][0] < stock['avg120'][1] and stock['avg60'][0] < stock['avg60'][1] and stock['avg20'][0] < stock['avg20'][1]:
if stock['close'][1] <= stock['close'][0] and stock['avg5'][0] <= stock['close'][0]:
if (stock['stochastic_slow_k'][0] < 30 and (stock['stochastic_slow_k'][1] < stock['stochastic_slow_d'][1] and stock['stochastic_slow_d'][0] < stock['stochastic_slow_k'][0])):
return "BEARMARKET#2_"
return ""
def check_stochastic(self, stock, stochastic, i):
if i > 2:
def check_stochastic(self, stock):
if len(stock['close']) > 60:
# 스토케스틱이 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']:
if stock['stochastic_slow_k'][0] < 15:
if stock['stochastic_slow_k'][1] < stock['stochastic_slow_k'][0] and stock['stochastic_slow_d'][0] < stock['stochastic_slow_k'][0]:
return "STOCHASTIC_"
return ""
def check_stochastic_buying(self, stock, stochastic, ichimoku, i):
if i > 3:
if len(stock['close']) > 60:
# 삼성전자 2020년 11월 4일
# 어제는 slow_K가 Slow_d 아래였지만, 오늘은 slow_K가 Slow_d 보다 높다.
# 에제의 slow_k는 20보다 작고, 오늘의 slow_K는 30보다 작다
@@ -422,29 +342,29 @@ class Common:
def check_Dolpa(self, stock, i, avg1, avg2):
upper_index = 0
if len(stock) > 2:
if len(stock['close']) > 2:
if stock[i-1]["avg"+avg1] < stock[i-1]["avg"+avg2] and stock[i]["avg"+avg1] > stock[i]["avg"+avg2]:
return avg1+"_"+avg2+"_"
return ""
def check_Dolpa_Jiji(self, stock, i, day='20'):
def check_Dolpa_Jiji(self, stock, day='20'):
upper_index = 0
if len(stock) > 5:
if len(stock['close']) > 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']:
if stock['open'][idx] < stock["avg"+day][idx] < stock['close'][idx] and stock['high'][idx] - 100 <= stock['close'][idx]:
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['close'][upper_index] <= stock['open'][cidx] and stock['open'][cidx] < stock['close'][cidx]:
# 해당 기준일 선은 상승이어야 한다.
if stock[-upper_index]['avg'+day] < stock[-cidx]['avg'+day]:
if stock['avg'+day][upper_index] < stock['avg'+day][cidx]:
return day + "_"
return ""
def check_Dolpa_Jiji_20(self, stock, i):
def check_Dolpa_Jiji_20(self, stock):
"""
top: 이전 5일선이 20일선 위에 있을 때 최고가
top일 체크 사항 (20일 < 5일선)
@@ -452,28 +372,28 @@ class Common:
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']:
if len(stock['close']) > 61:
if stock['avg20'][0] < stock['close'][0] and stock['avg20'][0] < stock['open'][0]:
if stock['avg5'][0] < stock['avg20'][0]:
index1 = -1
for j in range(1, 61):
if stock[i-j]['avg20'] < stock[i-j]['avg5']:
if stock['avg20'][j] < stock['avg5'][j]:
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']
if stock['open'][j] < stock['close'][j]:
if top < stock['close'][j]:
top = stock['close'][j]
else:
if top < stock[i - j]['open']:
top = stock[i - j]['open']
if stock[i-j]['avg5'] < stock[i-j]['avg20']:
if top < stock['open'][j]:
top = stock['open'][j]
if stock['avg5'][j] < stock['avg20'][j]:
break
return "5-20_"
return ""
def check_Danta1(self, stock, i):
def check_Danta1(self, stock):
"""
어제 상한가 혹은 상승양봉이 나온다.
오늘 상승 출발을 해야 하며 상승 음봉이 나온다
@@ -483,78 +403,79 @@ class Common:
만약 다음날 시작초가가 오늘 종가보다 높게 상승으로 출발한다면 매수를 한다.
손절가는 오늘 최저가이다.
"""
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']:
if stock['open'][1] < stock['close'][1] == stock['high'][1]:
if stock['close'][1] < stock['close'][0] < stock['open'][0] < stock['high'][0]:
return "danta1_"
return ""
def check_Danta2(self, stock, i):
def check_Danta2(self, stock):
"""
쐐기, 수렴, 깃대 패턴 확인
# 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"]
price_10 = round(stock["close"][0] / 10)
if stock["open"][0] < stock["close"][0]:
top = stock["close"][0]
bottom = stock["open"][0]
else:
top = stock[-i]["open"]
bottom = stock[-i]["close"]
top = stock["open"][0]
bottom = stock["close"][0]
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"]
if stock["open"][i] < stock["close"][i]:
if top < stock["close"][i]:
top = stock["close"][i]
if stock["open"][i] < bottom:
bottom = stock["open"][i]
else:
if top < stock[-i]["open"]:
top = stock[-i]["open"]
if stock[-i]["close"] < bottom:
bottom = stock[-i]["close"]
if top < stock["open"][i]:
top = stock["open"][i]
if stock["close"][i] < bottom:
bottom = stock["close"][i]
if top - bottom < price_10:
return "danta2_"
return ""
def check_RightArrange(self, stock, i):
def check_RightArrange(self, stock):
"""
어제는 정배열이 아니었는데, 오늘은 정배열인 경우
"""
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"]):
if len(stock['close']) > 2:
if (not (stock["avg120"][1] < stock["avg60"][1] < stock["avg20"][1] < stock["avg5"][1] < stock["close"][1]) and
stock["avg120"][0] < stock["avg60"][0] < stock["avg20"][0] < stock["avg5"][0] < stock["close"][0]):
return "arrange_"
return ""
def checkHigherUmbong(self, stock, i):
def checkHigherUmbong(self, stock):
# 음봉인데 어제보다 종가가 더 높은 경우
# 이 경우 정배열 상태인지도 함께 체크를 한다.
if len(stock) > 3:
if len(stock['close']) > 3:
# 어제는 거래량이 터진 양봉이다.
if stock[i-1]['open'] < stock[i-1]['close'] and 5*stock[i-2]['volume'] < stock[i-1]['volume']:
if stock['open'][1] < stock['close'][1] and 5*stock['volume'][2] < stock['volume'][1]:
# 오늘은 음봉인데, 오늘 종가는 어제 시가보다는 높다
if stock[i]['close'] < stock[i]['open'] and stock[i-1]['open'] < stock[i]['close']:
if stock['close'][0] < stock['open'][0] and stock['open'][1] < stock['close'][0]:
return "HIGHERUMBONG_"
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)
def check_W1Rise(self, stock, limit):
if len(stock['close']) > 5:
rate = round((stock["close"][0] - stock["close"][4]) / stock["close"][4],2)
if rate >= limit:
return "1w("+str(rate)+")_"
return ""
def check_D1Fall(self, stock, i, limit):
if len(stock) > 2:
def check_D1Fall(self, stock, limit):
if len(stock['close']) > 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)
rate = round((stock["close"][0] - stock["close"][1]) / stock["close"][1], 2)
if rate <= limit:
return "1d("+str(rate)+")_"
return ""

View File

@@ -93,34 +93,24 @@ class IchimokuCloud:
df = self.apply(df)
diff = len(df.changeLine) - len(stock['PRICE'])
lastDay = stock['PRICE'][len(stock['PRICE']) - 1]['DATE']
tmpLastDay = datetime.datetime.strptime(lastDay, "%Y-%m-%d")
"""
lastDay = stock['PRICE'][len(stock['PRICE']) - 1]['ymd']
tmpLastDay = datetime.datetime.strptime(lastDay, "%Y.%m.%d")
for i in range(diff):
nextDay = tmpLastDay + datetime.timedelta(days=(i + 1))
stock['PRICE'].append(
{"DATE": nextDay.strftime("%Y-%m-%d"), "close": 0, "diff": 0, "open": 0, "high": 0, "low": 0, "volume": 0,
{"ymd": nextDay.strftime("%Y-%m-%d"), "close": 0, "diff": 0, "open": 0, "high": 0, "low": 0, "volume": 0,
"avg3": 0, "avg5": 0, "avg7": 0, "avg10": 0, "avg20": 0, "avg30": 0, "avg60": 0, "avg90": 0, "avg100": 0,
"avg120": 0, "avg150": 0, "avg180": 0, "avg200": 0, "avg240": 0})
"""
for i in range(len(df.changeLine)):
stock['PRICE'][i]['ichimoku_buy'] = 0
stock['PRICE'][i]['changeLine'] = df.changeLine.values[i]
stock['PRICE'][i]['baseLine'] = df.baseLine.values[i]
stock['PRICE'][i]['leadingSpan1'] = df.leadingSpan1.values[i]
stock['PRICE'][i]['leadingSpan2'] = df.leadingSpan2.values[i]
for i in range(len(df.changeLine)-diff):
stock['PRICE'][i]['ichimokucloud_changeLine'] = df.changeLine.values[i]
stock['PRICE'][i]['ichimokucloud_baseLine'] = df.baseLine.values[i]
stock['PRICE'][i]['ichimokucloud_leadingSpan1'] = df.leadingSpan1.values[i]
stock['PRICE'][i]['ichimokucloud_leadingSpan2'] = df.leadingSpan2.values[i]
for i in range(len(df.changeLine)):
stock['PRICE'][i]['ichimoku_buy'] = self.common.getIchimokuCloudScore(stock['PRICE'], i)
results = []
for day in stock['PRICE']:
results.append({'DATE': day['DATE'],
'changeLine': day['changeLine'],
'baseLine': day['baseLine'],
'leadingSpan1': day['leadingSpan1'],
'leadingSpan2': day['leadingSpan2'],
'ichimoku_buy': day['ichimoku_buy']})
return results
return
if __name__ == "__main__":

View File

@@ -15,7 +15,9 @@ class Stochastic:
# 일자(n,m,t)에 따른 Stochastic(KDJ)의 값을 구하기 위해 함수형태로 만듬
# n=15 (%k), m=5 (%d), t=3
def apply(self, df, n=5, m=3, t=3):
# n=5 (%k), m=3 (%d), t=3
# n=14 (%k), m=3 (%d), t=3
def apply(self, df, n=14, m=3, t=3):
# 입력받은 값이 dataframe이라는 것을 정의해줌
df = pd.DataFrame(df)
@@ -130,31 +132,16 @@ class Stochastic:
df = self.apply(df)
for i in range(len(df.fast_k)):
stock['PRICE'][i]['stochastic_buy'] = 0
if "fast_k" not in stock['PRICE'][i]:
stock['PRICE'][i]['fast_k'] = -1
stock['PRICE'][i]['slow_k'] = -1
stock['PRICE'][i]['slow_d'] = -1
if "stochastic_fast_k" not in stock['PRICE'][i]:
stock['PRICE'][i]['stochastic_fast_k'] = -1
stock['PRICE'][i]['stochastic_slow_k'] = -1
stock['PRICE'][i]['stochastic_slow_d'] = -1
stock['PRICE'][i]['fast_k'] = df.fast_k.values[i]
stock['PRICE'][i]['slow_k'] = df.slow_k.values[i]
stock['PRICE'][i]['slow_d'] = df.slow_d.values[i]
stock['PRICE'][i]['stochastic_fast_k'] = df.fast_k.values[i]
stock['PRICE'][i]['stochastic_slow_k'] = df.slow_k.values[i]
stock['PRICE'][i]['stochastic_slow_d'] = df.slow_d.values[i]
# 0: 중립, 1: 매수, -1: 매도
stock['PRICE'][i]['stochastic_buy'] = 0
if i > 0:
if ('slow_k' in stock['PRICE'][i-1] and 'slow_k' in stock['PRICE'][i]):
stock['PRICE'][i]['stochastic_buy'] = self.common.getStochasticScore(stock['PRICE'], i)
results = []
for day in stock['PRICE']:
results.append({'DATE': day['DATE'],
'fast_k': day['fast_k'],
'slow_k': day['slow_k'],
'slow_d': day['slow_d'],
'stochastic_buy': day['stochastic_buy']})
return results
return
if __name__ == "__main__":
stochastic = Stochastic()