Files
DeepStock/hts/BuySellChecker.py
dosang.yoon 1fbacc472a init
2022-07-09 22:15:08 +09:00

363 lines
16 KiB
Python

import math
import pandas as pd
from stockpredictor.analysis.Common import Common
from stockpredictor.analysis.Stochastic import Stochastic
from stockpredictor.analysis.RSI import RSI
from stockpredictor.analysis.MACD import MACD
from stockpredictor.analysis.IchimokuCloud import IchimokuCloud
class BuySellChecker:
common = None
stochastic = None
rsi = None
ichimokuCloud = None
def __init__(self):
self.common = Common()
self.stochastic = Stochastic()
self.rsi = RSI()
self.macd = MACD()
self.ichimokuCloud = IchimokuCloud()
return
def getPriceAndWeight1(self, data, i):
buy, weight, sell = -1, -1, -1
if i >= 3:
################
### sell 분석 ###
################
# 1. 볼린져밴드 상단이 최고와 종가 사이 아래에 있는 경우 매도한다.
#if (data["high"][i] - data["close"][i]) / 2 + data["close"][i] > data["upper"][i]:
# sell = data["high"][i]
# 2. slow_k가 90이 넘으면 매도한다.
if data["slow_k"][i] > 90:
sell = data["high"][i]
#if data["slow_k"][i] >= 85:
# if data["slow_d"][i-1] < data["slow_k"][i-1] and data["slow_k"][i] < data["slow_d"][i]:
# sell = data["high"][i]
# 3. 2시 이후에는 최고가가 볼린져밴드 상단 위에 있으면 매도한다.
if i > 300 and data["high"][i] > data["upper"][i]:
sell = data["high"][i]
##########################
### buy 분석 ###
##########################
if data["low"][i] < data["lower"][i] + 5 and data["open"][i] <= data["close"][i]:
if data["slow_k"][i-1] < 30 and data["slow_k"][i] < 30:
if data["slow_k"][i-1] < data["slow_k"][i]:
buy = data["low"][i]
if data["rsi"][i] < 25:
if data["rsi"][i - 2] < data["rsis"][i - 2] and data["rsi"][i - 1] < data["rsis"][i - 1] and data["rsis"][i] < data["rsi"][i]:
if data["close"][i] < data["avg5"][i]:
buy = data["close"][i]
else:
buy = data["low"][i]
weight = 1
#############################
### STOCHASTIC weight 분석 ###
#############################
if data["slow_k"][i] in (0, 1, 2, 3):
weight = 1
if data["slow_k"][i] in (4, 5, 6, 7, 8):
weight = 1
elif data["slow_k"][i] in (9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20):
weight = 1
elif data["slow_k"][i] in (21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35):
weight = 1
return buy, weight, sell
def getPriceAndWeight2(self, data, i):
buy, weight, sell = -1, -1, -1
################
### sell 분석 ###
################
# 1. 볼린져밴드 상단이 최고와 종가 사이 아래에 있는 경우 매도한다.
if (data["high"][i] - data["close"][i]) / 2 + data["close"][i] > data["upper"][i]:
sell = data["high"][i]
if data["slow_k"][i] >= 85:
if data["slow_d"][i - 1] < data["slow_k"][i - 1] and data["slow_k"][i] < data["slow_d"][i]:
sell = data["high"][i]
# 3. 2시 이후에는 최고가가 볼린져밴드 상단 위에 있으면 매도한다.
if i > 300 and data["high"][i] > data["upper"][i]:
sell = data["high"][i]
##########################
### STOCHASTIC buy 분석 ###
##########################
if i < 40:
pre_slow = data["slow_k"][i - 1] / data["slow_d"][i - 1] - 1
now_slow = data["slow_k"][i] / data["slow_d"][i] - 1
if pre_slow < 0 and 0 < now_slow:
if data["slow_k"][i] <= 35:
if (data["close"][i] - data["lower"][i]) / (data["upper"][i] - data["lower"][i]) < 0.35:
if data["slow_k"][i - 1] < data["slow_d"][i - 1] and data["slow_d"][i] < data["slow_k"][i]:
if data['avg10'][i] < data['avg5'][i]:
if data["open"][i] < data["close"][i]:
buy = data["close"][i]
else:
buy = data["low"][i]
else:
pre_slow = data["slow_k"][i - 1] / data["slow_d"][i - 1] - 1
now_slow = data["slow_k"][i] / data["slow_d"][i] - 1
if pre_slow < 0 and pre_slow < now_slow and -0.15 < now_slow:
if data["slow_k"][i] <= 30:
if (data["close"][i] - data["lower"][i]) / (data["upper"][i] - data["lower"][i]) < 0.35:
if data["slow_k"][i - 1] < data["slow_d"][i - 1] and data["slow_d"][i] < data["slow_k"][i]:
if data['avg10'][i] < data['avg5'][i]:
if data["close"][i] < data["avg5"][i]:
buy = data["close"][i]
else:
buy = data["low"][i]
#############################
### STOCHASTIC weight 분석 ###
#############################
if data["slow_k"][i] in (0, 1, 2, 3):
weight = 1
if data["slow_k"][i] in (4, 5, 6, 7, 8):
weight = 1
elif data["slow_k"][i] in (9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20):
weight = 1
elif data["slow_k"][i] in (21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35):
weight = 1
return buy, weight, sell
# 곱버스에 해당함
def getPriceAndWeight3(self, data, i):
buy, weight, sell = -1, -1, -1
# 381: 어제 날짜 데이터 개수
if i >= 381:
# 매수 분석
# 이동선을 이용한 매매
# 3분선과 5분선이 10분 이상 내려오다가 3분선이 5분선을 넘어 서는 순간 매수
if int(data["avg3"][i]) > int(data["avg5"][i]):
valid = True
same_count = 0
for c in range(1, 10):
if int(data["avg3"][i-c]) == int(data["avg5"][i-c]):
same_count += 1
if int(data["avg3"][i-c]) > int(data["avg5"][i-c]):
valid = False
break
if int(data["avg3"][i-c]) > int(data["avg3"][i-c-1]) or int(data["avg5"][i-c]) > int(data["avg5"][i-c-1]):
valid = False
break
if valid and same_count < 3:
buy = data["close"][i] - 5
weight = 3
# 이동선을 이용한 매매
# 3분선이 10분선에 돌파 후 지지하는지 확인하고 slow_k < 40일 때 매수함
# 현재 단계:
# - avg3[i]이 avg10[i]보다 커야함
# - avg3[i]가 avg3[i-1]보다 커야함
if data['avg10'][i] < data['avg3'][i] and data['avg3'][i-1] < data['avg3'][i] and abs(data['avg10'][i] - data['avg3'][i]) > 2:
# 첫 이전 단계:
# - avg3[i-1]과 avg10[i-1]의 abs가 3이내여야 함
if abs(data['avg3'][i-1] - data['avg10'][i-1]) < 3 and data['avg3'][i-1] < data['avg3'][i-2]:
index1 = -1
valid = False
for j in range(2, 20):
# 두 번째 이전 단계:
# - avg3[i-2]가 avg10[i-2]보다 커야 함
# - avg3[i-2]가 avg3[i-3]보다 작아야함
if data['avg10'][i-j] < data['avg3'][i-j] and data['avg3'][i-j] > data['avg3'][i-j-1]:
index1 = j
break
for j in range(index1 + 1, 20):
# 세 번째 이전 단계:
# - avg3[i-3]가 avg3[i-4]보다 커야 함
if data['avg3'][i-j] > data['avg3'][i-j-1]:
valid = True
index1 = j
else:
break
# 마지막 체크:
# 만약 avg[3]이 avg[10]보다 작다면 매수함
if valid:
if data['avg3'][i-index1-1] < data['avg10'][i-index1-1]:
if data["slow_k"][i] < 40:
buy = data["close"][i]
weight = 3
# 만약 30원 이상 장대 양봉이 나온 경우, 다음이나 다다음 중간 값에서 매수를 한다.
if (data["close"][i] - data["low"][i]) >= 30:
middle = int((data["close"][i] + data["low"][i])/2)
buy = middle
# 장 초기 (시작 7분 이내), 볼린져 하단에서 시작하여 이병선을 모두 상승하여 마감한 경우 low 값에서 매수한다.
if i < 381 + 8:
if data["open"][i] == data["low"][i]:
if data["close"][i] > max(data["avg3"][i], data["avg5"][i], data["avg10"][i], data["avg20"][i], data["avg30"][i]):
buy = data["low"][i]
"""
## macd를 이용한 매매
#if data["macdo"][i] < 0 and data["macd"][i] < -5:
# if data["macd"][i-3] > data["macd"][i-2] and data["macd"][i-2] > data["macd"][i-1] and data["macd"][i-1] < data["macd"][i]:
# buy = data["close"][i] - 5
"""
# 표준편차를 이용한 매매
"""
#mean = (data["avg3"][i] + data["avg5"][i] + data["avg10"][i] + data["avg20"][i] + data["avg30"][i])/5
#vsum = (data["avg3"][i] - mean) ** 2 + (data["avg5"][i] - mean) ** 2 + (data["avg10"][i] - mean) ** 2 + (data["avg20"][i] - mean) ** 2 + (data["avg30"][i] - mean) ** 2
#variance = vsum / 5
#std = math.sqrt(variance)
#if std < 1:
# sell = data["close"][i] - 5
"""
"""
# 매도 분석
# 3일 선이 10분 전부터 게속 10분선 위에 있다가 아래로 내려오면 매도함
valid = False
if data["avg3"][i] < data["avg5"][i]:
if (data["avg3"][i-1] > data["avg5"][i-1] and data["avg3"][i-2] > data["avg5"][i-2] and
data["avg3"][i-3] > data["avg5"][i-3] and data["avg3"][i-4] > data["avg5"][i-4] and
data["avg3"][i-5] > data["avg5"][i-5] and data["avg3"][i-6] > data["avg5"][i-6] and
data["avg3"][i-7] > data["avg5"][i-7] and data["avg3"][i-8] > data["avg5"][i-8] and
data["avg3"][i-9] > data["avg5"][i-8] and data["avg3"][i-10] > data["avg5"][i-10]):
valid = True
if valid:
sell = data["close"][i]
"""
# slow_k와 slow_d가 90이상에서 slow_k가 slow_d 아래롸 내려온 경우
if data["rsi"][i] >= 75 and data["rsis"][i] >= 75:
if data["rsi"][i-1] > data["rsis"][i-1] and data["rsi"][i] < data["rsis"][i]:
sell = data["close"][i] - 5
#if data["slow_d"][i] > 90 and data["rsi"][i] > 65:
# if data["upper"][i] <= data["high"][i]:
# sell = data["close"][i] - 5
#if data['avg3'][i-1] > data['avg10'][i-1] and data['avg3'][i] <= data['avg10'][i]:
# if abs(data['avg3'][i - 1] - data['avg30'][i - 1]) > 10:
# sell = data["close"][i]
return buy, weight, sell
def analyze(self, result):
open = result["open"]
close = result["close"]
high = result["high"]
low = result["low"]
vol = result["vol"]
close_df = pd.DataFrame(close)
avg3_list = close_df.rolling(window=3).mean().fillna(close[0]).values.tolist()
avg3 = [item[0] for item in avg3_list]
avg5_list = close_df.rolling(window=5).mean().fillna(close[0]).values.tolist()
avg5 = [item[0] for item in avg5_list]
avg10_list = close_df.rolling(window=10).mean().fillna(close[0]).values.tolist()
avg10 = [item[0] for item in avg10_list]
avg20_list = close_df.rolling(window=20).mean().fillna(close[0]).values.tolist()
avg20 = [item[0] for item in avg20_list]
avg30_list = close_df.rolling(window=30).mean().fillna(close[0]).values.tolist()
avg30 = [item[0] for item in avg30_list]
avg60_list = close_df.rolling(window=60).mean().fillna(close[0]).values.tolist()
avg60 = [item[0] for item in avg60_list]
df = pd.DataFrame(close)
max20 = df.rolling(window=20).mean()
stddev20 = df.rolling(window=20).std()
upper_df = max20 + (stddev20 * 2) # 상단 볼린저 밴드
lower_df = max20 - (stddev20 * 2) # 하단 볼린저 밴드
upper, lower = [], []
for i in range(len(upper_df)):
if i < 10:
upper.append(upper_df.values[0][0])
lower.append(lower_df.values[0][0])
else:
upper.append(upper_df.values[i][0])
lower.append(lower_df.values[i][0])
point_temp = result["time"]
STOCK = []
for i in range(len(open)):
STOCK.append({'volume': vol[i], 'close': close[i], 'open': open[i], 'high': high[i], 'low': low[i],
'avg3': avg3[i], 'avg5': avg5[i],'avg10': avg10[i],'avg20': avg20[i],'avg30': avg30[i],'avg60': avg60[i]})
# stochastic 계산
stochastic_df = self.stochastic.apply(STOCK, n=30, m=5, t=5)
stochastic_df = stochastic_df.fillna(100)
fast_k = stochastic_df['fast_k'].values.tolist()
slow_k = stochastic_df['slow_k'].values.tolist()
slow_d = stochastic_df['slow_d'].values.tolist()
# macd 계산
macd_df = self.macd.apply(STOCK, short=12, long=26, t=9)
macd_df = macd_df.fillna(100)
macd = macd_df['macd'].values.tolist()
macds = macd_df['macds'].values.tolist()
macdo = macd_df['macdo'].values.tolist()
# rsi 계산
rsi_df = self.rsi.apply(STOCK, period=30, window=5)
rsi_df = rsi_df.fillna(100)
rsi = rsi_df['rsi'].values.tolist()
rsis = rsi_df['rsis'].values.tolist()
# ichimokuCloud 계산
# ichimokuCloud_df = self.ichimokuCloud.apply(STOCK, c=9, b=26, l=52)
# ichimokuCloud_df = rsi_df.fillna(100)
# changeLine = rsi_df['changeLine'].values.tolist()
# baseLine = rsi_df['baseLine'].values.tolist()
# leadingSpan1 = rsi_df['leadingSpan1'].values.tolist()
# leadingSpan2 = rsi_df['leadingSpan2'].values.tolist()
temp = {"date": point_temp,
"open": open, "high": high, "low": low, "close": close, "volume": vol, "upper": upper, "lower": lower,
"avg3": avg3, "avg5": avg5, "avg10": avg10, "avg20": avg20, "avg30": avg30, "avg60": avg60,
"macd": macd, "macds": macds, "macdo": macdo,
"fast_k": fast_k, "slow_k": slow_k, "slow_d": slow_d,
"rsi": rsi, "rsis": rsis}
data = pd.DataFrame(temp)
df_final_time = pd.DatetimeIndex(point_temp)
data.index = df_final_time
return data
def checkTransaction(self, data, stock_code):
size = len(data["close"])
bsLine = {}
bsLine['buy'] = [-1 for i in range(size)]
bsLine['weight'] = [-1 for i in range(size)]
bsLine['sell'] = [-1 for i in range(size)]
for i in range(size):
if stock_code == "252670":
buy, weight, sell = self.getPriceAndWeight3(data, i)
else:
buy, weight, sell = self.getPriceAndWeight4(data, i)
bsLine['buy'][i] = buy
bsLine['weight'][i] = weight
bsLine['sell'][i] = sell
return bsLine