05. 레전드 사건 발생 (-62%)

멀티타임프레임이라는 우아한 아이디어

v2.3에서 37,970%라는 역대 최고 수익률을 찍고 나서, 나는 다음 목표로 승률 개선에 집중하기로 했다. 수익률은 높은데 승률이 55%에 불과했다. 100번 거래하면 45번은 손실. 심리적으로 꽤 힘든 숫자다.

아이디어는 직관적이었다. 5분봉 하나의 예측에 의존하지 말고, 여러 타임프레임의 의견을 모아보자. 15분, 30분, 1시간 -- 세 가지 시간 지평에서 모두 "상승"이라고 할 때만 매수에 들어가면, 거짓 신호를 걸러낼 수 있지 않을까?

# v2.5: 신호 일치도 기반 거래 결정
horizons = {
    3:  {'name': '15분', 'down': -0.01, 'up': 0.01},
    6:  {'name': '30분', 'down': -0.015, 'up': 0.015},
    12: {'name': '1시간', 'down': -0.02, 'up': 0.02},
}

# 3개 타임프레임 모두 일치할 때만 거래
if agreement_level == 3:    # 완전 일치
    confidence_boost = 0.30  # +30% 신뢰도 부스트
elif agreement_level == 2:  # 부분 일치
    confidence_boost = 0.10
else:                       # 불일치
    should_trade = False     # 거래 보류

각 타임프레임별로 독립적인 앙상블(LSTM + XGBoost + LightGBM)을 학습시켰다. 모델 9개. 학습에 40분. 꽤 무거운 시스템이었지만, 결과는 놀라웠다.

승률 68.51%, MDD 6.96% -- 숫자만 보면 완벽했다

메트릭 v2.4 v2.5 변화
승률 54.87% 68.51% +13.64%
MDD 50.15% 6.96% -43.19%
총 거래 수 9,539 235 -97.5%
총 수익률 36,250% 5.61% ---

승률이 13.64%나 뛰었고, 최대 낙폭은 50%에서 7%로 떨어졌다. 235번의 거래 중 68.51%가 수익이었다. 안정성의 극치였다. 나는 이 모델에 꽤 만족했다.

하지만 총 수익률 5.61%라는 숫자가 마음에 걸렸다. 거래 빈도가 97.5%나 줄었으니 수익률이 낮은 건 당연하다고 스스로 합리화했다. "승률이 높으면 레버리지를 올리면 되니까." 그때는 그렇게 생각했다.

승률만으로 수익이 보장되지 않는 이유: 기대수익 공식

여기서 한 발짝 물러서, 승률(Win Rate)이라는 지표가 수익과 어떤 관계에 있는지를 수학적으로 들여다보자. 트레이딩에서 기대수익(Expected Return)은 단순히 승률이 아니라 다음과 같이 정의된다:

$$E[R] = WR \cdot \bar{W} - (1 - WR) \cdot \bar{L}$$

여기서 $WR$은 승률, $\bar{W}$는 평균 수익 크기, $\bar{L}$은 평균 손실 크기다. 이 공식이 말해주는 건 명확하다: 승률이 아무리 높아도, 한 번 질 때의 손실이 이길 때의 수익보다 훨씬 크면 돈을 잃는다.

비유하자면, 가위바위보를 10판 해서 7번 이겨도, 이길 때마다 100원 받고 질 때마다 500원 내야 한다면 결국 적자다. 승률이 아니라 "한 판의 판돈 구조"가 진짜 중요하다.

v2.5의 숫자를 넣어보면:

  • 승률 68.51%, 평균 수익률 +0.48%
  • $E[R] = 0.685 \times 0.48\% - 0.315 \times |\bar{L}|$

승률만 보면 훌륭해 보이지만, 235건의 거래로 5.61%밖에 내지 못했다는 건 평균 수익과 평균 손실의 크기가 비슷하다는 뜻이다. 진짜 좋은 시스템은 승률뿐 아니라 Profit Factor도 높아야 한다:

