117 lines
5.9 KiB
Python
117 lines
5.9 KiB
Python
import pandas as pd
|
|
import datetime
|
|
from plotly import tools, subplots
|
|
import plotly.offline as offline
|
|
import plotly.graph_objs as go
|
|
import plotly.io as po
|
|
|
|
from stockpredictor.analysis.Common import Common
|
|
|
|
# graph: https://plotly.com/python/candlestick-charts/
|
|
# https://www.nanumtrading.com/fx-%EB%B0%B0%EC%9A%B0%EA%B8%B0/%EC%B0%A8%ED%8A%B8-%EB%B3%B4%EC%A1%B0%EC%A7%80%ED%91%9C-%EC%9D%B4%ED%95%B4/06-%EC%9D%BC%EB%AA%A9%EA%B7%A0%ED%98%95%ED%91%9C/
|
|
# 일목균형표 - 매매기법 알아보기 !: https://layhope.tistory.com/222
|
|
class IchimokuCloud:
|
|
|
|
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"])
|
|
leadingSpan1 = go.Scatter(x=df.DATE, y=df['leadingSpan1'], name="선행스팬1", line_color='#8B4513')
|
|
leadingSpan2 = go.Scatter(x=df.DATE, y=df['leadingSpan2'], name="선행스팬2", line_color='#4169E1')
|
|
candle = go.Candlestick(x=df.DATE, open=df.open, high=df.high, low=df.low, close=df.close, increasing_line_color= 'red', decreasing_line_color= 'blue')
|
|
data = [leadingSpan1, leadingSpan2, candle]
|
|
|
|
layout = go.Layout(title='{} MACD 그래프'.format(item_name))
|
|
fig = subplots.make_subplots(rows=1, 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 + "/ichimokuCloud_" + item_code+'.html', auto_open=False)
|
|
return fig
|
|
|
|
# c=9, b=26, l=52
|
|
def apply(self, df, c=9, b=26, l=52):
|
|
# 입력받은 값이 dataframe이라는 것을 정의해줌
|
|
df = pd.DataFrame(df)
|
|
|
|
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
|
|
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
|
|
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
|
|
|
|
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
|
|
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
|
|
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
|
|
|
|
# 3. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
|
|
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
|
|
leadingSpan1 = (changeLine + baseLine) / 2
|
|
move_LeadingSpan1 = list(leadingSpan1.values)
|
|
for i in range(b - 1):
|
|
move_LeadingSpan1.insert(0, None)
|
|
|
|
# 4. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
|
|
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
|
|
leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
|
|
move_LeadingSpan2 = list(leadingSpan2.values)
|
|
for i in range(l - 1):
|
|
move_LeadingSpan2.insert(0, None)
|
|
|
|
# leadingSpan2에 맞추어 뒤로 빈 row를 채운다.
|
|
for i in range(len(move_LeadingSpan2) - len(df)):
|
|
df = df.append({"DATE": None, "close": None, "diff": None, "open": None, "high": None, "low": None, "volume": None, "avg3": None, "avg5": None, "avg7": None, "avg10": None, "avg20": None, "avg30": None, "avg60": None, "avg90": None, "avg100": None, "avg120": None, "avg150": None, "avg180": None, "avg200": None, "avg240": None}, ignore_index=True)
|
|
move_changeLine = list(changeLine.values)
|
|
for i in range(len(move_LeadingSpan2) - len(move_changeLine)):
|
|
move_changeLine.append(None)
|
|
move_baseLine = list(baseLine.values)
|
|
for i in range(len(move_LeadingSpan2) - len(move_baseLine)):
|
|
move_baseLine.append(None)
|
|
for i in range(len(move_LeadingSpan2) - len(move_baseLine)):
|
|
move_LeadingSpan1.append(None)
|
|
|
|
# dataframe에 컬럼 추가
|
|
df = df.assign(changeLine=pd.Series(move_changeLine), baseLine=pd.Series(move_baseLine), leadingSpan1=pd.Series(move_LeadingSpan1), leadingSpan2=pd.Series(move_LeadingSpan2))
|
|
|
|
return df
|
|
|
|
# 일목균형표의 구성을 훑어보면 주가를 선행과 후행으로 과거의 주가를 통해 미래 혹은 현재의 주식의 가격의 추세를 예측해보려는 지표라는 것을 이해할 수 있다.
|
|
# 또한 구름층의 색을 통해서 주식의 추세를 손쉽게 확인할 수 있을 것 같다는 것도 이해할 수 있다면 끝 !
|
|
def analyze(self, stock):
|
|
df = pd.DataFrame()
|
|
df = df.from_dict(stock['PRICE'])
|
|
df = self.apply(df)
|
|
|
|
diff = len(df.changeLine) - len(stock['PRICE'])
|
|
"""
|
|
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(
|
|
{"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)-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]
|
|
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
ichimokuCloud = IchimokuCloud()
|