VAA 전략, 백테스트 실시 - 심화편(자산별 비교, MDD 계산)

퀀트 전략/자산배분|2020. 9. 27. 18:23

 

 안녕하세요, 지난 포스팅에서 VAA 전략을 직접 백테스트한 결과를 보여드렸었습니다. 이번 포스팅에서는 과연 VAA 전략이 다른 지수들과 비교했을 때는 어떤 모습을 보이는지, 최대 자본감소(MDD)는 어떤지 확인해보도록 하겠습니다. 이전 포스팅에서 진행했던 내용을 이어서 진행할 것이기 때문에, 아직 VAA 전략 백테스트 기본편을 보시지 못한 분들은 아래의 포스팅 링크 참조 부탁드립니다 : )

 

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

 

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

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

lazyquant.tistory.com

 

1. 로그 스케일 수익률 확인

 지난 포스팅에서는 일반적인 수익률을 확인했었는데요. 저도 다른 글들을 참고하면서 공부하다가 일반적인 누적 수익률 그래프는 현상을 왜곡해서 해석하게 될 여지가 많다는 사실을 알게 되었습니다. 자세한 내용은 아래 글을 참고해주세요.

 

https://steemit.com/tooza/@jongsiksong/2zp8zf

 

로그 차트를 봐야하는 이유 (장기 성장률, 수익률, % 기울기 참고할 때) — Steemit

리니어 vs. 로그 HTS에서 제공하는 차트는 물론이고, 포털에서 제공하는 차트, 그리고 각종 장기 경제 지표들을 표시하는 차트들도 의외로 리니어 형태로 데이터를 보여주는 경우가 많습니다. 우�

steemit.com

 

 그래서 저도 지난 포스팅에서 일반적인 수익률로 계산했던 것을, 로그 수익률로 재계산해보려고 합니다. 직접 파이썬을 이용하여 확인해보고 싶으신 분들은 아래 소스 코드를 참조해주세요.

 

 

더보기
# 매월 수익률 & 누적 수익률 계산
df_VAA['PROFIT'] = 0
df_VAA['PROFIT_ACC'] = 0
df_VAA['LOG_PROFIT'] = 0
df_VAA['LOG_PROFIT_ACC'] = 0

for i in range(len(df_VAA)):
    profit = 0
    log_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']
            log_profit = math.log(df_VAA.iloc[i]['PRICE'] / df_VAA.iloc[i-1]['PRICE'])
         
        #지난달과 다른 자산 보유
        else :
            profit = (df_VAA.iloc[i][df_VAA.iloc[i-1]['ASSET']] - df_VAA.iloc[i-1]['PRICE']) / df_VAA.iloc[i-1]['PRICE']
            log_profit = math.log(df_VAA.iloc[i][df_VAA.iloc[i-1]['ASSET']] / df_VAA.iloc[i-1]['PRICE'])
    
    df_VAA.loc[df_VAA.index[i], 'PROFIT'] = profit * 100
    df_VAA.loc[df_VAA.index[i], 'PROFIT_ACC'] = ((1+df_VAA.loc[df_VAA.index[i-1], 'PROFIT_ACC']/100)*(1+profit)-1)*100
    df_VAA.loc[df_VAA.index[i], 'LOG_PROFIT'] = log_profit * 100
    df_VAA.loc[df_VAA.index[i], 'LOG_PROFIT_ACC'] = df_VAA.loc[df_VAA.index[i-1], 'LOG_PROFIT_ACC'] + log_profit * 100

 

 

월별 로그 수익률, 누적 수익률

 

 로그 스케일로 계산된 수익률을 그래프로 나타내면 아래와 같습니다. 지난 포스팅에서 일반적인 수익률로 비교했을 때에는 최근 수익률만 급격하게 높아진 것으로 해석될 여지가 있었으나, 로그 스케일 수익률을 확인하니 과거에도 충분히 높은 수익률을 기록한 적이 있었고, 2010년도에 들어서는 꾸준한 상승률을 보이고 있음을 확인할 수 있습니다.

 

로그 스케일 그래프

 

2. 타 자산 지수와의 비교(나스닥, S&P 500)

 이렇게 그래프를 확인하면 꾸준히 우상향하는 그래프로 상당히 좋은 수익을 낸 것처럼 보여집니다. 그러나 대부분의 자산이 장기적으로 보았을 때 우상향한다는 사실을 생각해보면, VAA 전략의 수익률 이렇게 우상향 그래프를 그린다고 해서 '특별히' 좋은 전략인가?라는 의문을 가질 수 있습니다. 그래서 이 VAA 전략이 같은 기간동안의 다른 지수들과는 얼마나 차이가 나는지 확인해보도록 하겠습니다.

 

 비교 자산으로는 상장 지수 펀드 중 나스닥과 S&P 500 지수를 추종하는, QQQ와 SPY로 선정하였습니다. 동일한 방식으로 과거 10년치의 데이터를 불러오고, 월별 로그 수익률과 누적 수익률을 계산합니다.

 

 

