자동매매 MDD 제어 전략

자동매매에서 MDD가 중요한 이유

자동매매 시스템을 운영할 때 수익률만큼 중요한 지표가 바로 MDD(Maximum Drawdown, 최대 드로다운)입니다. MDD는 포트폴리오가 고점 대비 최대 얼마나 하락했는지를 나타내는 지표로, 전략의 위험 수준을 직관적으로 보여줍니다. 연 수익률 50%를 달성해도 MDD가 60%라면 실전에서 견디기 어려운 전략이며, 대부분의 투자자는 심리적 압박으로 중도 포기하게 됩니다.

퀀트 트레이딩에서 MDD 제어는 단순한 손절이 아닙니다. 전략 수준, 포트폴리오 수준, 계좌 수준의 다층 방어 체계를 구축해야 실전에서 살아남을 수 있습니다. 이 글에서는 자동매매 봇에 적용할 수 있는 MDD 제어 기법을 체계적으로 정리합니다.

MDD 계산 공식과 파이썬 구현

MDD를 계산하는 기본 공식은 다음과 같습니다:

MDD = (최저점 - 고점) / 고점 × 100%

파이썬으로 구현하면 누적 수익 곡선에서 실시간으로 MDD를 추적할 수 있습니다:

import numpy as np

def calculate_mdd(equity_curve):
    """누적 수익 곡선에서 MDD 계산"""
    peak = np.maximum.accumulate(equity_curve)
    drawdown = (equity_curve - peak) / peak
    mdd = drawdown.min()
    return mdd

def rolling_mdd(equity_curve, window=20):
    """롤링 윈도우 MDD - 최근 N일 기준"""
    mdds = []
    for i in range(window, len(equity_curve)):
        segment = equity_curve[i-window:i+1]
        mdds.append(calculate_mdd(segment))
    return mdds

실시간 자동매매에서는 rolling_mdd 함수를 활용해 최근 구간의 드로다운 추이를 모니터링하는 것이 핵심입니다.

3단계 MDD 방어 체계

실전 자동매매에서 MDD를 효과적으로 제어하려면 3단계 방어 체계를 구축해야 합니다. 각 단계별 트리거 조건과 대응 액션을 명확하게 정의하는 것이 중요합니다.

1단계: 경고(Yellow Zone) — MDD 10~15%

포트폴리오가 고점 대비 10~15% 하락하면 경고 단계에 진입합니다. 이 단계에서는 포지션 크기를 50% 축소하고, 신규 진입 조건을 강화합니다. 텔레그램이나 슬랙으로 알림을 발송하여 수동 모니터링을 병행합니다.

class MddController:
    def __init__(self, yellow=0.10, orange=0.20, red=0.30):
        self.yellow = yellow   # 경고
        self.orange = orange   # 위험
        self.red = red         # 긴급 정지
        self.peak_equity = 0
        self.current_equity = 0

    def update(self, equity):
        self.current_equity = equity
        self.peak_equity = max(self.peak_equity, equity)

    @property
    def current_dd(self):
        if self.peak_equity == 0:
            return 0
        return (self.peak_equity - self.current_equity) / self.peak_equity

    def get_position_scale(self):
        dd = self.current_dd
        if dd >= self.red:
            return 0.0    # 전면 정지
        elif dd >= self.orange:
            return 0.25   # 75% 축소
        elif dd >= self.yellow:
            return 0.50   # 50% 축소
        return 1.0        # 정상 운영

2단계: 위험(Orange Zone) — MDD 20~25%

드로다운이 20%를 넘기면 포지션을 75% 축소하고, 기존 보유 포지션의 손절 기준을 타이트하게 조정합니다. 동시에 전략 파라미터가 현재 시장 레짐에 맞는지 점검해야 합니다. 이 단계에서는 수동 개입을 권장합니다.

3단계: 긴급 정지(Red Zone) — MDD 30% 이상

MDD 30%를 돌파하면 모든 포지션을 즉시 청산하고 자동매매를 정지합니다. 이 수준의 드로다운은 전략 자체에 구조적 문제가 있거나 시장 환경이 급변했음을 의미합니다. 최소 1~2주간 전략을 재검증한 후 재가동해야 합니다.

전략별 MDD 한도 설정 기준

모든 전략에 동일한 MDD 한도를 적용하면 안 됩니다. 전략의 특성에 따라 허용 MDD를 차등 설정해야 합니다:

전략 유형 권장 MDD 한도 근거
추세추종(Trend Following) 20~30% 횡보장에서 연속 손실 발생이 자연스러움
평균회귀(Mean Reversion) 10~15% 급등·급락 시 큰 손실 위험
차익거래(Arbitrage) 5~8% 저위험 전략이므로 이탈 시 즉시 점검
모멘텀(Momentum) 15~25% 반전 구간에서 드로다운 불가피

핵심은 백테스트에서 관찰된 MDD의 1.5~2배를 실전 한도로 설정하는 것입니다. 백테스트 MDD가 15%였다면 실전 한도는 22~30%로 설정합니다. 실전은 백테스트보다 항상 더 나쁜 결과가 나오기 때문입니다.

동적 포지션 사이징과 MDD 연동

고정 비율 포지션 사이징 대신, 현재 드로다운 수준에 따라 포지션 크기를 동적으로 조절하면 MDD를 효과적으로 억제할 수 있습니다. 대표적인 방법이 Anti-Martingale 방식입니다:

