변동성 타겟팅이란?
변동성 타겟팅(Volatility Targeting)은 포트폴리오의 변동성을 일정 수준으로 유지하는 리스크 관리 전략입니다. 시장 변동성이 높아지면 포지션을 줄이고, 변동성이 낮아지면 포지션을 늘려 일관된 리스크 수준을 유지합니다. 글로벌 헤지펀드와 연기금에서 가장 널리 사용하는 기법 중 하나입니다.
핵심 아이디어는 간단합니다. 변동성이 2배로 올라가면 포지션을 절반으로 줄이는 것입니다. 이를 통해 극단적 손실을 방지하면서도 안정적인 수익 곡선을 만들 수 있습니다.
왜 변동성 타겟팅이 필요한가?
고정 비율로 투자하면 시장 상황에 따라 실제 리스크가 크게 달라집니다.
- 저변동성 구간: 같은 투자 비율인데 리스크가 너무 낮아 기회비용 발생
- 고변동성 구간: 같은 투자 비율인데 리스크가 폭증하여 큰 손실 가능
- 변동성 클러스터링: 높은 변동성은 연속되는 경향이 있어 손실이 누적됨
변동성 타겟팅은 이 문제를 해결합니다. 시장이 불안할 때 자동으로 방어적 포지션을 취하고, 안정적일 때 적극적으로 투자합니다.
파이썬 구현: 기본 변동성 타겟팅
실현 변동성 기반의 기본 구현입니다. 목표 변동성 대비 현재 변동성의 비율로 포지션 크기를 조절합니다.
import numpy as np
import pandas as pd
import yfinance as yf
# 데이터 로드
data = yf.download('SPY', start='2015-01-01', end='2025-12-31')
returns = data['Close'].pct_change().dropna()
def volatility_targeting(returns, target_vol=0.15, lookback=20,
max_leverage=1.5, min_weight=0.1):
"""
변동성 타겟팅 전략
- target_vol: 목표 연환산 변동성 (15%)
- lookback: 변동성 추정 윈도우 (영업일)
- max_leverage: 최대 레버리지 한도
- min_weight: 최소 투자 비중
"""
# 실현 변동성 계산 (연환산)
realized_vol = returns.rolling(lookback).std() * np.sqrt(252)
# 포지션 크기 = 목표 변동성 / 실현 변동성
position = target_vol / realized_vol
# 레버리지 제한 적용
position = position.clip(lower=min_weight, upper=max_leverage)
# 1일 지연 (미래 정보 방지)
position = position.shift(1)
# 전략 수익률
strategy_returns = position * returns
return strategy_returns, position, realized_vol
strat_ret, position, real_vol = volatility_targeting(returns)
# 성과 비교
buy_hold = returns.cumsum()
strategy = strat_ret.cumsum()
print(f"=== Buy & Hold ===")
print(f"연환산 수익률: {returns.mean() * 252:.2%}")
print(f"연환산 변동성: {returns.std() * np.sqrt(252):.2%}")
print(f"샤프 비율: {returns.mean() / returns.std() * np.sqrt(252):.2f}")
print(f"n=== 변동성 타겟팅 ===")
print(f"연환산 수익률: {strat_ret.mean() * 252:.2%}")
print(f"연환산 변동성: {strat_ret.std() * np.sqrt(252):.2%}")
print(f"샤프 비율: {strat_ret.mean() / strat_ret.std() * np.sqrt(252):.2f}")
EWMA 변동성으로 반응 속도 개선
단순 이동평균 변동성은 급격한 변동에 느리게 반응합니다. 지수가중이동평균(EWMA)을 사용하면 최근 데이터에 더 큰 가중치를 부여하여 빠르게 대응할 수 있습니다.
def ewma_volatility_targeting(returns, target_vol=0.15,
span=20, max_leverage=1.5):
"""EWMA 기반 변동성 타겟팅"""
# EWMA 변동성
ewma_var = returns.ewm(span=span).var()
ewma_vol = np.sqrt(ewma_var) * np.sqrt(252)
# 포지션 크기
position = (target_vol / ewma_vol).clip(0.1, max_leverage).shift(1)
strategy_returns = position * returns
return strategy_returns, position, ewma_vol
ewma_ret, ewma_pos, ewma_vol = ewma_volatility_targeting(returns)
print(f"EWMA 샤프: {ewma_ret.mean() / ewma_ret.std() * np.sqrt(252):.2f}")
EWMA의 span 파라미터가 작을수록 반응이 빠르지만 과민해질 수 있습니다. 일반적으로 15~30 범위가 적합합니다.
멀티 자산 변동성 타겟팅
여러 자산으로 구성된 포트폴리오에 변동성 타겟팅을 적용하는 방법입니다. 각 자산별로 독립적으로 변동성을 조절합니다.
def multi_asset_vol_target(prices, target_vol=0.10,
lookback=20, max_leverage=1.5):
"""멀티 자산 변동성 타겟팅"""
returns = prices.pct_change().dropna()
n_assets = returns.shape[1]
# 자산별 동일 리스크 배분
per_asset_vol = target_vol / np.sqrt(n_assets)
positions = pd.DataFrame(index=returns.index, columns=returns.columns)
for col in returns.columns:
vol = returns[col].rolling(lookback).std() * np.sqrt(252)
pos = (per_asset_vol / vol).clip(0.05, max_leverage).shift(1)
positions[col] = pos
# 포트폴리오 수익률
port_returns = (positions * returns).sum(axis=1)
return port_returns, positions
# 예시: 주식 + 채권 + 금
tickers = ['SPY', 'TLT', 'GLD']
prices = yf.download(tickers, start='2015-01-01', end='2025-12-31')['Close']
port_ret, positions = multi_asset_vol_target(prices)
print(f"포트폴리오 샤프: {port_ret.mean() / port_ret.std() * np.sqrt(252):.2f}")
print(f"포트폴리오 MDD: {(port_ret.cumsum().cummax() - port_ret.cumsum()).max():.2%}")
파이썬 리스크 패리티 포트폴리오와 결합하면 자산 배분과 리스크 관리를 동시에 최적화할 수 있습니다.
변동성 타겟팅 파라미터 최적화
핵심 파라미터를 체계적으로 테스트하는 프레임워크입니다.
| 파라미터 | 범위 | 권장값 | 영향 |
|---|---|---|---|
| 목표 변동성 | 5%~25% | 10~15% | 높을수록 공격적 |
| 룩백 윈도우 | 10~60일 | 20~30일 | 짧을수록 민감 |
| 최대 레버리지 | 1.0~2.0x | 1.5x | 리스크 상한 |
| 리밸런싱 주기 | 일/주/월 | 일간 | 비용 vs 정확도 |
def optimize_params(returns, target_vols, lookbacks):
"""파라미터 그리드 서치"""
results = []
for tv in target_vols:
for lb in lookbacks:
strat_ret, _, _ = volatility_targeting(
returns, target_vol=tv, lookback=lb
)
sharpe = strat_ret.mean() / strat_ret.std() * np.sqrt(252)
mdd = (strat_ret.cumsum().cummax() - strat_ret.cumsum()).max()
results.append({
'target_vol': tv,
'lookback': lb,
'sharpe': round(sharpe, 3),
'mdd': round(mdd, 4)
})
df = pd.DataFrame(results).sort_values('sharpe', ascending=False)
return df
best = optimize_params(
returns,
target_vols=[0.08, 0.10, 0.12, 0.15, 0.20],
lookbacks=[10, 15, 20, 30, 60]
)
print(best.head(10))
백테스트 오버피팅 방지법에서 강조한 것처럼, 인샘플에서 최적 파라미터를 찾은 후 반드시 아웃오브샘플에서 검증해야 합니다.
실전 적용 시 핵심 포인트
- 변동성 급등 시 주의: VIX 급등 구간에서 포지션이 급격히 줄어 반등 수익을 놓칠 수 있습니다. 포지션 변화 속도에 제한을 두는 것이 좋습니다.
- 거래 비용: 일간 리밸런싱은 거래 비용이 큽니다. 포지션 변화가 임계값(예: 10%) 이상일 때만 리밸런싱하면 비용을 절감할 수 있습니다.
- 변동성 추정 오류: 실현 변동성은 과거 데이터 기반이므로 구조적 변화에 늦게 반응합니다. 옵션 내재 변동성(VIX)을 보조 지표로 활용하면 도움이 됩니다.
- 레버리지 제한: 저변동성 구간에서 레버리지가 과도해지지 않도록 상한을 설정하세요. 1.5배 이하가 안전합니다.
- 다른 전략과 결합: 변동성 타겟팅은 독립 전략이 아닌 리스크 관리 레이어로 활용하는 것이 가장 효과적입니다. 기존 모멘텀·평균회귀 전략 위에 적용해 보세요.
마무리
변동성 타겟팅은 복잡한 알파 모델 없이도 리스크 조정 수익률(샤프 비율)을 개선할 수 있는 강력한 기법입니다. 특히 2020년 코로나 폭락, 2022년 금리 인상기처럼 변동성이 급등하는 구간에서 큰 손실을 방지하는 효과가 뚜렷합니다. 목표 변동성과 룩백 윈도우만 결정하면 구현이 간단하므로, 자동매매 시스템에 반드시 추가해야 할 리스크 관리 모듈입니다.