더보기
df_COMP = df_COMP[start_day:end_day]
df_COMP = df_COMP.resample(rule='M').apply(lambda x: x[-1])

# 매월 수익률 & 누적 수익률 계산
df_COMP['QQQ_LP'] = 0
df_COMP['QQQ_LPA'] = 0
df_COMP['SPY_LP'] = 0
df_COMP['SPY_LPA'] = 0

for i in range(len(df_COMP)):
    if i != 0: 
        df_COMP.loc[df_COMP.index[i], 'QQQ_LP'] = math.log(df_COMP.iloc[i]['QQQ'] / df_COMP.iloc[i-1]['QQQ']) * 100
        df_COMP.loc[df_COMP.index[i], 'SPY_LP'] = math.log(df_COMP.iloc[i]['SPY'] / df_COMP.iloc[i-1]['SPY']) * 100
        df_COMP.loc[df_COMP.index[i], 'QQQ_LPA'] = df_COMP.loc[df_COMP.index[i-1], 'QQQ_LPA'] + math.log(df_COMP.iloc[i]['QQQ'] / df_COMP.iloc[i-1]['QQQ']) * 100
        df_COMP.loc[df_COMP.index[i], 'SPY_LPA'] = df_COMP.loc[df_COMP.index[i-1], 'SPY_LPA'] + math.log(df_COMP.iloc[i]['SPY'] / df_COMP.iloc[i-1]['SPY']) * 100

 

 

QQQ와 SPY의 월별, 누적 수익률

 

 

 이렇게 계산된 QQQ와 SPY의 수익률을 이전에 계산했던 VAA 전략 수익률과 같이 그래프로 표시해보겠습니다.

 

 

더보기
df_LPA = pd.concat([df_VAA[['LOG_PROFIT','LOG_PROFIT_ACC']], df_COMP[['QQQ_LP','QQQ_LPA','SPY_LP','SPY_LPA']]],axis=1)
df_LPA.columns = ['VAA_LP','VAA_LPA','QQQ_LP','QQQ_LPA','SPY_LP','SPY_LPA']
df_LPA = df_LPA.reset_index()

plt.figure(figsize=(15,5))
sns.lineplot(x='Date', y='value', hue='variable', data=pd.melt(df_LPA, id_vars='Date', value_vars=['VAA_LPA','QQQ_LPA', 'SPY_LPA']))

 

 

자산별 누적 수익률

 

 결과를 그래프로 나타내보았습니다. QQQ(NASDAQ) - SPY(S&P 500) - VAA 전략 순으로 수익률이 높았습니다. 놀랍게도(?) VAA전략이 수익률 측면에서 꼴찌를 차지했습니다. 수익률 끝판왕이라고 포스팅을 했는데, 이 그래프만 본다면 그냥 NASDAQ과 S&P 500에 베팅하는게 더 좋은 전략처럼 보여집니다.

 

 하지만 여기서 알아야 할 사실은 지난 10년간 미국 주식은 전 세계적으로 가장 호황을 누렸던 시장이라는 점입니다. 동적 자산 배분 전략과 가장 잘 나갔던 전략을 단순히 수익률로만 비교한다면 상대가 안 되는게 당연한 사실입니다. 2020년이 된 지금은 결과적으로 지난 10년간 미국 주식 시장이 가장 호황이었다는 사실을 알지만, 미래 10년간은 또 어떤 자산이 가장 잘 나갈지 알 수 없기 때문에, 안정성 측면을 고려한다면 VAA 전략을 선택할만한 이유는 충분해집니다.

 

3. MDD 계산 및 비교

 또한 어떠한 전략을 선택할 때 고려해야할 추가적인 지표가 한 가지 있습니다. 바로 최고점 대비 얼마나 많은 자산이 감소하느냐(한 번에 얼마나 많이 깨졌느냐)를 나타내는 MDD(Max Draw Down)입니다. 결과적으로 수익률 그래프를 본다면 QQQ가 가장 좋은 수익률을 냈기 때문에, QQQ를 선택하면 좋겠구나라고 생각할 수도 있지만, 사람의 심리상 한 번에 많은 손실이 발생하면 견디지 못 하고 전략 운영을 중단하는 사례가 빈번히 발생합니다. 그렇게 되면 장기적으로 수익을 낼 수 있는 자산임에도 불구하고, 수익 맛보지 못하고 포기하게 됩니다.

 

 

더보기
start_asset = 1000
df_MDD = df_LPA
df_MDD[['VAA_ASSET','QQQ_ASSET','SPY_ASSET','VAA_MAX','QQQ_MAX','SPY_MAX','VAA_MDD','QQQ_MDD','SPY_MDD']] = 0

