모멘텀 팩터란?
모멘텀 팩터(Momentum Factor)는 최근 수익률이 높았던 자산이 계속 상승하고, 낮았던 자산이 계속 하락하는 경향을 체계적으로 포착하는 퀀트 투자 전략입니다. 1993년 Jegadeesh & Titman의 논문 이후 가장 견고한 시장 이상 현상(anomaly) 중 하나로 인정받고 있습니다.
글로벌 주식, 채권, 원자재, 암호화폐 등 거의 모든 자산군에서 모멘텀 효과가 관찰되며, AQR·Dimensional·BlackRock 같은 대형 자산운용사들이 핵심 팩터로 활용하고 있습니다.
모멘텀의 두 가지 유형
| 구분 | 횡단면 모멘텀 | 시계열 모멘텀 |
|---|---|---|
| 비교 대상 | 자산 간 상대 성과 | 자산 자체의 과거 수익률 |
| 매매 방식 | 상위 매수 + 하위 매도(롱숏) | 양(+)이면 매수, 음(-)이면 매도 |
| 시장 노출 | 시장 중립 가능 | 방향성 노출 있음 |
| 위기 대응 | 모멘텀 크래시 취약 | 하락장 자동 헷지 |
| 대표 연구 | Jegadeesh & Titman (1993) | Moskowitz, Ooi & Pedersen (2012) |
횡단면 모멘텀 전략 구현
여러 종목 중 최근 수익률 상위를 매수하고 하위를 매도하는 전략입니다. 파이썬 자동매매 시스템에 적용할 수 있는 코드를 살펴봅니다.
import numpy as np
import pandas as pd
class CrossSectionalMomentum:
def __init__(self, formation=12, skip=1, holding=1,
top_pct=0.2, bottom_pct=0.2):
"""
formation: 모멘텀 측정 기간 (월)
skip: 최근 제외 기간 (월) — 단기 반전 회피
holding: 보유 기간 (월)
top_pct: 상위 비율 (롱)
bottom_pct: 하위 비율 (숏)
"""
self.formation = formation
self.skip = skip
self.holding = holding
self.top_pct = top_pct
self.bottom_pct = bottom_pct
def compute_momentum(self, prices: pd.DataFrame) -> pd.DataFrame:
"""12-1 모멘텀 스코어 계산"""
total_period = self.formation + self.skip
past = prices.shift(self.skip * 21) # skip 기간 이전
start = prices.shift(total_period * 21) # formation 시작
momentum = (past - start) / start
return momentum
def rank_and_select(self, momentum: pd.Series) -> dict:
"""모멘텀 기준 상위/하위 종목 선정"""
valid = momentum.dropna()
n = len(valid)
top_n = max(1, int(n * self.top_pct))
bottom_n = max(1, int(n * self.bottom_pct))
ranked = valid.sort_values(ascending=False)
longs = ranked.head(top_n).index.tolist()
shorts = ranked.tail(bottom_n).index.tolist()
return {'long': longs, 'short': shorts}
def generate_weights(self, prices: pd.DataFrame,
date_idx: int) -> dict:
"""특정 시점의 포트폴리오 비중 생성"""
momentum = self.compute_momentum(prices)
mom_scores = momentum.iloc[date_idx]
selection = self.rank_and_select(mom_scores)
weights = {}
long_w = 1.0 / len(selection['long'])
short_w = -1.0 / len(selection['short'])
for s in selection['long']:
weights[s] = long_w
for s in selection['short']:
weights[s] = short_w
return weights
시계열 모멘텀 전략 구현
각 자산의 과거 수익률 부호에 따라 방향을 결정하는 전략입니다. 하락장에서 자동으로 숏 포지션을 잡아 위기 방어 능력이 뛰어납니다.
class TimeSeriesMomentum:
def __init__(self, lookbacks=[1, 3, 6, 12],
vol_target=0.10):
"""
lookbacks: 여러 룩백 기간 (월) — 앙상블
vol_target: 자산별 변동성 타겟
"""
self.lookbacks = lookbacks
self.vol_target = vol_target
def signal(self, prices: pd.Series,
lookback_months: int) -> float:
"""단일 룩백 시계열 모멘텀 시그널"""
days = lookback_months * 21
if len(prices) < days:
return 0.0
ret = prices.iloc[-1] / prices.iloc[-days] - 1
return np.sign(ret) # +1 또는 -1
def ensemble_signal(self, prices: pd.Series) -> float:
"""여러 룩백 기간 앙상블 시그널"""
signals = [self.signal(prices, lb)
for lb in self.lookbacks]
return np.mean(signals) # -1 ~ +1 연속 시그널
def position_size(self, prices: pd.Series) -> float:
"""변동성 조정 포지션 크기"""
sig = self.ensemble_signal(prices)
# 실현 변동성 (60일)
returns = prices.pct_change().dropna()
realized_vol = returns.tail(60).std() * np.sqrt(252)
if realized_vol == 0:
return 0.0
# 시그널 × 변동성 타겟 / 실현 변동성
weight = sig * (self.vol_target / realized_vol)
return np.clip(weight, -2.0, 2.0) # 레버리지 상한
모멘텀 크래시 방어
모멘텀 전략의 가장 큰 리스크는 모멘텀 크래시입니다. 급격한 시장 반전 시 과거 패자(loser)가 급등하고 과거 승자(winner)가 급락하면서 큰 손실이 발생합니다. 2009년 3월이 대표적인 사례입니다.
class MomentumCrashDefense:
def __init__(self, base_strategy, crash_lookback=126):
self.strategy = base_strategy
self.crash_lookback = crash_lookback
def market_stress_indicator(self,
market_prices: pd.Series) -> float:
"""시장 스트레스 지표 (변동성 + 하락폭 기반)"""
returns = market_prices.pct_change().dropna()
recent = returns.tail(self.crash_lookback)
# 실현 변동성 대비 장기 변동성
short_vol = returns.tail(21).std()
long_vol = returns.tail(252).std()
vol_ratio = short_vol / long_vol if long_vol > 0 else 1
# 최근 최대 낙폭
cum = (1 + recent).cumprod()
drawdown = (cum / cum.cummax() - 1).min()
# 스트레스 스코어 (0~1, 높을수록 위험)
stress = min(1.0, max(0.0,
0.5 * (vol_ratio - 1) + 0.5 * abs(drawdown)))
return stress
def adjusted_weight(self, raw_weight: float,
market_prices: pd.Series) -> float:
"""스트레스 비례 포지션 축소"""
stress = self.market_stress_indicator(market_prices)
# 스트레스 높으면 포지션 축소
scaling = max(0.2, 1.0 - stress)
return raw_weight * scaling
서킷브레이커와 함께 사용하면 모멘텀 크래시 시 자동으로 거래를 중단하는 추가 방어선을 구축할 수 있습니다.
듀얼 모멘텀: 횡단면 + 시계열 결합
Gary Antonacci가 제안한 듀얼 모멘텀은 두 유형을 결합해 성과를 극대화합니다.
class DualMomentum:
def __init__(self, assets, safe_asset='BIL',
lookback=12):
"""
assets: 투자 대상 자산 리스트
safe_asset: 안전자산 (단기채 등)
lookback: 모멘텀 측정 기간 (월)
"""
self.assets = assets
self.safe_asset = safe_asset
self.lookback = lookback
def select(self, prices: pd.DataFrame) -> str:
"""듀얼 모멘텀 자산 선택"""
days = self.lookback * 21
# 1단계: 횡단면 — 상대 모멘텀 최강 자산
mom_scores = {}
for asset in self.assets:
p = prices[asset]
if len(p) >= days:
mom_scores[asset] = p.iloc[-1] / p.iloc[-days] - 1
if not mom_scores:
return self.safe_asset
best_asset = max(mom_scores, key=mom_scores.get)
# 2단계: 시계열 — 절대 모멘텀 필터
if mom_scores[best_asset] > 0:
return best_asset # 양의 모멘텀 → 투자
else:
return self.safe_asset # 음의 모멘텀 → 안전자산
def backtest(self, prices: pd.DataFrame,
rebal_freq=21) -> pd.Series:
"""듀얼 모멘텀 백테스트"""
all_assets = self.assets + [self.safe_asset]
returns = prices[all_assets].pct_change().dropna()
portfolio_returns = []
for i in range(self.lookback * 21, len(returns)):
if (i - self.lookback * 21) % rebal_freq == 0:
hist = prices.iloc[:i+1]
selected = self.select(hist)
portfolio_returns.append(returns[selected].iloc[i])
return pd.Series(portfolio_returns,
index=returns.index[self.lookback*21:])
모멘텀 팩터 성과 특성
학술 연구와 실증 데이터 기반 모멘텀 팩터의 주요 특성입니다:
- 연평균 초과 수익: 미국 주식 기준 연 6~10% 롱숏 프리미엄 (1927~2024)
- 글로벌 보편성: 40개국 이상에서 통계적으로 유의한 모멘텀 효과 확인
- 최적 기간: 12개월 형성기간, 최근 1개월 제외(12-1)가 표준
- 최대 약점: 시장 급반전 시 모멘텀 크래시 (2009년 3월: 한 달 -40% 이상)
- 다른 팩터와 상관관계: 가치(Value) 팩터와 음의 상관 → 결합 시 분산 효과
실전 적용 가이드
- 리밸런스 주기: 월 1회가 표준. 주간 리밸런스는 거래비용 대비 개선 효과가 미미합니다.
- 유니버스: 유동성 충분한 대형주 위주로 구성. 소형주는 슬리피지 리스크가 큽니다.
- 거래비용: 모멘텀 전략은 회전율이 높아(연 200%+) 거래비용 관리가 핵심입니다.
- 팩터 결합: 모멘텀 단독보다 가치·퀄리티 팩터와 결합하면 위험 대비 수익이 개선됩니다.
- 암호화폐 적용: 1~4주 단기 모멘텀이 효과적. 장기 모멘텀은 구조 변화가 잦아 불안정합니다.
마무리
모멘텀 팩터는 가장 오래되고 견고한 퀀트 투자 전략 중 하나입니다. 횡단면과 시계열 모멘텀을 이해하고, 듀얼 모멘텀으로 결합하며, 모멘텀 크래시 방어까지 갖추면 체계적인 자동매매 시스템의 핵심 알파 엔진으로 활용할 수 있습니다. 파이썬으로 구현하면 데이터 수집부터 백테스트, 실시간 시그널 생성까지 전 과정을 자동화할 수 있습니다.