$$PF = \frac{\sum \text{Wins}}{\sum |\text{Losses}|}$$

PF가 1.0이면 본전, 2.0 이상이면 준수하다. 장사로 비유하면, PF는 매출 대비 원가의 비율이다. PF 1.0은 팔아도 남는 게 없는 박리다매, 2.0 이상이면 마진이 넉넉한 장사다. v2.5의 PF는 겨우 1.1 수준이었다. 반면 나중에 구현하게 되는 v2.7은 PF가 5.01에 달한다. 같은 승률 70%대라도 질적으로 완전히 다른 거래를 하고 있었던 것이다.

v2.6: 리스크 관리를 얹었더니 무너졌다

v2.6에서 실전에 가까운 리스크 관리 레이어를 추가했다. Circuit Breaker(연속 손실 시 대기), Trailing Stop, ATR 기반 동적 손절 등. 이런 안전장치들은 좋은 모델을 더 좋게 만들어줄 거라 기대했다.

v2.5 모델에 v2.6 리스크 관리를 적용한 백테스트 결과:

수익률: -62.83% 거래 수: 990건, 승률: 32.2% 손절 발동: 668건 (67.6%)

충격이었다. 승률 68%의 "안정적인" 모델이 리스크 관리를 달았더니 오히려 -62%가 된 것이다. 990건 중 668건이 손절. 내가 믿었던 승률 68.51%는 어디로 간 걸까?

가짜 신호 합의라는 함정

문제의 근본 원인을 분석하면서, 나는 v2.5 설계의 치명적 결함을 발견했다.

세 개의 타임프레임 모델이 전부 같은 5분봉 데이터를 쓰고 있었다.

15분 모델이든 30분 모델이든 1시간 모델이든, 입력 피처는 동일한 42개의 5분봉 기반 지표였다. horizon(예측 지평)만 3, 6, 12로 달랐을 뿐이다. 이건 "세 명의 전문가에게 의견을 물었다"가 아니라, "같은 사람에게 세 번 물어본 것"이었다.

정보이론으로 보는 가짜 독립성

이 문제를 정보이론의 언어로 더 정밀하게 표현해 보자. 세 모델의 신호를 $S_1$(15분), $S_2$(30분), $S_3$(1시간)이라 하자. 만약 세 신호가 진정으로 독립이라면, 세 모델이 동시에 같은 결론을 낼 조건부 확률은 다음과 같다:

$$P(\text{agree}) = P(S_1 = S_2 = S_3) = P(S_1) \cdot P(S_2) \cdot P(S_3)$$

각 모델이 60% 정확도로 "LONG"을 예측한다면, 독립 가정 하에 세 모델이 동시에 LONG을 외칠 확률은 $0.6^3 = 0.216$, 약 21.6%다. 이것이 진짜 필터링이다. 전체 거래 기회의 약 1/5만 선별하는 고품질 필터.

의사 3명에게 독립적으로 진료를 받아서 셋 다 "수술 필요"라고 하면 꽤 신뢰할 만하다. 하지만 그 3명이 같은 검사 결과지 하나만 보고 판단했다면? 그건 사실상 1명의 의견이다.

하지만 v2.5에서는 실제 신호 일치율이 94%였다. 이론적 독립 가정의 21.6%와 실측 94%의 괴리가 너무 크다. 이 괴리를 정량화할 수 있는 도구가 상호정보량(Mutual Information)이다:

$$I(X; Y) = \sum_{x, y} p(x, y) \log \frac{p(x, y)}{p(x) \cdot p(y)}$$

$I(X; Y) = 0$이면 $X$와 $Y$가 완전히 독립이고, 값이 클수록 두 변수가 공유하는 정보가 많다. v2.5의 세 모델은 같은 42개 피처를 입력으로 받기 때문에, 모델 간 상호정보량이 극도로 높았다. 사실상 같은 정보를 세 번 읽고 있었으니, 서로 다른 "의견"이 나올 여지가 거의 없었다.

