자산배분

TQQQ, TMF 듀얼 모멘텀 백테스트

unius 2023. 1. 9. 16:15
728x90
반응형

TQQQ, TMF 종목으로 백테스트 결과를 공유하기 시작한 지 벌써 한달이 되었다. 진작에 다 올렸어야 하는데 게으르다 보니 많이 늦어졌다.  오늘부터 마음을 다잡고 다시 부지런히 올려보겠다. 지난글에서 1~12개월 절대 모멘텀을 살펴보았고 이번글에서는 평균모멘텀 방식의 결과를 공유하려 했으나 순서를 바꾸어서 이번글에서는 듀얼 모멘텀을 테스트해 보려한다.

 

먼저 간단하게 듀얼 모멘텀을 알아보면 널리 잘 알려진 듀얼 모멘텀 전략들이 있다. 원조 격이라고 할 수 있는 게리 안토나치의 오리지널 듀얼 모맨텀 전략이 대표적이고 이를 변형한 가속 듀얼 모멘텀 전략도 있으며 조금씩 변형된 많은 전략들이 존재하지만 듀얼 모멘텀은 기본적으로 투자자산, 비교자산, 안전자산의 3가지의 자산군으로 구성되고 기본적인 동작 원리는 해당 투자자산과 비교자산의 모멘텀을 비교하여 비교자산보다 모멘텀이 좋으면 매수하고 그렇지 못한 경우에는 해당 투자자산을 매도하고 안전자산을 매수하는 전략이다. 일반적으로 상대 모멘텀과 절대 모멘텀의 장점을 혼합하여 수익률은 높이면서 MDD를 낮춘다고 알려져 있다.

 

서두가 길었다. 본격적으로 TQQQ, TMF 를 투자자산으로 하는 듀얼 모멘텀 전략을 살펴보자.

# 투자자산
tickers = ['TQQQ','TMF']
# 비교자산,안전자산
dualtickers = ['BND','BIL']

# 월초 리밸런싱
run_on_end_of_period = False
# 지연시간 1일, 하루전 종가 기준으로 리밸런싱
lag = 1

비교자산과 안전자산을 무엇으로 선택하는 지에 따라서 결과는 많이 달라지게 된다. 나는 비교자산으로 다양한 미국 채권으로 구성된 BND ETF와 안전자산으로 미국 초단기 국채인 BIL ETF를 선택하였다.

# 듀얼모멘텀 백테스트
def DualMomentum_BT(assets, rank, months, start_day, run_on_end_of_period=False, lag=1, name='Dual Momentum'):
    s = bt.Strategy(name, [bt.algos.RunAfterDate(start_day),
                           bt.algos.RunMonthly(run_on_first_date=False, run_on_end_of_period=run_on_end_of_period, run_on_last_date=False),
                           SelectDualMomentum(rank=rank, lookback=pd.DateOffset(months=months), lag=pd.DateOffset(days=lag)),
                           bt.algos.WeighEqually(),
                           bt.algos.Rebalance()])
    return bt.Backtest(s, assets, initial_capital=100000000.0)

듀얼 모멘텀을 판단하여 대상 종목을 선정하는 사용자 정의 클래스로 SelectDualMomentum() 을 사용하고 월 1회 리밸런싱하는 것으로 전략을 생성하고 백테스트 객체를 생성한다. 이전 글들을 자세히 읽은 사람들은 알아챘을 지도 모르겠는데 절대 모멘텀 백테스트 부터는 리밸런싱 주기를 월 1회로 테스트 하였다. 그 이전의 고정비중이나 상대모멘텀은 분기 1회로 리밸런싱하여 테스트 하였다. 차이는 RunQuarterly()와 RunMonthly() 에 있다. 이렇게 한 이유는 동일하게 분기 1회로도 해보았지만 유의미한 결과를 얻을 수 없어서 월 1회로 변경하였다.

이제 위에서 생성한 백테스트 객체로 아래와 같이 1~12개월 모멘텀으로 백테스트를 수행하였다.

# 듀얼모멘텀 상위 2종목 (1~12개월 비교)
dualmomentums = {}
for i in range(0, 12):
    dualmomentums[i] = DualMomentum_BT(assets, 2, i+1, start_day, False, lag, name='ODM({})'.format(str(i+1)))

dm2_report = bt.run(*dualmomentums.values())

위 코드에서 DualMomentum_BT()의 두번째 인자인 '2'는 선택될 종목의 최대 개수를 의미한다. 즉, TQQQ, TMF 2종목 모두 BND 보다 모멘텀이 좋다면 WeighEqually()에 의해 5:5의 비중으로 투자하게 된다. 따라서 TQQQ 종목만 BND 보다 모멘텀이 좋은 경우에는 TQQQ와 BIL 종목에 5:5의 비중으로 투자하게 되는 것이다. 듀얼 모멘텀에 따른 백테스트 결과는 아래와 같다.

결과를 보면 절대 모멘텀 보다 CAGR이 낮지만 절대 모멘텀의 CAGR이 모멘텀 개월수에 따라서 편차가 있었던 반면에 듀얼 모멘텀은 편차가 심하지 않고 15% 근처에서 형성되었음을 알 수 있고 MDD는 절대 모멘텀 보다 확실히 개선되어 대체로 -40% 초반을 기록함을 확인할 수 있다. 안정적인 성향의 투자자라면 절대 모멘텀 보다는 듀얼 모멘텀이 조금 더 나아보이긴 한다.

 

참고로 듀얼 모멘텀을 판단하는 사용자 정의 클래스는 아래와 같이 첨부한다.

# 듀얼모멘텀 종목 선정
class SelectDualMomentum(bt.Algo):
    """
    듀얼모멘텀 종목을 선정한다.
        Args:
            rank : 상대모멘텀으로 선택할 종목의 개수
            lookback : 반추기간(기본값: 12개월)
            lag : 리밸런스 지연일(기본값: 1일)
        Returns:
            target.temp['selected']에 듀얼모멘텀 종목을 반환
    """
    def __init__(self, rank=1, lookback=pd.DateOffset(months=1), lag=pd.DateOffset(days=1)):
        super(SelectDualMomentum, self).__init__()
        self.rank = rank
        self.lookback = lookback
        self.lag = lag
    
    def __call__(self, target):
        assets = target.universe.columns
        end = target.now - self.lag
        start = end - self.lookback
        prc = target.universe.loc[start:end][assets[0:len(assets)-1]]
        momentum = prc.calc_total_return()
        rank = momentum[assets[0:len(assets)-2]].rank(ascending=False)
        
        selected = pd.Series(dtype=object)
        for i in range(0, len(assets)-2):
            if rank[assets[i]] <= self.rank:
                if momentum[assets[i]] > momentum[-1]:
                    selected = pd.concat([selected, pd.Series([assets[i]],index=[assets[i]],dtype=object)])
                else:
                    selected = pd.concat([selected, pd.Series([assets[-1]],index=[assets[-1]],dtype=object)])

        target.temp['selected'] = selected.drop_duplicates()
        return True

 

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
반응형