def dynamic_position_size(base_size, current_dd, max_dd=0.30):
    """드로다운 비율에 따라 포지션 사이즈 동적 조절"""
    if current_dd <= 0:
        return base_size
    
    # 드로다운이 깊을수록 포지션 축소
    scale = max(0, 1 - (current_dd / max_dd) ** 1.5)
    return base_size * scale

# 예시: 기본 10만원, 현재 DD 15%, 최대 허용 DD 30%
size = dynamic_position_size(100000, 0.15, 0.30)
# 결과: 약 64,645원 (35% 축소)

이 방식은 손실 구간에서 자동으로 리스크를 줄이고, 수익 구간에서는 원래 포지션을 유지하므로 포지션 사이징 전략과 자연스럽게 연동됩니다.

쿨다운 메커니즘 구현

MDD 임계치를 터치한 후 바로 재진입하면 추가 손실이 발생할 확률이 높습니다. 쿨다운(Cooldown) 기간을 두어 시장이 안정된 후 점진적으로 재가동하는 것이 안전합니다:

from datetime import datetime, timedelta

class CooldownManager:
    def __init__(self, cooldown_hours=48, ramp_up_days=5):
        self.cooldown_hours = cooldown_hours
        self.ramp_up_days = ramp_up_days
        self.stop_time = None

    def trigger_stop(self):
        self.stop_time = datetime.now()

    def get_allowed_scale(self):
        if self.stop_time is None:
            return 1.0
        
        elapsed = datetime.now() - self.stop_time
        
        # 쿨다운 기간 중에는 거래 금지
        if elapsed < timedelta(hours=self.cooldown_hours):
            return 0.0
        
        # 점진적 재가동 (20%씩 증가)
        days_since = (elapsed - timedelta(hours=self.cooldown_hours)).days
        scale = min(1.0, 0.2 * (days_since + 1))
        return scale

쿨다운 후 즉시 풀 사이즈로 복귀하는 것이 아니라, 5일에 걸쳐 20%씩 단계적으로 복원하는 것이 핵심입니다. 이를 통해 시장 환경이 여전히 불리한 경우 추가 손실을 최소화할 수 있습니다.

멀티 전략 MDD 관리

여러 전략을 동시에 운영하는 경우, 개별 전략 MDD뿐 아니라 포트폴리오 전체 MDD도 관리해야 합니다. 상관관계가 높은 전략들이 동시에 드로다운에 빠지면 합산 손실이 급격히 커질 수 있기 때문입니다.

멀티 전략 MDD 관리의 핵심 원칙:

  • 전략 간 상관계수를 주기적으로 계산하여 상관관계가 0.7 이상인 전략 쌍은 자본 배분을 줄임
  • 포트폴리오 레벨 MDD 한도를 별도로 설정 (예: 개별 전략 MDD 한도 합계의 60~70%)
  • 하나의 전략이 Red Zone에 진입하면 다른 전략의 포지션도 축소하여 시스템 리스크에 대비
  • 전략 추가 시 기존 포트폴리오와의 포트폴리오 최적화를 재실행

실전 MDD 모니터링 대시보드

자동매매 봇에 MDD 모니터링을 통합하려면 다음 지표를 실시간으로 추적해야 합니다:

  • 현재 드로다운: 최근 고점 대비 현재 하락률
  • 최대 드로다운: 운영 시작 이후 최악의 드로다운
  • 드로다운 기간: 고점 회복까지 걸린 시간 (Recovery Time)
  • Calmar Ratio: 연수익률 ÷ MDD — 1.0 이상이면 양호, 2.0 이상이면 우수
  • Ulcer Index: 드로다운의 깊이와 지속시간을 종합한 리스크 지표

이 지표들을 텔레그램 알림이나 Grafana 대시보드에 연동하면 24시간 자동매매 중에도 리스크 상태를 즉시 파악할 수 있습니다.

MDD 제어 체크리스트

자동매매 봇에 MDD 제어를 적용할 때 반드시 확인해야 할 항목들을 정리합니다:

  • ✅ 전략별 MDD 한도가 백테스트 결과 기반으로 설정되었는가
  • ✅ 3단계 방어 체계(경고 → 위험 → 긴급 정지)가 코드에 구현되었는가
  • ✅ 쿨다운 메커니즘이 적용되어 과도한 재진입을 방지하는가
  • ✅ 동적 포지션 사이징이 현재 드로다운과 연동되는가
  • ✅ 실시간 알림 시스템이 MDD 임계치 도달 시 작동하는가
  • ✅ 멀티 전략 운영 시 포트폴리오 레벨 MDD도 별도 관리하는가
  • ✅ 월 1회 이상 MDD 한도의 적정성을 재검증하는가

결론

자동매매에서 MDD 제어는 생존의 문제입니다. 아무리 높은 기대수익률을 가진 전략이라도 MDD 관리 없이는 한 번의 급락으로 계좌가 회복 불가능한 수준까지 손상될 수 있습니다. 3단계 방어 체계, 동적 포지션 사이징, 쿨다운 메커니즘을 조합하여 체계적인 MDD 제어 시스템을 구축하세요. 수익을 추구하기 전에 먼저 살아남아야 합니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux