Etc

설정 버그를 고쳤더니, 그다음엔 'ML을 켜는 게 맞나'라는 질문이 남았다

발단: 단순한 설정 누락

  • docker-compose.ymlenvironment 항목 — 어떤 환경변수를 컨테이너에 넘길지 명시적으로 나열하는 방식
  • 누락된 항목 — HYBRID_ENABLE_ML
  • 결과 — .env 파일에 값을 뭐라고 적어두든 컨테이너까지 미전달
  • 그래서 enable_ml — 항상 기본값 false로 결정
  • 실질 영향 — 앙상블 전략에서 ML에 배정된 가중치 0.15가 항상 0을 출력
  • 발견 시점 — 2026년 7월 28일 개장 점검 과정

고치는 건 간단했다, 그런데

  • 조치 — HYBRID_ENABLE_ML=${HYBRID_ENABLE_ML:-false}를 목록에 추가해 전달 경로 복구
  • 하지 않은 것 — “이제 .env 값대로 켜지겠지”로 종료
  • 추가 결정 — 기본값을 false로 확정. 즉 지금 당장 동작을 바꾸지 않음

  • 이유: “그럼 ML을 켜는 게 실제로 더 나은가”라는 질문이 별도로 잔존
  • 원칙: 버그 수정과, 수정 후 그 기능을 켤지 말지는 별개의 판단

세 방향에서 검증하고, 셋 다 기각했다

36개 종목 대상, 세 가지 방식으로 확인:

1) ML을 켰을 때와 껐을 때의 A/B 백테스트

기간 설정 Sharpe 평균수익률 승률
OOS OFF -1.69 -0.19% 31.2%
OOS ON -1.25 -0.31% 27.9%
2년 OFF -0.84 +3.07% 45.8%
2년 ON -1.31 +1.61% 39.4%
  • 두 기간 공통 — ML을 켰을 때 승률과 수익률 모두 악화
  • 증가한 것 — 거래량만 약 40%

2) 분류 타깃을 바꿔봐도 기저율을 못 넘었다

방식 cv_acc 기저율
3분류(현행, ±1%) 0.442 0.485
클래스 가중 3분류 0.431 0.485
2분류(flat 제거) 0.516 0.555
  • 결과: 세 가지 분류 방식 어느 쪽도 “아무것도 안 하고 다수 클래스만 찍는 것” 대비 성능 우위 확보 실패

3) 회귀 타깃으로 바꿔서 더 엄격하게 재검증

  • 방식 — 회귀로 전환 후 정보계수(IC) 측정
  • walk-forward 엄격 측정 결과 — IC +0.0051
  • 95% 신뢰구간 — [-0.033, +0.044]. 0을 포함
  • 해석 — 통계적으로 예측력이 있다고 말할 수 없는 수준
  • 백테스트 비교 — baseline이 수익(+2.91%), 승률(45.4%) 모두에서 회귀 ML(+2.33%, 43.1%)을 상회

스스로 잡아낸 함정

여기서 중요한 대목 하나:

  • 진단 초기 TimeSeriesSplit 교차검증(CV) 결과 — IC +0.050
  • 언뜻 보면 — 쓸만한 수치
  • 취한 행동 — 그대로 믿지 않고 더 엄격한 walk-forward로 재측정
  • 재측정 결과 — +0.050이 0과 통계적으로 구분되지 않는 수준으로 붕괴

진단 단계의 TimeSeriesSplit CV에서는 IC +0.050이 나왔으나, 엄격 walk-forward로 재측정하니 0과 구분되지 않았다. CV 방식의 낙관 편향이었다.

  • 성격: “처음 방법이 틀렸다”를 스스로 인정하고 더 보수적인 검증으로 이행한 사례
  • 배경 지식: CV가 실제보다 낙관적 결과를 주는 경향 인지
  • 그에 따른 처리: 그 결과를 최종 판단 근거로 미사용, 재검증 1단계 추가

근본 원인: 라벨이 아니라 피처

세 검증 모두 ML 활성화를 기각. 단, 그 이유를 타깃(라벨) 정의의 문제로 보지 않았다. 실제 원인은 피처 쪽.

  • 사용 중인 피처 — 15개
  • IC 0.03 이상인 피처 — 단 2개 (feat_atr -0.055, feat_volatility -0.047)
  • 함의 — 타깃을 3분류로 하든 2분류로 하든 회귀로 하든, 애초에 학습할 만한 정보가 피처에 미포함

  • 피처를 살리는 데 필요한 것 — 재무 데이터, 수급 데이터, 뉴스 같은 완전히 새로운 정보원
  • 그때까지의 결정 — HYBRID_ENABLE_MLtrue로 변경하지 않음

검증

docker compose config | grep HYBRID_ENABLE_ML
→ HYBRID_ENABLE_ML: "false"     # .env 값이 정상 전달됨(주석 혼입 없음)
  • 확인한 것 — 전달 경로 자체의 복구 여부
  • 적용 시점 — 다음 컨테이너 재시작(장 마감 후)으로 연기
  • 연기 이유 — 실거래 중인 시스템이라 장중에 컨테이너 미조작

남는 교훈

설정 버그 하나(환경변수 누락)를 고치는 일이, “이 기능을 켜는 게 맞는가”라는 훨씬 큰 질문으로 이어졌다.

  • 답을 찾는 과정의 부산물: 처음 쓴 검증 방법(TimeSeriesSplit CV)의 낙관 편향 발견
  • 후속 조치: 더 엄격한 방법(walk-forward)으로 재확인

  • 머신러닝 실무에서 이런 낙관 편향은 빈발
  • 이 작업 전체를 관통한 태도: 좋아 보이는 첫 결과를 그대로 믿지 않고 “이 검증 방법 자체가 나를 속이고 있는 건 아닌가”를 한 번 더 의심