STOCK/변동성돌파전략
[파이썬 주식] 변동성돌파전략 - 9. 조건추가 PB
BOTTLE6
2021. 2. 13. 10:13
#20210212_2.
## 1. 라이브러리
from Investar import Analyzer
mk = Analyzer.MarketDB()
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import time
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
# matplotlib 한글 폰트 출력코드
import matplotlib
from matplotlib import font_manager, rc
import platform
try :
if platform.system() == 'Windows':
# 윈도우인 경우
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)
else:
# Mac 인 경우
rc('font', family='AppleGothic')
except :
pass
matplotlib.rcParams['axes.unicode_minus'] = False
## 2. 종목 불러오기
## 종목 불러오기
import pandas as pd
"""KRX로부터 상장기업 목록 파일을 읽어와서 데이터프레임으로 반환"""
url = 'http://kind.krx.co.kr/corpgeneral/corpList.do?method='\
'download&searchType=13'
krx = pd.read_html(url, header=0)[0]
krx = krx[['종목코드', '회사명']]
krx = krx.rename(columns={'종목코드': 'code', '회사명': 'company'})
krx.code = krx.code.map('{:06d}'.format)
krx = krx.set_index('code')
krx
codes = list(krx.index)
companys = [krx.loc[code,'company'] for code in codes]
## 3. 백테스트함수 - 조건 추가
pb : Percent Bollinger로 현재 상태가 과매수/ 과매도 상태인지 알려주는 지표,
조건은 어제 종가기준으로 pb < 특정값보다 작을때 , 오늘 매매 여부를 결정
PB = (close - lower) / (upper - lower)
보통 PB가 0.2이하일 경우, 과매도, PB가 0.8이상일 경우 과매수라고 보는 보조지표임.
def backtest(종목명, k, start='2020-01-01', pb=0.2):
df=mk.get_daily_price(종목명, start)
df.set_index(df['date'].apply(lambda x:pd.to_datetime(x)),inplace=True)
df['변동폭'] = df['high']-df['low']
df['목표가'] = df['open'] + df['변동폭'].shift(1)*k
df['MA3_yes'] = df.close.rolling(window=3).mean().shift(1)
df['내일시가'] = df.open.shift(-1)
df['MA20'] = df['close'].rolling(window=20).mean()
df['stddev'] = df['close'].rolling(window=20).std()
df['upper'] = df['MA20'] + (df['stddev'] * 2)
df['lower'] = df['MA20'] - (df['stddev'] * 2)
df['PB'] = (df['close'] - df['lower']) / (df['upper'] - df['lower'])
df['PB_yes'] = df['PB'].shift(1)
cond = ( df['high'] > df['목표가'] ) & ( df['목표가'] > df['MA3_yes'] ) & ( df['PB_yes'] < pb )
df.loc[cond,'수익률'] = df.loc[cond,'내일시가']/df.loc[cond,'목표가']*0.9975 - 0.006 #0.9975 수수료, 0.002 슬리피지
df=df[19:]
return [df.dropna().shape[0] , df.dropna().수익률.cumprod().iloc[-1] , df.dropna().수익률.cumprod().iloc[-1]**(1/df.dropna().shape[0])]
df = backtest("현대건설",0.5,'2020-01-01', 0.2)
df
## 4. 몇가지 종목 확인
def pb구하기(종목명):
a=[]
b=[]
for pb in np.arange(0.1, 1.3, 0.1):
a.append(backtest(종목명,0.5,'2020-01-01',pb))
b.append(pb)
s = pd.Series(a, index=b)
return s
pb구하기("신풍제약")
▶ pb / [ 만족 횟수 , 누적수익률, 기하평균수익률 ]
▶ pb <1 조건일 때 누적수익률이 가장 좋음,
pb구하기("LG이노텍")
▶ pb < 0.6 일때 누적수익률이 가장 좋음.
▶ pb < 0.2 일때, 기하평균 수익률이 가장 좋음(9회 만족)
pb구하기("현대글로비스")
▶ PB < 1.2일때, 누적수익률이 가장 좋음
▶ PB < 0.1일때 기하평균 수익률이 가장 좋음(3회 만족)
pb구하기("LG전자")
▶ pb<0.8 일때 누적수익률이 가장 좋음
▶ pb<0.2 일때 기하평균수익률이 가장 좋음 ...
pb구하기("현대바이오")
▶ pb < 0.4 일때 누적수익률이 가장 좋음
▶ pb <0.2 일때 기하평균 수익률이 가장 좋음(9회)