2026. 8. 30. 22:35ㆍ카테고리 없음
화면 뒤의 데이터 판단 · 방향 신호
라벨을 "오르내림"에서 "과거평균 대비 초과수익"으로 바꾸자 우위가 생겼다
그리고 지평 하나는 다시 되돌렸다
지수 방향을 맞히는 분류 모델을 만들 때 라벨은 자명해 보입니다. N일 뒤에 올랐으면 1, 내렸으면 0.
이 정의로는 기저율을 못 넘었습니다. 여러 구성을 바꿔 봐도 최악 구간이 42~47에 머물렀습니다. 결국 손댄 곳은 모델이 아니라 라벨이었습니다.
문제 — 주식은 원래 오른다
"올랐나?"로 라벨을 만들면 1의 비율이 65.4%가 됩니다. 상승 드리프트가 통째로 라벨에 들어오기 때문입니다.
여기서 두 가지가 동시에 망가집니다.
- 클래스 불균형 — 하락 표본이 3분의 1뿐이라 모델이 하락을 배울 재료가 부족하다
- 기저율이 높아진다 — "항상 상승"이라고 답하는 무지성 모델이 65.4%를 낸다. 실력을 증명하려면 그 위로 올라가야 한다
즉 모델은 어려워지고 채점 기준은 높아집니다. 최악의 조합입니다.
바꾼 라벨 — "평소보다 나은가"
질문을 바꿨습니다. "오를까"가 아니라 "평소보다 나을까".
벤치마크는 과거 1년치 같은 기간 수익률의 평균입니다. 그보다 잘했으면 1, 못했으면 0입니다.
def make_labels(close, hzn):
# 앞으로 hzn 봉 수익률
fwd = close.shift(-hzn) / close - 1
# 벤치마크 = 그 시점 '이전' 1년치 평균. shift 로 미래를 차단한다
bench = fwd.shift(hzn).rolling(252, min_periods=60).mean()
ex = fwd - bench
return (ex > 0).astype(float)
핵심은 두 번째 줄의 fwd.shift(hzn)입니다. fwd는 정의상 미래를 담고 있으므로, 그대로 평균 내면 벤치마크에 미래가 섞입니다. 지평만큼 밀어 그 시점에서 이미 확정된 값만 쓰게 만듭니다.
바뀐 것
실제 부호 라벨초과수익 라벨
| 양성 비율(=기저율) | 65.4% | 53.5% |
| 클래스 균형 | 2:1 편중 | 거의 균형 |
| 넘어야 할 선 | 65.4% | 53.5% |
기저율이 11.9%p 내려갔습니다. 같은 모델이 갑자기 똑똑해진 게 아니라, 드리프트가 라벨에서 걷히면서 채점 기준이 정직해진 것입니다.
동시에 하락 표본이 늘어 모델이 하락을 배울 재료도 생겼습니다. 문제와 채점 기준이 한 번에 개선됐습니다.
라벨 하나만 바꾼 게 아니다
정직하게 적자면, 이 라벨 단독으로 성적이 좋아진 게 아닙니다. 실험에서 네 조건이 모두 필요했고 하나라도 빠지면 최악 구간이 42~47로 떨어졌습니다.
조건내용
| 글로벌 지수 | 아시아·유럽 종가는 미국 개장 전에 확정된다 — 미래가 아니라 실제로 쓸 수 있는 선행 정보 |
| 미국 매크로 제거 | VIX·환율·금리·유가는 이미 가격에 반영돼 잡음으로 작동했다 (넣으면 46.8, 빼면 51.2) |
| 과거평균 라벨 | 기저 65.4% → 53.5% |
| 예측 결합 | 피처별 얕은 모델의 로그오즈 평균. 가중치를 배우는 스태킹은 과적합해 실패 (48.6) |
네 번째가 특히 반직관적입니다. 가중치를 학습하지 않는 것이 요점이었습니다 — 메타러너가 배우려 들면 과적합하고, 단순 평균은 배울 게 없어 강건합니다.
그런데 5봉은 다시 되돌렸다
여기가 이 글에서 가장 중요한 대목입니다. 라벨이 좋다고 모든 지평에 쓰지는 않았습니다.
워크포워드 결과를 실제 부호 기준으로 다시 보니, 이 구성은 사실상 상승만 말하고 있었습니다.
- 상승 예측 비중 1.00 — 하락을 한 건도 내지 않았다
- 출력 확률이 0.53~0.79에만 머물렀다
원인은 결합 방식에 있었습니다. 평균은 극단을 상쇄해 확률을 중앙에 뭉치게 하는데, 기저 61%인 시장에서 그 중앙은 이미 0.5 위입니다. 확률이 아무리 낮게 나와도 0.5 밑으로 안 내려갑니다.
그리고 화면이 답하는 질문은 "오를까 내릴까"입니다. "평소보다 나을까"가 아닙니다.
그래서 5봉만 단일 모델 + 실제 부호 라벨로 되돌렸습니다. 하락도 냅니다 — 홀드아웃 하락 우위 +8.9%p.
남은 한계
20·60봉의 한계는 문서에 그대로 적어 뒀습니다 — 기저 대비 상승 +6.5%p인데 하락은 +1.9%p입니다. 방향을 맞히는 게 아니라 사실상 상승만 맞히는 모델입니다.
그래서 화면에서는 상승·하락을 나눠 표기합니다. 하나의 정확도로 뭉뚱그리면 하락 신호를 과신하게 됩니다.
5봉도 우위가 작고 AUC 신뢰구간이 0.5를 포함해, 호출부가 weak_edge 플래그를 받아 참고용으로 표기합니다.
정리
- 기저율이 높으면 모델은 어려워지고 채점 기준은 높아진다 — 최악의 조합이다
- 드리프트를 라벨에서 걷으면 문제와 기준이 동시에 개선된다 — 65.4% → 53.5%
- 벤치마크에 미래가 안 섞이게 한 칸 민다 — fwd.shift(hzn)
- 라벨은 그 분야의 표준 비교 대상에서 가져온다 — 임의로 정하지 않는다
- 지표가 좋은 라벨과 화면이 묻는 라벨은 다를 수 있다 — 5봉은 되돌렸다
- 클래스별로 나눠 보지 않으면 "상승만 맞히는 모델"을 못 알아본다
모델 구조를 몇 번 바꿔도 안 되던 것이 라벨 정의 한 줄에서 갈렸습니다. 그런데 그 좋은 라벨을 전부에 쓰지 않기로 한 결정이, 라벨을 바꾼 결정만큼 중요했습니다.
화면 뒤의 데이터 판단 · 분석 → 종합 — 방향 신호