VAA 전략, 백테스트 실시 - 기본편(수익률)

퀀트 전략/자산배분|2020. 9. 25. 15:04

 

안녕하세요, 오늘은 지난 포스팅에서 알려드렸던 VAA 전략을 직접 백테스트 해볼 예정입니다. 아직 VAA 전략에 대한 포스팅을 못 보신 분들은 아래 링크를 통해 확인하시기 바랍니다 : )

 

[퀀트 전략] - VAA 전략, 동적 자산 배분의 수익 끝판왕!

 

VAA 전략, 동적 자산 배분의 수익 끝판왕!

1. VAA 전략이란?  안녕하세요. 오늘 소개해드릴 전략은 VAA(Vigilant Asset Allocation) 전략입니다. VAA 전략은 Breadth Momentum and Vigilant Asset Allocation (VAA): Winning More by Losing Less라는 논..

lazyquant.tistory.com

 

 지난 포스팅에서 VAA는 동적 자산 배분 전략 중 지난 50년 기간 백테스트 결과 수익률 측면에서 1위를 기록했다고 알려드렸습니다. 1971년부터 2017년까지의 수익률 그래프가 아래와 같이 아름답게 그려지는데요.

 

 

 물론 백테스트를 실시한 AllocateSmartly에서 백테스트를 잘못 진행했을 가능성은 적지만, 백테스트는 '직접' 해보는 것이라고 강환국 선생님께 배웠기 때문에, 직접 백테스트를 진행해보았습니다. 이 글을 보는 분들도 직접 백테스트를 진행해보신다면 전략이 성과를 발휘하는 원리를 파악하고, 다양한 전략을 구상하실 수 있을 것 같습니다.

 

 처음에는 백테스트를 엑셀로 진행을 하려다, 엑셀에 익숙치 않아서(?) & 다양한 기능들을 활용하기 위해, 파이썬을 활용해 데이터를 불러오고 작업해보았습니다.

 

1. 필요 데이터 추출

import pandas_datareader as pdr
import pandas as pd
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import seaborn as sns

pd.options.display.float_format = '{:.2f}'.format

start_day = datetime(2010,1,1) # 시작일
end_day = datetime(2020,9,22) # 종료일

# 공격자산
SPY = pdr.get_data_yahoo('SPY', start_day - timedelta(days=365), end_day)['Adj Close']
VEA = pdr.get_data_yahoo('VEA', start_day - timedelta(days=365), end_day)['Adj Close']
EEM = pdr.get_data_yahoo('EEM', start_day - timedelta(days=365), end_day)['Adj Close']
AGG = pdr.get_data_yahoo('AGG', start_day - timedelta(days=365), end_day)['Adj Close']

# 수비자산
LQD = pdr.get_data_yahoo('LQD', start_day - timedelta(days=365), end_day)['Adj Close']
SHY = pdr.get_data_yahoo('SHY', start_day - timedelta(days=365), end_day)['Adj Close']
IEF = pdr.get_data_yahoo('IEF', start_day - timedelta(days=365), end_day)['Adj Close']

 요즘에는 워낙 다양한 라이브러리들이 잘 개발되어 있기 때문에, 잘 활용한다면 쉽게 데이터를 가져올 수 있습니다. 주가의 전체 데이터를 가져와서 DB를 구축할 것이 아니라면, 위의 소스와 같이 필요 데이터 중 일부만 가져오는게 편리합니다.

 

2. 추출 데이터 확인

df_VAA = pd.concat([SPY,VEA,EEM,AGG,LQD,SHY,IEF],axis=1)
df_VAA.columns = ['SPY','VEA','EEM','AGG','LQD','SHY','IEF']
df_VAA.head(5)

샘플로 5일치의 데이터만 출력해보았습니다. 원하는 형태로 데이터가 잘 불러와진 것을 확인할 수 있습니다. 이제 이 데이터들을 활용해서 모멘텀 지수를 계산하고, 실제로 운영했을 때의 수익률을 확인해보도록 하겠습니다.

 

3. 모멘텀 지수 계산

# 모멘텀 지수 계산 함수
def get_momentum(x):    
    momentum = pd.Series([0,0,0,0,0,0,0], index=['SPY','VEA','EEM','AGG','LQD','SHY','IEF'])

    try:
        before1 = df_VAA[x.name-timedelta(days=35):x.name-timedelta(days=30)].iloc[-1] 
        before3 = df_VAA[x.name-timedelta(days=95):x.name-timedelta(days=90)].iloc[-1]        
        before6 = df_VAA[x.name-timedelta(days=185):x.name-timedelta(days=180)].iloc[-1]        
        before12 = df_VAA[x.name-timedelta(days=370):x.name-timedelta(days=365)].iloc[-1]

        momentum = 12 * (x / before1 - 1) + 4 * (x / before3 - 1) + 2 * (x / before6 - 1) + (x / before12 - 1)
    except:
        pass    

    return momentum
