데이터 공부를 기록하는 공간

[파이썬 주식] 변동성돌파전략 - 3. 종목/조건 3개월 백테스트 본문

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만원이 된다.

과연 실제로 그럴지는.. 한번 실제로 테스트를 해보겠다.

Comments