STOCK/변동성돌파전략
[파이썬 주식] 변동성돌파전략 - 3. 종목/조건 3개월 백테스트
BOTTLE6
2021. 1. 23. 23:03
## 2021.01.23
1. 라이브러리 임포트
from pandas_datareader import data as pdr
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
import time
from pykrx import stock
# 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. 선정 된 종목 불러오기
codes = ['A204320', 'A028050', 'A035150', 'A011210', 'A131390', 'A006360', 'A005070',
'A005380', 'A001510', 'A001140', 'A068270', 'A004020', 'A032560', 'A200130', 'A039490',
'A079430', 'A000990', 'A011790', 'A210980', 'A002840', 'A035510', 'A029460', 'A086280',
'A005940', 'A006800', 'A020760', 'A011760', 'A069260']
codes = [ code[1:] for code in codes ]
codes
3. 테스트 및 날짜 불러오기
def Symbol_Volatility(code, k, start):
code = str(code)+".KS"
df=pd.DataFrame()
df = pdr.get_data_yahoo(code, start)
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)
#cond = ( df['High'] > df['목표가'] ) & ( df['목표가'] > df['MA3_yes'] )
return df
dates = list(df.index.strftime("%Y-%m-%d")) # 날짜 적절한 형태로 포맷 변경
dates[:5]
4. 최근 3개월 백테스트해보기
def Symbol_Volatility(code, k, start):
code = str(code)+".KS"
df=pd.DataFrame()
df = pdr.get_data_yahoo(code, start)
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)
return df
start = time.time()
만족수 = []
평균수익률 = []
날짜 = []
for spec_date in dates:
수익률 = []
만족 = []
try :
for code in codes:
df = Symbol_Volatility(code, k=0.5, start='2020-10-01')
cond = ( df['High'] > df['목표가'] ) & ( df['목표가'] > df['MA3_yes'] )
수익률.append((df.loc[spec_date,"내일시가"] - df.loc[spec_date,"목표가"] )/ df.loc[spec_date,"목표가"] - 0.0032)
만족.append(spec_date in list(df.loc[cond].index.strftime("%Y-%m-%d")))
time.sleep(0.2)
df = pd.DataFrame({"수익률":수익률, "만족":만족},index=codes)
cond = (df['만족']==True)
만족수.append(df.만족.sum())
평균수익률.append(df.loc[cond, '수익률'].sort_values(ascending=False).mean())
날짜.append(spec_date)
except:
pass
df = pd.DataFrame({"만족수":만족수, "평균수익률":평균수익률},index=날짜)
print("time :", time.time() - start) # 현재시각 - 시작시간 = 실행 시간
df.head()
4. 시각화해보기
plt.figure(figsize=(12,8))
plt.subplot(2,1,1)
df.평균수익률.plot()
plt.subplot(2,1,2)
df.만족수.plot.bar()
df['승패'] = [1 if x > 0 else 0 for x in df['평균수익률']]
sns.scatterplot(data=df, x='만족수' , y='평균수익률',hue='승패')
(df['평균수익률']+1).cumprod().plot.bar()
plt.ylim(0.8,1.8)
11월 1일부터 1월 22일까지 약 3개월간 백테스트 해보면,
11월 1일에 100만원을 넣고 매일매일 금액 전체를 투자했다면, 이론대로라면
1월 22일에는 168만원이 된다.
과연 실제로 그럴지는.. 한번 실제로 테스트를 해보겠다.