자산배분

TQQQ, TMF 상대 모멘텀 백테스트

unius 2022. 12. 14. 11:19
728x90
반응형

지난 글에서는 TQQQ, TMF 자산 사이의 상관계수와 고정 비중 백테스트를 수행해 보았다.

 

TQQQ, TMF 고정 비중 백테스트

나는 지난 4월부터 라오어님의 미국주식 무한매수법 이라는 서적을 읽고 TQQQ 무한매수를 시작했었다. 무한매수법 한 사이클이 40회로 구성되지만 난 한사이클도 끝내지 못하고 현재 원금 대비 -4

myportfolio.tistory.com

이번 글에서는 TQQQ, TMF 자산군에서 상대 모멘텀에 따른 백테스트를 수행해 볼 것이다. 먼저 모멘텀이란 용어를 먼저 살펴보면 원래 물리학에서 파생된 용어로 물체가 한 방향으로 지속적으로 움직이려는 경향을 의미한다. 이것이 투자 영역에서도 한번 올라가는 종목이 계속 오르더라는 경험과 이론으로 증명되어 오고 있다. 그리고 이와 같은 모멘텀에 기반한 수많은 전략들이 있다.

 

이번 글에서 다루는 모멘텀은 상대 모멘텀 전략이다. 상대 모멘텀이란 n개의 투자자산군에 내에서 모멘텀이 좋은 상위 m개의 자산에 투자하는 전략이다. 모멘텀을 판단하는 기준은 매우 다양하다고 할 수 있지만 일반적으로 1~12개월 수익률을 기준으로 판단한다. 예를 들면 10개의 투자자산들의 3개월 수익률을 구해서 상위 3개 자산에 투자하는 방식이다.

 

나는 TQQQ, TMF 3배 레버리지 ETF를 투자자산으로 고려하고 있으므로 이번 글에서는 분기별로 두개의 자산중에서 1~12개월 수익률이 더 좋은 한 종목에 투자하는 방식을 백테스트해 볼 것이다. 먼저 야후 파이낸스에서 데이터를 가져오는 방법은 동일하다.

data = yf.download(tickers, end='2022-12-10')['Adj Close']
data = data[tickers]
for c in data.columns:
    print(c, data[c].first_valid_index())
assets = data.dropna().copy()

start_day = assets.index.min() + pd.DateOffset(months=12)
print('asset \n', assets.head(30))
print('start day : ', start_day)

단지 지난 고정 비중 백테스트와 테스트 기간을 일치시키기 위해서 종료일자(end='2022-12-10')를 지정했고 1~12개월 모멘텀에 따른 비교를 위해 시작일자를 첫번째 데이터 날짜에서 12개월 후로 지정할 것이다. 지난 글에서의 백테스트 시작일자는 데이터의 첫번째 일자부터 수행했으나 이번에는 최대 12개월 모멘텀을 사용하기에 시작일자를 12개월 후로 변경한 것이다. 따라서 지난 백테스트 결과와 비교시에는 1년의 테스트 기간 차이가 있으므로 이를 고려해서 판단해야 한다.

 

수신한 데이터를 분기별로 모멘텀을 평가하고 더 나은 종목을 선택하여 리밸런싱하는 코드는 아래와 같다.

# 상대모멘텀 백테스트
def RelativeMomentum_BT1(assets, rank, months, start_day, run_on_end_of_period=False, lag=1, name='Relative Momentum'):
    s = bt.Strategy(name, [bt.algos.RunAfterDate(start_day),
                           bt.algos.RunQuarterly(run_on_first_date=False, run_on_end_of_period=run_on_end_of_period, run_on_last_date=False),
                           bt.algos.SelectAll(),
                           bt.algos.StatTotalReturn(lookback=pd.DateOffset(months=months), lag=pd.DateOffset(days=lag)),
                           bt.algos.SelectN(rank, sort_descending=True),
                           bt.algos.WeighEqually(),
                           #bt.algos.PrintTempData(),
                           bt.algos.Rebalance()])
    return bt.Backtest(s, assets, initial_capital=100000000.0)
    
# 상대모멘텀 상위 1종목 (1~12개월 비교)
relativemomentum = {}
for i in range(0, 12):
    relativemomentum[i] = RelativeMomentum_BT2(assets[tickers], 1, i+1, start_day, False, 1, name='RM({})'.format(str(i+1)))
    
rm1_report = bt.run(*relativemomentum.values())

bt 패키지를 이용하면 위와 같이 간단하게 구현할 수 있다. 정말 초보자도 누구나 쉽게 백테스트를 해볼 수가 있다. bt 패키지를 사용하여 백테스트 하는 과정은 간단하다.

  1. 전략을 생성한다. bt.Strategy() 여기서 전략 생성시 인자로 주어지는 것들은 전략을 구성하는 알고리즘 인스턴스들이다. 순서대로 해석하면 된다. 시작일자 이후에 실행하고 RunAfterDate(), 분기에 한번 RunQuarterly(), 입력된 모든 증권에 대해 SelectAll(), 모멘텀을 산출하고 StatTotalReturn(), 상위 종목을 선택하여 SelectN(), 리밸런싱을 Rebalance() 수행하는 전략이다.
  2. 생성된 전략과 자산군의 데이터를 인자로 백테스트 인스턴스를 생성한다.
  3. 마지막으로 생성된 백테스트를 수행한다. run()
rm1_report.plot(figsize=(20,7), grid=True, logy=True, title="Relative Momentum (1~12 month) with rank 1")
rm1_report.prices[start_day:].calc_stats().display()

상대 모멘텀 백테스트 결과는 실망스럽다. 리스크 헷지도 안되고 전체적으로 수익률도 이전 고정비중 백테스트 결과보다 나쁘다. 아무래도 각 자산의 수익률에 관계없이 무조건 더 나은 자산만 선택해서 100% 비중으로 투자하기 때문이다. 즉, 하락장에서 안전자산으로 도망가지 못하고 조금 덜 빠지는 자산에 몰빵하니 3배 레버리지에 따른 하락 충격을 그대로 흡수하는 것 같다. 다음 글에서는 모멘텀이 양수(+) 인 경우에만 투자하는 절대 모멘텀 백테스트를 수행해본다.

 

1편 : TQQQ, TMF 고정 비중 백테스트
2편 : TQQQ, TMF 상대 모멘텀 백테스트
3편 : TQQQ, TMF 절대 모멘텀 백테스트(1)
4편 : TQQQ, TMF 절대 모멘텀 백테스트(2)
5편: TQQQ,TMF 듀얼 모멘텀 백테스트
6편: TQQQ, TMF 평균 모멘텀 스코어 백테스트
7편: TQQQ, TMF 수익곡선 모멘텀 백테스트

8편: TQQQ, TMF 평균모멘텀 전략의 비중 계산 Algo 클래스

9편: TQQQ, TMF 가속듀얼모멘텀 백스트

 

☞ 이 글은 순수하게 개인적인 의도로 테스트한 결과이며 내용상 오류가 있을 수도 있습니다.

.

728x90
반응형