백테스트 과최적화 피하는 법 — 학습·검증 구간을 나누는 워크포워드 검증
백테스트 성과가 좋았는데 실전은 왜 다를까
이전 글 백테스팅이란 무엇인가에서 과최적화라는 함정의 존재를 짚었다. 문제는 함정이 있다는 걸 아는 것과, 실제로 그 함정에 빠졌는지 확인하는 방법을 아는 것이 다르다는 점이다. 파라미터를 이리저리 바꿔가며 백테스트 성과를 끌어올렸는데, 막상 실거래로 넘어가면 그 좋은 성과가 재현되지 않는 경우를 겪고 나서야 이 차이를 실감하게 된다.
이 글은 과최적화 개념 자체보다 "지금 이 전략이 과최적화됐는지 어떻게 확인하나"에 초점을 맞춘다. 코드는 이번에도 특정 전략 로직이 아닌 검증 절차를 다루는 의사코드다.
학습 구간과 검증 구간을 나눈다
파라미터(이동평균 기간, 손절 기준 등)를 조정하는 구간과 그 성과를 평가하는 구간을 반드시 분리해야 한다. 이를 각각 학습 구간(in-sample)과 검증 구간(out-of-sample)이라 부른다. 파라미터 튜닝은 학습 구간에서만 하고, 성과 평가는 검증 구간에서 한다. 검증 구간 성과가 학습 구간보다 크게 떨어진다면 과최적화를 의심해야 한다.
워크포워드 검증 — 구간을 옮겨가며 반복 검증한다
학습·검증 구간을 한 번만 나누는 것으로는 부족하다. 시간 축을 따라 구간을 계속 옮겨가며 같은 절차를 반복하는 방법이 워크포워드(Walk-forward) 검증이다.
python 코드 보기
def walk_forward_validate(prices, param_grid, train_size, test_size):
results = []
start = 0
while start + train_size + test_size <= len(prices):
train = prices[start : start + train_size]
test = prices[start + train_size : start + train_size + test_size]
best_params = tune_on_training_data(train, param_grid)
test_performance = backtest(test, best_params)
results.append({
"train_range": (start, start + train_size),
"params": best_params,
"test_performance": test_performance,
})
start += test_size
return results여기서 중요한 건 튜닝은 항상 train에서만 이루어지고, 성과 평가는 그 파라미터를 한 번도 보지 않은 test 구간에서 측정한다는 점이다. 구간을 옮겨가며 여러 번 반복해, 특정 구간에만 맞는 우연의 결과가 아닌지 확인한다.
검증 결과를 해석하는 법 — 구간마다 파라미터가 다르다면
워크포워드마다 최적 파라미터가 크게 요동친다면(예: 어떤 구간은 짧은 이동평균이 최적, 다른 구간은 훨씬 긴 이동평균이 최적), 이는 전략이 특정 시장 상황에만 의존한다는 신호다. 안정적인 전략이라면 구간이 바뀌어도 최적 파라미터가 어느 정도 비슷한 범위에 머무는 경향을 보인다.
자주 하는 실수
- 학습 구간에서 나온 최고 성과를 그대로 실전 기대치로 삼는다. 학습 구간 성과는 그 구간에 맞춰진 결과일 뿐, 실전 기대치가 아니다.
- 검증 구간 성과가 나쁘게 나오면 검증 구간을 슬쩍 바꿔서 다시 돌린다. 이러면 검증 구간도 사실상 학습 구간이 되어버려 검증의 의미가 사라진다.
- 워크포워드를 한 번만 돌리고 끝낸다. 최소 여러 구간을 반복해야 우연인지 아닌지 구분할 수 있다.
오늘의 정리
- 과최적화를 예방하려면 파라미터 튜닝은 학습 구간에서만, 성과 평가는 검증 구간에서 분리해서 진행해야 한다.
- 워크포워드 검증은 학습·검증 구간을 시간순으로 옮겨가며 반복해, 특정 구간에만 맞는 우연의 결과인지 확인하는 방법이다.
- 구간마다 최적 파라미터가 크게 다르면 전략이 특정 시장 상황에 과도하게 의존한다는 신호로 봐야 한다.
- 검증 구간 성과가 나쁘다고 검증 구간 자체를 바꿔 다시 돌리면, 검증의 의미가 사라진다.
이 글의 코드는 검증 절차를 설명하기 위한 의사코드이며 특정 전략이나 실거래 시스템의 구현이 아닙니다. 이 글은 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 백테스트나 워크포워드 검증 결과가 좋다고 해서 미래 수익을 보장하지 않으며, 투자 손실에 대한 책임은 투자자 본인에게 있습니다.