같은 교과서로 공부한 세 학생에게 같은 시험을 보게 하면, 답이 거의 똑같이 나온다. 상호정보량이 높다는 건 "공유하는 교과서"가 너무 많다는 뜻이다. 다른 교재를 읽어야 서로 다른 관점이 나온다.

이것은 정보이론에서 말하는 정보의 중복(redundancy) 문제다. 독립된 정보원(independent sources)은 결합했을 때 엔트로피가 가산적으로 증가한다:

$$H(S_1, S_2, S_3) = H(S_1) + H(S_2) + H(S_3) \quad \text{(독립일 때)}$$

하지만 상관된 정보원은 결합 엔트로피가 개별 엔트로피의 합보다 훨씬 작다:

$$H(S_1, S_2, S_3) \ll H(S_1) + H(S_2) + H(S_3) \quad \text{(상관일 때)}$$

세 모델이 제공하는 총 정보량은 모델 하나와 거의 같았다. 필터가 작동하지 않은 것이다.

v2.5의 "독립적" 타임프레임:
  - 15분 모델: 5분봉 42개 피처 → horizon=3 예측
  - 30분 모델: 5분봉 42개 피처 → horizon=6 예측
  - 1시간 모델: 5분봉 42개 피처 → horizon=12 예측
  → 피처가 동일하니 예측도 거의 동일 → 일치율 94%

진짜 독립적 타임프레임이라면:
  - 15분 모델: 15분봉으로 리샘플링한 독립 피처
  - 1시간 모델: 1시간봉으로 리샘플링한 독립 피처
  → 서로 다른 정보를 보고 → 의미 있는 합의

235건의 거래는 "엄선된 고품질 신호"가 아니라 "어쩌다 70% 이상 신뢰도를 넘긴 신호"에 불과했다.

6가지 구조적 결함

v2.5를 깊이 파고들면서, 승률 68%라는 숫자 뒤에 숨어 있던 구조적 결함들이 드러났다.

  1. 가짜 신호 일치도 -- 같은 피처, 다른 horizon. 94%가 일치하니 필터 무의미
  2. SHORT 편향 -- 990건 중 SHORT가 709건(71.6%). 타겟 불균형 + 고정 0.5 임계값의 합작
  3. 느린 피처 -- RSI-14(70분 지연), MA20(100분 지연). 5분봉 스캘핑에 부적합
  4. 타겟-전략 불일치 -- 학습 타겟은 "N봉 후 방향"인데, 실전은 TP/SL 먼저 닿는 쪽이 승패 결정
  5. NO_TRADE 없음 -- 횡보장에서도 강제로 방향을 선택. 모든 봉에서 거래 시도
  6. 고정 0.5 임계값 -- 51% 확률로도 진입. 저확신 거래 다수 포함

이 중 4번 "타겟-전략 불일치"가 가장 치명적이었다. 모델이 학습하는 문제와 실제로 풀어야 하는 문제가 달랐으니, 정확도가 높아도 수익이 나지 않는 건 당연했다. 이 문제는 v2.7의 Triple-Barrier로 해결하게 된다.

Quality vs Quantity: 트레이드오프의 수학

v2.5의 진짜 교훈은 "승률과 수익률은 다른 차원의 지표"라는 것이었다.

v2.3 (수익형) v2.5 (승률형)
거래 수 9,539 235
승률 55.10% 68.51%
수익률 37,970% 5.61%
MDD 40.41% 6.96%

v2.3은 9,539번 거래하면서 55% 승률로 37,970% 수익을 냈다. v2.5는 235번 거래하면서 68% 승률로 5.61% 수익을 냈다. 한쪽은 양으로 승부하고, 다른 쪽은 질로 승부했다. 하지만 v2.5의 "질"은 가짜 필터 위에 세워진 사상누각이었다.