# 각 자산별 모멘텀 지수 계산
df_VAA[['SPY_M','VEA_M','EEM_M','AGG_M','LQD_M','SHY_M','IEF_M']] = df_VAA.apply(lambda x: get_momentum(x), axis=1)
df_VAA.tail(10)

각 자산별 모멘텀 지수 계산

 각 자산별로 계산된 모멘텀 지수를 우측에 _M 필드로 만들어서 생성했습니다. 지금은 모멘텀 지수를 계산하기 위해 매일의 데이터를 가지고 있지만, 실제로 리밸런싱을 월 1회 한다는 가정으로 테스트 하기 위해서는 매월 말일의 데이터만 있으면 충분합니다.

 

 

 

 

 

4. 필요 기간 데이터 추출

# 백테스트할 기간 데이터 추출
df_VAA = df_VAA[start_day:end_day]

# 매월 말일 데이터만 추출(리밸런싱에 사용)
df_VAA = df_VAA.resample(rule='M').apply(lambda x: x[-1])
df_VAA.head(10)

매월 말일 데이터만 남김

5. 계산된 모멘텀 지수로 보유 자산 선정

# VAA 전략 기준에 맞춰 자산 선택
def select_asset(x):
    asset = pd.Series([0,0], index=['ASSET','PRICE'])
    
    # 공격 자산이 모두 0이상이면, 공격 자산 중 최고 모멘텀 자산 선정
    if x['SPY_M'] > 0 and x['VEA_M'] > 0 and x['EEM_M'] > 0 and x['AGG_M'] > 0:
        max_momentum = max(x['SPY_M'],x['VEA_M'],x['EEM_M'],x['AGG_M'])     
    
    # 공격 자산 중 하나라도 0이하라면, 방어 자산 중 최고 모멘텀 자산 선정
    else :
        max_momentum = max(x['LQD_M'],x['SHY_M'],x['IEF_M'])
    
    asset['ASSET'] = x[x == max_momentum].index[0][:3]
    asset['PRICE'] = x[asset['ASSET']]   
     
    return asset
# 매월 선택할 자산과 가격
df_VAA[['ASSET','PRICE']] = df_VAA.apply(lambda x: select_asset(x), axis=1)
df_VAA.head(10)

월별 보유 자산 및 가격

6. 월별 & 누적 수익률 계산

 이제 매달 어떤 자산을 보유 해야 하는지, 해당 월에 어떤 가격으로 매수를 했는지를 가정할 수 있게 되었습니다. 지난 달 자산과 비교하여 얼마의 수익률을 거두었고, 누적 수익률은 어떻게 되는지 구해보도록 하겠습니다.

# 매월 수익률 & 누적 수익률 계산
df_VAA['PROFIT'] = 0
df_VAA['PROFIT_ACC'] = 0
for i in range(len(df_last_day)):
    profit = 0
    if i != 0: 
        
        #지난달과 동일 자산 보유
        if df_VAA.iloc[i]['ASSET'] == df_VAA.iloc[i-1]['ASSET']:
            profit = (df_VAA.iloc[i]['PRICE'] - df_VAA.iloc[i-1]['PRICE']) / df_VAA.iloc[i-1]['PRICE'] * 100
         
        #지난달과 동일 자산 보유
        else :
            profit = (df_VAA.iloc[i][df_VAA.iloc[i-1]['ASSET']] - df_VAA.iloc[i-1]['PRICE']) / df_VAA.iloc[i-1]['PRICE'] * 100
    
    df_VAA.loc[df_VAA.index[i], 'PROFIT'] = profit
    df_VAA.loc[df_VAA.index[i], 'PROFIT_ACC'] = ((1+df_VAA.loc[df_VAA.index[i-1], 'PROFIT_ACC']/100)*(1+profit/100)-1)*100
df_VAA.tail(10)

VAA 전략의 월별, 누적 수익률

7. 수익률 그래프

plt.figure(figsize=(15,8))
sns.lineplot(data=df_VAA, x=df_VAA.index, y=df_VAA['PROFIT_ACC'])

 


공감댓글, 공유는 큰 힘이 됩니다!

도움이 되셨다면 널리널리 알려주세요😉

 

 

댓글()