백테스트-수익률, MDD 시각화&그래프(feat.seaborn)

 안녕하세요, 게으른 퀀트입니다. 이런저런 주제로 다양하게 포스팅을 하다보니 한 주제로 우직하게 포스팅하기가 어렵네요🤣 백테스트 코드를 정리하면서 그래프를 그리는 방법에 대해서 다루기로 하였는데 잊고 있었습니다. 댓글로 다시 한 번 요청해주신 분이 계셔서, 후다닥 포스팅을 준비해보았습니다. 필요한 주제나 내용에 대해서 댓글로 알려주시면 최선을 다해 준비해보도록 하겠습니다. 언제나 환영이에요!!

 

 데이터 시각화는 다양한 방식으로 가능하겠지만, 저는 seaborn이라는 패키지를 사용합니다. anaconda를 사용하시는 분들은 아래 명령어로 간단하게 설치가 가능합니다.

 

# seaborn 설치 명령어
conda install -c anaconda seaborn

 

1. 데이터 준비

 데이터는 예전 포스팅에서 다루었던 수익률, MDD 데이터로 세팅해보도록 하겠습니다. 데이터는 S&P 500, 나스닥, 금, 단기채, 중기채를 사용할 예정입니다. 그래프를 다루는 포스팅이기 때문에 수익률, MDD를 구하는 코드에 대해서 상세한 설명은 생략하겠습니다. 

 

 혹시 각 코드에 대해 상세한 설명이 궁금하신 분들은 아래 포스팅들을 참고해주세요.

백테스트-수익률 구하는 방법(pandas-월별 수익률, 누적수익률, log 수익률, 누적 log 수익률)

백테스트-MDD 구하는 방법(pandas)

 

데이터 세팅 코드)

import pandas_datareader as pdr
import pandas as pd
from datetime import datetime, timedelta

pd.options.display.float_format = '{:.4f}'.format
pd.set_option('display.max_columns', None)

start_day = datetime(2005,1,1) # 시작일
end_day = datetime(2021,4,30) # 종료일

# 주가 데이터를 반환하는 함수
# x는 종목명이 포함된 리스트(ex: ['SPY','QQQ','GLD','SHY','IEF'])
def get_price_data(x):
    df_price = pd.DataFrame(columns=x)
    
    for ticker in x:
        df_price[ticker] = pdr.get_data_yahoo(ticker, start_day - timedelta(days=365), end_day)['Adj Close']  

    return df_price
    
# 조회할 종목을 리스트로 선언하고 호출
TICKER = ['SPY','QQQ','GLD','SHY','IEF']
df_PRICE = get_price_data(TICKER)

# 월별로 세팅
df_PRICE = df_PRICE.resample(rule='1M').last()

# 각 자산별 수익률 계산
col_list_P = [col+'_수익률' for col in df_PRICE[TICKER].columns]
col_list_PA = [col+'_누적 수익률' for col in df_PRICE[TICKER].columns]
col_list_LP = [col+'_로그 수익률' for col in df_PRICE[TICKER].columns]
col_list_LPA = [col+'_누적 로그 수익률' for col in df_PRICE[TICKER].columns]

df_PRICE[col_list_P] = df_PRICE[TICKER].pct_change()
df_PRICE[col_list_PA] = (1+df_PRICE[col_list_P]).cumprod()-1
df_PRICE[col_list_LP] = np.log(df_PRICE[col_list_P]+1)
df_PRICE[col_list_LPA] = df_PRICE[col_list_LP].cumsum()

# 백분율을 %로 전환
df_PRICE[col_list_P+col_list_PA+col_list_LP+col_list_LPA] = df_PRICE[col_list_P+col_list_PA+col_list_LP+col_list_LPA] * 100

# 가상의 잔고 필드와 낙폭 필드 추가
col_list_BAL = [col+'_BAL' for col in df_PRICE[TICKER_NAME].columns]
col_list_DD = [col+'_DD' for col in df_PRICE[TICKER_NAME].columns]

df_PRICE[col_list_BAL] = (1+df_PRICE[col_list_P]/100).cumprod()
df_PRICE[col_list_DD] = -(df_PRICE[col_list_BAL].cummax() - df_PRICE[col_list_BAL]) / df_PRICE[col_list_BAL].cummax()

# 백분율을 %로 전환
df_PRICE[col_list_BAL+col_list_DD] = df_PRICE[col_list_BAL+col_list_DD] * 100

 

2. 데이터 확인

 위의 코드에서 주가 데이터를 가져왔고, 필요한 수익률과 DD 필드를 세팅했습니다. 정상적으로 데이터가 세팅되었는지 확인해보겠습니다.

 

로그 누적 수익률 확인)

 

낙폭(Draw Down) 필드 확인)

 지금까지 필요한 데이터를 세팅해보았고, 이번 포스팅의 핵심인 그래프 그리는 방법은 아래에서 알아보도록 하겠습니다.

3. 데이터 시각화, 그래프 그리기

 이제 본격적으로 세팅된 데이터를 가지고 그래프를 그려보도록 하겠습니다. seaborn 패키지를 사용할 것이기 때문에 아주 간단하게 구현이 가능합니다.

 

구현 코드)

# 필요 패키지 import
import matplotlib.pyplot as plt
import seaborn as sns

# 한글 글꼴 세팅
plt.rcParams['font.family'] = 'NanumGothic'

# 그래프 사이즈 세팅
plt.figure(figsize=(15,5))

# 그래프 구현 코드
sns.lineplot(data=df_PRICE[col_list_LPA])

 

코드 실행 결과) 로그 누적 수익률 그래프

 seaborn 패키지를 활용하여 선, 막대, 산점도 등 다양한 그래프를 구현할 수 있습니다. 수익률과 MDD 그래프를 그릴 때는 선 그래프(lineplot)을 사용합니다. data라는 인수에 세팅된 데이터를 입력하면 자동으로 그래프를 예쁘게 그려 줍니다. x축은 DataFrame의 인덱스인 Date으로 세팅되고, y축은 누적 로그 수익률로 세팅됩니다.

 

data 인수의 값만 바꾸면 MDD 그래프도 그릴 수 있습니다. col_list_LPA를 col_list_DD로만 바꿔주면 낙폭 그래프가 그려집니다.

 

구현 코드)

plt.figure(figsize=(15,5))
sns.lineplot(data=df_PRICE[col_list_DD])

 

코드 실행 결과) MDD 그래프

 

 위에서 구현한 것처럼 이미 세팅된 데이터의 그래프를 그리는 방법은 매우 간단합니다. 잘 구현된 패키지를 그대로 사용하기만 하면 되기 때문이죠. 수익률과 MDD 뿐만 아니라 데이터를 다양한 방법으로 시각화 하는 방법을 연습한다면, 데이터에서 의미있는 인사이트를 도출해낼 수 있을 것입니다. 이 외에도 특정 데이터를 시각화하는 방법이 궁금하신 분들은 댓글로 알려주세요!

 


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

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

 

 

댓글()