범주 | 기술적 지표 |
---|---|
추세 | 선형회귀, 이동평균선 (MACD) |
모멘텀 | 변화율, 스토캐스틱 (%k, %d) |
거래량 | 일중강도(II), 매집/분산(A/D), 현금흐름지표(MFI), 거래량가중(MACD) |
과매수/과매도 | CCI, RSI |
심리 | 여론조사선, 풋/콜옵션 비율 |
DATA_FILENAME = 'data/stock-naver.pkl'
import pandas as pd
import FinanceDataReader as fdr
try:
data_raw = pd.read_pickle(DATA_FILENAME)
except FileNotFoundError:
data_raw = fdr.DataReader("035420", "2019-01-01")
data_raw.columns = [_.lower() for _ in data_raw.columns]
data_raw.to_pickle(DATA_FILENAME)
data_df = data_raw.copy()
data_df.tail(3)
open | high | low | close | volume | change | |
---|---|---|---|---|---|---|
Date | ||||||
2021-08-11 | 445000 | 449000 | 442000 | 445000 | 446275 | -0.003359 |
2021-08-12 | 448000 | 448500 | 438000 | 440500 | 671083 | -0.010112 |
2021-08-13 | 445000 | 446000 | 433000 | 436500 | 479201 | -0.009081 |
# 볼린저 밴드 데이터 추가
data_df['MA20'] = data_df['close'].rolling(window=20).mean()
data_df['stddev'] = data_df['close'].rolling(window=20).std()
data_df['upper'] = data_df['MA20'] + (data_df['stddev'] * 2)
data_df['lower'] = data_df['MA20'] - (data_df['stddev'] * 2)
data_df['PB'] = (data_df['close'] - data_df['lower']) / (data_df['upper'] - data_df['lower'])
data_df.tail(3)
open | high | low | close | volume | change | MA20 | stddev | upper | lower | PB | |
---|---|---|---|---|---|---|---|---|---|---|---|
Date | |||||||||||
2021-08-11 | 445000 | 449000 | 442000 | 445000 | 446275 | -0.003359 | 441875.0 | 7530.420761 | 456935.841523 | 426814.158477 | 0.603746 |
2021-08-12 | 448000 | 448500 | 438000 | 440500 | 671083 | -0.010112 | 441450.0 | 7344.708084 | 456139.416168 | 426760.583832 | 0.467664 |
2021-08-13 | 445000 | 446000 | 433000 | 436500 | 479201 | -0.009081 | 440925.0 | 7302.261726 | 455529.523452 | 426320.476548 | 0.348506 |
# 중심가격 (Typical Price) 의 계산 : (일정기간 고가/ 저가/ 종가) 의 3평균
data_df['TP'] = (data_df['high'] + data_df['low'] + data_df['close']) / 3
# PMF (Positive Money Flow)
data_df['PMF'], data_df['NMF'] = 0, 0
# 현금흐름값 : (i+1 일차 중심가격) X (i+1 일차 거래량)
for i in range(len(data_df.close)-1):
# 익일 중심가격이 높아진 경우 (중심가격 X 거래량) : PMF 현금흐름값 저장, NMF 는 0 저장
if data_df.TP.values[i] < data_df.TP.values[i+1]:
data_df.PMF.values[i+1] = data_df.TP.values[i+1] * data_df.volume.values[i+1]
data_df.NMF.values[i+1] = 0
# 익일 중심가격이 높아진 경우 : PMF 0 저장, NMF 는 현금흐름값 저장
else:
data_df.NMF.values[i+1] = data_df.TP.values[i+1] * data_df.volume.values[i+1]
data_df.PMF.values[i+1] = 0
# 현금흐름비율 (MFR : Money Flow raito)
# : 10일 간의 긍정적 현금흐름의 합을 10일간 부정적 현금흐름의 합으로 나는 결과
data_df['MFR'] = (data_df.PMF.rolling(window=10).sum() /
data_df.NMF.rolling(window=10).sum())
# 10일 간의 현금흐름지표 계산결과 저장
data_df['MFI10'] = 100 - 100 / (1 + data_df['MFR'])
data_df = data_df[19:]
data_df.tail(3)
open | high | low | close | volume | change | MA20 | stddev | upper | lower | PB | TP | PMF | NMF | MFR | MFI10 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Date | ||||||||||||||||
2021-08-11 | 445000 | 449000 | 442000 | 445000 | 446275 | -0.003359 | 441875.0 | 7530.420761 | 456935.841523 | 426814.158477 | 0.603746 | 445333.333333 | 0 | 198741133333 | 0.445550 | 30.822196 |
2021-08-12 | 448000 | 448500 | 438000 | 440500 | 671083 | -0.010112 | 441450.0 | 7344.708084 | 456139.416168 | 426760.583832 | 0.467664 | 442333.333333 | 0 | 296842380333 | 0.432718 | 30.202577 |
2021-08-13 | 445000 | 446000 | 433000 | 436500 | 479201 | -0.009081 | 440925.0 | 7302.261726 | 455529.523452 | 426320.476548 | 0.348506 | 438500.000000 | 0 | 210129638500 | 0.448763 | 30.975603 |
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
# Loading ... Visualization Modules
import matplotlib.pyplot as plt
import warnings
plt.style.use('seaborn')
warnings.simplefilter(action='ignore', category=FutureWarning)
from matplotlib.font_manager import fontManager as fm # 한글폰트 확인 및 추가
font_list_check = ['D2Coding', 'NanumGothicCoding', 'NanumGothic']
for _ in font_list_check:
font_counts = [f for f in font_list_check if _ in [_.name for _ in fm.ttflist]]
if len(font_counts) > 1: print(f"found : {_}"); plt.rc('font', family=_); break
found : D2Coding
plt.rcParams['figure.dpi'] = 300
plt.rcParams['figure.figsize'] = (20.0, 8.0) # plt.figure(figsize=(15, 8))
plt.subplot(2,1,1, ylabel='BBand(20 day, 2 std)')
plt.plot(data_df.index, data_df['close'], label='Close', color='purple')
plt.plot(data_df.index, data_df['upper'], '--', label ='Upper band', color='orange')
plt.plot(data_df.index, data_df['MA20'], 'k--', label='Moving average 20')
plt.plot(data_df.index, data_df['lower'], 'c--', label ='Lower band')
plt.fill_between(data_df.index, data_df['upper'], data_df['lower'], color='0.9')
plt.subplot(2,1,2)
plt.plot(data_df.index, data_df['PB'] * 100, label='%B x 100', color='orange')
plt.plot(data_df.index, data_df['MFI10'], 'g--', label='MFI(10 day)')
plt.axhline(y=(1*100), color ='black', linewidth=.5, linestyle="--") # 볼린저 밴드 상단
plt.axhline(y=(.5*100), color ='red', linewidth=1.5, linestyle="--") # 볼린저 밴드 중심
plt.axhline(y=(0*100), color ='black', linewidth=.5, linestyle="--") # 볼린저 밴드 하단
plt.yticks([-20, 0, 20, 40, 60, 80, 100, 120])
plt.grid(True); plt.legend(loc='best'); plt.show();
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
# Loading ... Visualization Modules
import matplotlib.pyplot as plt
import warnings
plt.style.use('seaborn')
warnings.simplefilter(action='ignore', category=FutureWarning)
from matplotlib.font_manager import fontManager as fm # 한글폰트 확인 및 추가
font_list_check = ['D2Coding', 'NanumGothicCoding', 'NanumGothic']
for _ in font_list_check:
font_counts = [f for f in font_list_check if _ in [_.name for _ in fm.ttflist]]
if len(font_counts) > 1: print(f"found : {_}"); plt.rc('font', family=_); break
found : D2Coding
plt.rcParams['figure.dpi'] = 300
plt.rcParams['figure.figsize'] = (20.0, 6.0) # plt.figure(figsize=(15, 8))
plt.subplot(2, 1, 1, title='NAVER Bollinger Band(20 day, 2 std) - Trend Following')
plt.plot(data_df.index, data_df['close'], label='Close', color='purple')
plt.plot(data_df.index, data_df['upper'], '--', label ='Upper band', color='orange')
plt.plot(data_df.index, data_df['MA20'], 'k--', label='Moving average 20')
plt.plot(data_df.index, data_df['lower'], 'c--', label ='Lower band')
plt.fill_between(data_df.index, data_df['upper'], data_df['lower'], color='0.9')
for i in range(len(data_df.close)):
if data_df.PB.values[i] > 0.8 and data_df.MFI10.values[i] > 80:
plt.plot(data_df.index.values[i], data_df.close.values[i], 'r^')
elif data_df.PB.values[i] < 0.2 and data_df.MFI10.values[i] < 20:
plt.plot(data_df.index.values[i], data_df.close.values[i], 'bv')
plt.legend(loc='best')
plt.subplot(2, 1, 2)
plt.plot(data_df.index, data_df['PB'] * 100, label='%B x 100', color='orange')
plt.plot(data_df.index, data_df['MFI10'], 'g--', label='MFI(10 day)')
plt.axhline(y=(1*100), color ='black', linewidth=.5, linestyle="--") # 볼린저 밴드 상단
plt.axhline(y=(.5*100), color ='red', linewidth=1.5, linestyle="--") # 볼린저 밴드 중심
plt.axhline(y=(0*100), color ='black', linewidth=.5, linestyle="--") # 볼린저 밴드 하단
plt.yticks([-20, 0, 20, 40, 60, 80, 100, 120])
for i in range(len(data_df.close)):
if data_df.PB.values[i] > 0.8 and data_df.MFI10.values[i] > 80: # 매수시점
plt.plot(data_df.index.values[i], 0, 'r^')
elif data_df.PB.values[i] < 0.2 and data_df.MFI10.values[i] < 20: # 매도시점
plt.plot(data_df.index.values[i], 0, 'bv')
plt.grid(True); plt.legend(loc='best'); plt.show()