본문 바로가기
IT & 비즈니스

백테스팅의 함정: 과최적화와 데이터 누수를 피하는 안정적 전략 설계

by notes9107 2026. 8. 24.

1. 수익 곡선에 취해 버린 첫 번째 백테스트

저는 2023년 3월부터 국내 주식 자동매매 전략을 만들면서 백테스트 결과를 지나치게 믿었습니다. 2018년 1월부터 2022년 12월까지 일봉 데이터를 넣고 이동평균선 조합을 바꿔 가며 테스트했는데, 20일선과 63일선 조합에서 누적 수익률 184%, 최대 낙폭 11.8%가 나왔습니다. 당시에는 계좌를 곧바로 운용해도 괜찮겠다고 판단했지만, 실제 매매를 시작한 뒤 결과는 전혀 달랐습니다.
2023년 4월부터 6월까지 소액으로 운용한 결과 수익률은 마이너스 7.4%까지 내려갔습니다. 백테스트에서는 한 달에 평균 18번 거래했는데 실전에서는 체결 지연과 호가 공백 때문에 진입 가격이 매번 달라졌고, 거래 횟수도 31번으로 늘었습니다. 그때 제가 본 수익 곡선은 전략의 실력보다 과거 구간에 우연히 잘 맞은 모양에 가까웠다는 사실을 뒤늦게 인정했습니다.

2. 숫자를 고르는 순간 과최적화가 시작됐다

처음에는 이동평균 기간을 5일 단위로만 비교했습니다. 그런데 성과가 마음에 들지 않자 17일, 23일, 41일처럼 숫자를 세분화했고, 손절 비율도 2.0%부터 2.9%까지 0.1% 단위로 조정했습니다. 총 4,800개 조합을 돌린 뒤 가장 높은 결과만 선택하니 수익률 246%라는 숫자가 나타났습니다. 제가 전략을 만든 게 아니라 과거 차트에 맞는 비밀번호를 찾고 있었다는 생각이 들었습니다.
이 문제를 확인하려고 2023년 1월부터 2024년 6월까지의 구간을 따로 떼어 검증했습니다. 20일선과 63일선 조합은 본 테스트에서 수익률 184%였지만 새 구간에서는 3.1% 손실을 냈고, 19일선과 60일선은 본 테스트에서 132%였지만 새 구간에서 8.7% 수익을 기록했습니다. 특정 숫자 하나에 성과가 몰리지 않고 주변 범위에서도 비슷한 결과가 나오는지 확인해야 한다는 교훈을 얻었습니다.
그 뒤에는 최적값 하나를 고르는 대신 구간의 모양을 먼저 봤습니다. 이동평균 조합을 15~25일과 55~75일 범위로 묶어 각각의 결과를 표로 만들고, 수익률보다 손실 구간의 길이와 거래 수 변화를 비교했습니다. 21일과 64일에서만 수익이 튀고 주변 값에서 급락하는 전략은 제외했습니다. 최종적으로 선택한 조합은 수익률이 246%에서 118%로 낮아졌지만, 파라미터를 조금 바꿔도 성과가 크게 흔들리지 않았습니다.

3. 제가 놓쳤던 데이터 누수와 시간의 착각

더 당황스러웠던 실수는 가격 정규화 과정에서 발생했습니다. 저는 2018년부터 2024년까지 전체 종목의 평균 거래대금을 한 번에 계산한 뒤, 2019년 시점의 종목 선별 조건에도 그 값을 사용했습니다. 2024년의 거래량이 이미 계산에 들어간 상태였으니 과거 시점에서는 알 수 없는 정보가 신호에 섞여 있었습니다. 이 부분을 연도별 누적 평균으로 바꾸자 수익률이 118%에서 76%로 내려갔습니다.
일봉 주문 처리에서도 미래를 훔쳐보고 있었습니다. 당일 종가가 50일 이동평균을 상향 돌파하면 종가에 매수하도록 코드를 작성했는데, 실제로는 종가가 확정되는 순간 주문을 넣어도 그 가격에 체결된다는 보장이 없습니다. 체결 시점을 다음 거래일 시가로 미루고 0.15% 슬리피지를 적용하자 연간 거래 비용이 42만 원에서 119만 원으로 늘었고, 일부 연도는 수익이 손실로 바뀌었습니다.

4. 시간을 한 칸씩 밀어 가며 다시 검증한 과정

2024년 7월에는 검증 절차를 전진 방식으로 다시 구성했습니다. 먼저 2018년부터 2020년까지로 파라미터를 고른 뒤 2021년 1월부터 6월까지 검증했고, 다음에는 2018년부터 2021년 6월까지 학습 구간을 넓혀 2021년 7월부터 12월까지 확인했습니다. 같은 과정을 2024년 6월까지 반복하니 구간마다 선택되는 숫자가 달라졌고, 단일 백테스트에서 보이지 않던 약점이 드러났습니다.
전진 검증 결과 훈련 구간 수익률은 평균 92%였지만 검증 구간 평균은 18.6%에 그쳤습니다. 특히 2022년 하락장에서는 네 번의 검증 구간 중 세 번이 손실로 끝났고 최대 낙폭은 24.3%까지 커졌습니다. 저는 이 결과를 실패로만 보지 않았습니다. 전략이 상승장 추세에는 반응하지만 급락장에서는 현금 비중을 충분히 늘리지 못한다는 성격을 파악했고, 운용 중단 조건을 별도로 두게 됐습니다.

5. 실전 투입 전 제가 남긴 점검표

현재는 마지막 20% 기간을 어떤 최적화에도 사용하지 않는 규칙을 지키고 있습니다. 2018년부터 2023년 6월까지 전략을 조정한 뒤, 2023년 7월부터 2024년 12월까지는 결과를 열어 보지 않고 보관했습니다. 또한 수수료 0.015%, 매도 세금 0.18%, 슬리피지 0.15%를 넣고 거래 정정이나 미체결 상황도 별도로 기록합니다. 이렇게 계산한 성과가 낮아도 실제 주문 환경과 가까운 결과를 우선합니다.
제가 지금 백테스트를 볼 때 가장 먼저 확인하는 값은 누적 수익률이 아닙니다. 연도별 손익, 월별 손실 연속 횟수, 파라미터 주변 성과, 수수료를 뺀 뒤의 순손익을 차례로 확인합니다. 백테스트 파일에는 신호 발생 시각과 주문 제출 시각도 함께 저장합니다. 독자 여러분도 전략을 검토할 때 아름다운 그래프 하나보다 미래 정보가 들어갈 틈이 없었는지, 숫자를 조금 바꿔도 버티는지, 실제 비용을 감당하는지를 먼저 기록해 보시기 바랍니다. 제가 겪은 손실은 검증을 더 번거롭게 만든 대가였지만, 그 덕분에 과거에 맞춘 전략과 시장에서 견디는 전략을 구분하는 기준을 갖게 됐습니다.