자산배분

TQQQ, TMF 절대 모멘텀 백테스트(2)

unius 2022. 12. 26. 11:16
728x90
반응형

지난글에서는 TQQQ 한 종목만으로 1~12개월 절대 모멘텀을 기준으로 백테스트를 수행하여 보았다. 결과는 만족스럽지 못했다. 이번 글에서는 TQQQ와 TMF 2개의 종목으로 1~12개월 절대 모멘텀 기준의 백테스트 결과를 공유하고 절대 모멘텀 기준을 만족하는 종목을 선택하기 위해 bt패키지의 Algo클래스를 상속해서 재정의한 SelectAbsoluteMomentum 클래스를 설명한다.

 

먼저 전략을 생성하고 해당 전략으로 백테스트 객체를 생성하는 코드를 살펴보자.

# 절대모멘텀 백테스트
def AbsoluteMomentum_BT(assets, rank, months, start_day, run_on_end_of_period=False, lag=1, name='Absolute 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),
                           SelectAbsoluteMomentum(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)

전략 생성시에 사용된 SelectAbsoluteMomentum()이 새롭게 정의한 클래스로 첫번째 인자로 순위가 주어진다. 이것은 백테스트 대상 종목들 중에서 절대 모멘텀 기준을 만족하는 종목을 몇개까지 선택할 것인지를 정하는 것이다. 우리는 이번 백테스트에서 TQQQ와 TMF 2개의 종목을 대상으로 절대 모멘텀 기준을 만족하는 종목을 최대 2개 선택할 것이므로 순위 인자로 2를 전달할 것이다.  예를 들어 12개월 절대 모멘텀 기준으로 판단한다면 TQQQ와 TMF 중에서 12개월 수익률이 양수인 종목을 최대 2개 선택할 것이다. 따라서 2개 종목 모두 양수이면 SelectAbsoluteMomentum()에 의해 2개 종목이 선택되고 WeighEqually() 에 의해 5:5의 비율로 Rebalance()가 수행될 것이고 1개 종목만 양수라면 1개 종목만 선택되고 해당 종목에 100% 비중으로 리밸런싱되는 것이다.

 

SelectAbsoluteMomentum()의 두번째 인자는 모멘텀 판단 기간으로 아래 코드와 같이 for문에 의해 1~12 개월이 입력되어 총 12번의 백테스트를 수행하고 그 결과를 비교하는 것이다.

# 절대모멘텀 상위 2종목 (1~12개월 비교)
absolutemomentum = {}
for i in range(0, 12):   
    absolutemomentum[i] = AbsoluteMomentum_BT(assets[tickers], 2, i+1, start_day, False, 1, name='AM({})'.format(str(i+1)))
am2_report = bt.run(*absolutemomentum.values())

SelectAbsoluteMomentum()의 세번째 인자를 보기전에 RunMonthly()의 두번째 인자인 run_on_end_of_period에 False 값을 전달할 것이다. 이것은 매월 초에 리밸런싱을 한다는 의미이다. 그리고 SelectAbsoluteMomentum()의 세번째 인자인 lag에 1을 할당하면 모멘텀 판단시에 리밸런싱을 하는 매월 초. 즉, 당일에서 하루전 날짜로부터 lookback 기간만큼으로 모멘텀을 판단하게 된다. 이렇게 하는 이유는 우리가 실제 현실 상황에서는 리밸런싱 하는 당일의 종가를 포함하여 모멘텀을 판단하고 당일의 종가로 리밸런싱 하기가 매우 어렵기 때문이다. 따라서 리밸런싱 당일에 전일 종가까지만으로 모멘텀을 판단하고 당일 종가로 리밸런싱을 수행하는 것이다.

SelectAbsoluteMomentum() 전체 코드를 천천히 참고해사 살펴보면 보면 이해가 될 듯하다.

#절대모멘텀 종목 선정
class SelectAbsoluteMomentum(bt.Algo):
    def __init__(self, rank, lookback=pd.DateOffset(months=1), lag=pd.DateOffset(days=1)):
        super(SelectAbsoluteMomentum, 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]
        momentum = prc.calc_total_return()
        rank = momentum.rank(ascending=False)
        
        selected = pd.Series(dtype=object)
        for i in range(0, len(momentum)):
            if (rank[assets[i]] <= self.rank) & (momentum[i] > 0):
                selected = pd.concat([selected, pd.Series([assets[i]],index=[assets[i]],dtype=object)])
                
        target.temp['selected'] = selected.drop_duplicates()         
        return True

이제 TQQQ와 TMF 2개 종목으로 1~12개월 백테스트를 수행한 결과를 살펴보자.

결과를 보면 상대 모멘텀보다 MDD가 많이 개선된 것을 알 수 있다. 전반적으로 MDD가 -50% 근처에 있고 연수익률도 20~25%가 넘는 것들이 여럿 보인다. 특히 6개월 모멘텀의 경우는 연수익률 30%를 초과 하면서 MDD는 -44% 정도를 보이고 있다. 이 정도면 이제 어느 정도 위험을 감수하고 투자해 볼 수도 있지 않을까 하는 생각이 든다. 하지만 조금 더 욕심을 내서 계속 다른 방식으로 백테스트를 해볼 것이다. 다음 글에서는 평균 모멘텀 스코어 방식으로 백테스트를 수행하여 볼 것이다.

 

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