import pandas as pd from stockpredictor.analysis.Common import Common from plotly import tools, subplots import numpy as np import plotly.graph_objs as go import plotly.io as po # [청송촌놈] 파생을 알아야 시장이 보인다. 청송이 종목 고르는법! https://www.youtube.com/watch?v=weABtgZDeGg # 6. Pandas와 Plotly를 이용한 MACD 차트 그리기 https://excelsior-cjh.tistory.com/110 # 첫번째. MACD 지표를 이용한 차트분석: https://post.naver.com/viewer/postView.nhn?volumeNo=7435935&memberNo=32471429 # MACD (Moving Average Conver gence Divergence) # 빨간 네모박스권으로 MACD가 MACD-Sign 을 골든크로스하며, 상승하였을때, 주가는 상승추세를 유지하며, MACD가 MACD-Sign(분홍색)을 데드크로스 할때 주가는 하락의 추세를 보이게 됩니다. # 즉, MSCD가 0이상에서 MACD-Sign 위에서 상승하는 그림이어야 class RSI: common = None def __init__(self): self.common = Common() return def draw(self, stock): item_name = stock["NAME"] item_code = stock["CODE"] df = pd.DataFrame(stock["PRICE"]) rsi = go.Scatter(x=df.DATE, y=df['rsi'], name="RSI") signal = go.Scatter(x=df.DATE, y=df['rsis'], name="RSI Signal") data = [rsi, signal] layout = go.Layout(title='{} RSI 그래프'.format(item_name)) fig = subplots.make_subplots(rows=2, cols=1, shared_xaxes=True) for trace in data: fig.append_trace(trace, 1,1) fig = go.Figure(data=data, layout=layout) path = "/Users/dsyoon/workspace/StockPredictor/resources/analysis/html" po.write_html(fig, file=path + "/rsi" + item_code+'.html', auto_open=False) return fig def apply(sefl, df, period=14): # df.diff를 통해 (기준일 종가 - 기준일 전일 종가)를 계산하여 0보다 크면 증가분을 감소했으면 0을 넣어줌 U = np.where(df.close.diff(1) > 0, df.close.diff(1), 0) # df.diff를 통해 (기준일 종가 - 기준일 전일 종가)를 계산하여 0보다 작으면 감소분을 증가했으면 0을 넣어줌 D = np.where(df.close.diff(1) < 0, df.close.diff(1) * (-1), 0) # AU, period=14일 동안의 U의 평균 AU = pd.DataFrame(U).rolling(window=period, min_periods=period).mean() # AD, period=14일 동안의 D의 평균 AD = pd.DataFrame(D).rolling(window=period, min_periods=period).mean() rsi = AU.div(AD + AU) * 100 rsis = rsi.rolling(window=9).mean() df = df.assign(rsi=rsi, rsis=rsis) return df def analyze(self, stock): """ RSI 값이 100에 접근하면 ㄷ 이상의 주가 상승을 기대하기 어렵고, 0에 접근하면 더 이상 하락을 기대하기 어렵다. 70이상이면 과매수 구간이라 할 수 있고, 30 이하면 과매도 구간이라 볼 수 있다. 따라서 과매수 구간에서는 매도 준비를, 과매도 구간에서는 매수 준비를 해야 한다. """ results = [] df = pd.DataFrame() df = df.from_dict(stock['PRICE']) df = self.apply(df) for i in range(len(df.rsi)): result = {'DATE':stock['PRICE'][i]['DATE'], 'rsi': df.rsi.values[i], 'rsis': df.rsis.values[i], 'rsi_buy': 0} # rsi가 상향이고 30을 돌파하면 매수, if df.rsi.values[i - 1] < df.rsi.values[i]: if df.rsi.values[i-1] <= 30 and df.rsi.values[i] > 30: result['rsi_buy'] = 1 # rsi가 상향이고 40을 돌파하면 매수, if df.rsi.values[i - 1] < df.rsi.values[i]: if df.rsi.values[i-1] <= 50 and df.rsi.values[i] > 50: result['rsi_buy'] = 1 # rsi가 상향이고 70을 돌파하면 단기매수, if df.rsi.values[i - 1] < df.rsi.values[i]: if df.rsi.values[i-1] <= 70 and df.rsi.values[i] > 70: result['rsi_buy'] = 1 # rsi가 하향이고 70이하로 떨어지면 매도, if df.rsi.values[i - 1] > df.rsi.values[i]: if df.rsi.values[i-1] > 70 and df.rsi.values[i] <= 70: result['rsi_buy'] = -1 # rsi가 하향이고 50이하로 떨어지면 매도, if df.rsi.values[i - 1] > df.rsi.values[i]: if df.rsi.values[i-1] > 50 and df.rsi.values[i] <= 50: result['rsi_buy'] = -1 # rsi가 하향이고 30이하로 떨어지면 단기매도, if df.rsi.values[i - 1] > df.rsi.values[i]: if df.rsi.values[i-1] > 30 and df.rsi.values[i] <= 30: result['rsi_buy'] = -1 results.append(result) return results