for i in range(len(df_MDD)):
    if i == 0:
        df_MDD.loc[i, 'VAA_ASSET'] = start_asset
        df_MDD.loc[i, 'QQQ_ASSET'] = start_asset
        df_MDD.loc[i, 'SPY_ASSET'] = start_asset
        df_MDD.loc[i, 'VAA_MAX'] = start_asset
        df_MDD.loc[i, 'QQQ_MAX'] = start_asset
        df_MDD.loc[i, 'SPY_MAX'] = start_asset
        
    else :
        df_MDD.loc[i, 'VAA_ASSET'] = df_MDD.loc[i-1, 'VAA_ASSET'] * (1+df_MDD.loc[i, 'VAA_LP']/100)
        df_MDD.loc[i, 'QQQ_ASSET'] = df_MDD.loc[i-1, 'QQQ_ASSET'] * (1+df_MDD.loc[i, 'QQQ_LP']/100)
        df_MDD.loc[i, 'SPY_ASSET'] = df_MDD.loc[i-1, 'SPY_ASSET'] * (1+df_MDD.loc[i, 'SPY_LP']/100)
        
        # MDD 계산
        if df_MDD.loc[i, 'VAA_ASSET'] > df_MDD.loc[i-1, 'VAA_ASSET']: 
            df_MDD.loc[i, 'VAA_MAX'] = df_MDD.loc[i, 'VAA_ASSET']
            df_MDD.loc[i, 'VAA_MDD'] = (df_MDD.loc[i, 'VAA_ASSET'] - df_MDD.loc[i, 'VAA_MAX']) / df_MDD.loc[i, 'VAA_MAX'] * 100
        else : 
            df_MDD.loc[i, 'VAA_MAX'] = df_MDD.loc[i-1, 'VAA_MAX']
            df_MDD.loc[i, 'VAA_MDD'] = (df_MDD.loc[i, 'VAA_ASSET'] - df_MDD.loc[i, 'VAA_MAX']) / df_MDD.loc[i, 'VAA_MAX'] * 100
            
        # MDD 계산
        if df_MDD.loc[i, 'QQQ_ASSET'] > df_MDD.loc[i-1, 'QQQ_ASSET']: 
            df_MDD.loc[i, 'QQQ_MAX'] = df_MDD.loc[i, 'QQQ_ASSET']
            df_MDD.loc[i, 'QQQ_MDD'] = (df_MDD.loc[i, 'QQQ_ASSET'] - df_MDD.loc[i, 'QQQ_MAX']) / df_MDD.loc[i, 'QQQ_MAX'] * 100
        else : 
            df_MDD.loc[i, 'QQQ_MAX'] = df_MDD.loc[i-1, 'QQQ_MAX']
            df_MDD.loc[i, 'QQQ_MDD'] = (df_MDD.loc[i, 'QQQ_ASSET'] - df_MDD.loc[i, 'QQQ_MAX']) / df_MDD.loc[i, 'QQQ_MAX'] * 100
            
        # MDD 계산
        if df_MDD.loc[i, 'SPY_ASSET'] > df_MDD.loc[i-1, 'SPY_ASSET']: 
            df_MDD.loc[i, 'SPY_MAX'] = df_MDD.loc[i, 'SPY_ASSET']
            df_MDD.loc[i, 'SPY_MDD'] = (df_MDD.loc[i, 'SPY_ASSET'] - df_MDD.loc[i, 'SPY_MAX']) / df_MDD.loc[i, 'SPY_MAX'] * 100
        else : 
            df_MDD.loc[i, 'SPY_MAX'] = df_MDD.loc[i-1, 'SPY_MAX']
            df_MDD.loc[i, 'SPY_MDD'] = (df_MDD.loc[i, 'SPY_ASSET'] - df_MDD.loc[i, 'SPY_MAX']) / df_MDD.loc[i, 'SPY_MAX'] * 100

 

 

QQQ, SPY, VAA의 MDD 그래프

 

 

 그래프를 확인하면 알 수 있지만, QQQ와 SPY는 10년동안 10% 이상 깨진 시기가 존재하지만, VAA 전략의 경우 최대로 손실을 많이 보았을 때가 -8.43%입니다. (QQQ : -17.68%, SPY : -20.52%) 올해 초 코로나로 인한 대폭락 시기에도 VAA 전략은 상당히 잘 방어했다는 사실이 인상적입니다.

 

 이처럼 VAA 전략과 같은 동적 자산 배분 전략은 한 가지 자산에 몰빵하는 상황과 비교했을 때 수익률은 더 적지만, 훨씬 더 안정적으로 운영할 수 있다는 장점이 있습니다. 투자자의 대부분이 심리적인 요인에 의해 실패한다는 사실을 생각해본다면, MDD가 낮으면서도 인상적인 수익률을 보여주는 VAA 전략을 선택하는 것이 좋은 선택지로 보여집니다. 

댓글()