이 트레이드오프를 수학적으로 프레이밍해 보면, 총 수익은 다음과 같이 분해된다:

$$R_{total} = N \cdot E[R] = N \cdot \left[WR \cdot \bar{W} - (1 - WR) \cdot \bar{L}\right]$$

여기서 $N$은 거래 횟수다. v2.3과 v2.5를 대입하면:

  • v2.3: $N = 9539$, 작은 $E[R]$이지만 $N$이 매우 커서 복리 효과가 압도적
  • v2.5: $N = 235$, $E[R]$이 약간 더 크지만 $N$이 97.5% 줄어서 총 수익 미미

중요한 것은 $N$과 $E[R]$이 독립이 아니라는 점이다. 필터를 강화하면 $E[R]$은 올라가지만 $N$이 줄어든다. 이 관계에서 최적점을 찾는 것이 핵심인데, v2.5는 $N$을 97.5%나 희생하면서 $E[R]$의 개선은 가짜 필터에 기반한 것이었다. 최악의 조합이었다.

낚시에 비유하면, 미끼를 까다롭게 고를수록 한 마리당 크기는 커지겠지만, 하루 종일 낚시해서 한두 마리밖에 못 잡으면 저녁 식탁이 빈약하다. 미끼 선별 기준(필터)과 투하 횟수(거래 수)의 균형이 총 어획량(수익)을 결정한다.

여기서 나를 가장 괴롭힌 질문은 이것이었다.

승률을 높이면서 동시에 충분한 거래 빈도를 유지할 수 있는가?

이 질문에 답하려면 모델 아키텍처나 피처를 손보는 것으로는 부족했다. 더 근본적인 것을 바꿔야 했다. "무엇을 예측할 것인가" 자체를 재정의해야 했다. 그리고 그 답은 v2.7의 Triple-Barrier에서 발견하게 된다.

되돌아보며

v2.5는 내가 만든 모델 중 가장 "보기 좋은" 숫자를 가진 모델이었다. 승률 68%, MDD 7%. 프레젠테이션에 넣기 완벽한 숫자들. 하지만 실전 리스크 관리를 얹는 순간 -62%라는 처참한 결과가 나왔다.

이 경험이 내게 가르쳐준 것은 명확하다.

백테스트 승률은 실전 수익을 보장하지 않는다. 특히 그 승률이 정보의 독립성 없이 달성된 것이라면.

멀티타임프레임 자체는 좋은 아이디어다. 문제는 구현에 있었다. 같은 데이터를 세 번 읽는 건 독립적인 정보가 아니다. 정보이론의 관점에서, 세 모델의 결합 엔트로피 $H(S_1, S_2, S_3)$가 단일 모델의 엔트로피 $H(S_1)$과 거의 같다면, 모델 세 개를 돌리는 건 비용만 3배 늘리고 정보는 추가하지 않는 행위다.

진짜 독립적인 타임프레임 피처 -- 15분봉을 실제로 리샘플링하고, 1시간봉을, 4시간봉을 독립적으로 구성해야 의미 있는 합의가 된다. 그건 v2.7에서 비로소 해결된 문제였다. v2.7에서는 5분봉(27개), 15분봉(12개), 1시간봉(14개), 4시간봉(14개)의 독립 피처 67개를 구성했고, XGBoost 피처 중요도 Top 20에서 다중 타임프레임 피처가 12개(60%)를 차지했다. 그게 진정한 정보의 독립성이 주는 힘이었다.

때때로 가장 위험한 것은 "그럴듯한 숫자"다. 나는 68%라는 승률에 취해서, 그 숫자가 어떤 기반 위에 서 있는지를 충분히 의심하지 않았다. 다음부터는 좋은 숫자가 나올수록 더 의심해야 한다는 걸 배웠다. Profit Factor, 기대수익 공식, 상호정보량 -- 단일 지표의 함정에 빠지지 않으려면, 여러 렌즈로 동시에 봐야 한다.