백테스트에서 좋아 보이는 값이 나왔다고 곧바로 운영 파라미터를 바꿀 수는 없어요. 이번에는 먼저 측정 기반을 복구한 뒤 표본 밖에서도 결과가 재현되는지 확인했고, 결국 현재 데이터만으로는 변경을 정당화할 수 없다는 결론을 내렸어요.
백테스트 절차는 있었지만 측정할 데이터가 부족했다
파라미터를 선택하는 절차는 이미 마련돼 있었어요. 앞쪽의 표본 내 데이터에서 후보를 고르고, 선택에 쓰지 않은 표본 밖 데이터로 성능을 확인하는 방식이었어요.
문제는 절차가 아니라 데이터였어요. 보유한 시세가 약 열 달치뿐이라 검증 구간을 둘로만 나눌 수 있었고, 두 구간의 시장 환경도 크게 달랐어요. 한쪽은 +96.7% 상승장이었고 다른 쪽은 −21.8% 하락장이었어요.
단기 매매 전략의 청산 밴드를 비교한 결과에서도 데이터 부족의 영향이 그대로 드러났어요.
| 청산 밴드 | 표본 내 2026-01-02~05-29 | 표본 밖 06-01~08-18 |
|---|---|---|
| +10 / −5, 현행 | +42.78% | −33.35% |
| +15 / −7 | +21.83% | −29.80% |
| +20 / −10 | −14.58% | −37.00% |
| +30 / −15 | +19.00% | +1.53% |
표본 내에서는 현행값이 가장 좋았지만 표본 밖에서는 −33.35%를 기록했어요. 표본 내 선택 대상이 아니었던 +30 / −15는 표본 밖에서 유일하게 플러스 수익률을 냈고, 두 결과의 차이는 35%p에 달했어요.
밴드를 넓힌다고 결과가 일관되게 좋아지거나 나빠지지도 않았어요. 중간값은 양쪽 구간에서 모두 가장 나빴고, 이 상태로는 파라미터의 방향조차 판단하기 어려웠어요.
파라미터를 바꾸려면 먼저 측정 기반부터 바로잡아야 했어요.
before 커서로 과거 5년 시세를 이어 받았다
시세 제공 API의 before 커서를 활용해 과거 데이터를 연속으로 수집하는 경로를 추가했어요. 최근 데이터만 한 번 조회하던 방식에서 벗어나 목표 기간에 도달할 때까지 이전 시세를 계속 이어서 받도록 했어요.
첫 번째 변경에서는 파라미터를 하나도 바꾸지 않고, 백테스트에 필요한 시세를 5년으로 확장하는 데 집중했어요.
전체 종목을 백필한 결과는 이랬어요.
- 대상 종목: 약 2,600개
- 실행 시간: 약 1시간
- 수집된 일봉: 약 280만 건
- 목표 기간 도달: 약 2,100종목
- 기존 이력 충분: 소수 종목
- 최초 실행에서 커서 미진전으로 분류: 수백 종목
- 별도 실패: 소수 종목
하지만 수백 종목을 공급자 이상으로 분류한 결과는 실제 상태와 맞지 않았어요.
데이터 소진과 공급자 이상을 구분했다
문제가 된 종목은 대부분 상장한 지 5년이 지나지 않은 종목이었어요. 목표로 한 5년치 데이터를 제공하지 못한 게 아니라, 상장일부터 현재까지 존재하는 데이터를 정상적으로 모두 제공한 상태였어요.
원장을 확인해 보니 5년 미만의 이력을 가진 수백 종목 가운데 대부분은 가장 오래된 봉의 날짜가 실제 상장일과 일치했어요.
| 종목 | 상장일 | 가장 오래된 봉 | 봉 수 |
|---|---|---|---|
| 종목 A | 2023-12-22 | 2023-12-22 | 약 650 |
| 종목 B | 2024-03-13 | 2024-03-13 | 약 600 |
| 종목 C | 2025-03-14 | 2025-03-14 | 약 350 |
오분류의 원인은 API가 커서를 처리하는 방식에 있었어요. 시세 조회 API는 before로 전달한 날짜의 봉도 응답에 다시 포함했어요. 상장일까지 모두 받은 뒤 다음 페이지를 요청하면 커서 날짜와 같은 봉 하나만 반환되기도 했어요.
기존 로직은 이 상황을 단순히 “커서가 진전하지 않았다”고 판단했어요. 정상적으로 데이터를 모두 받은 경우와 같은 페이지가 비정상적으로 반복되는 경우를 구분하지 못한 거예요.
후속 변경에서는 커서 날짜의 봉 하나만 반환되는 종료 형태를 정상적인 이력 소진으로 판단하도록 수정했어요. 설명되지 않은 소수 종목은 정상 사례에 포함하지 않고 별도 확인 대상으로 남겼어요.
단순히 로그만 정리하는 문제는 아니었어요. 데이터 공급 상태를 잘못 해석하면 정상 종목 수백 개를 결함 데이터로 취급하게 되고, 이후 백테스트의 신뢰 범위도 잘못 판단할 수 있으니까요.
데이터가 아니라 지표가 죽어 있었다
시세를 확장한 뒤 기존 측정을 다시 살펴보니 더 근본적인 문제가 드러났어요. 과거에 진행한 수십 회의 파라미터 측정에서 일부 핵심 지표가 사실상 작동하지 않았어요.
120일 이동평균, 6개월 수익률, 200일 고점 대비 위치 같은 지표를 계산하려면 과거 봉을 충분히 확보해야 해요. 하지만 열 달치 데이터로 백테스트 앞부분을 계산하면 필요한 봉 수를 채우지 못해 값이 null로 남아요.
5년 백필 전후로 지표를 사용할 수 있는 종목 수가 크게 달라졌어요.
| 지표 | 필요 봉 수 | 백필 전 2026-01-02 시점 | 백필 후 |
|---|---|---|---|
| 60일 거래대금 | 60 | 없음 | 대부분의 종목 |
| 120일 이동평균 | 120 | 없음 | 대부분의 종목 |
| 200일 고점 대비 위치 | 200 | 없음 | 대부분의 종목 |
결측의 영향은 일부 계산 결과가 비는 데서 끝나지 않았어요. 해당 지표를 사용하는 후보 선정과 보유 로직 자체가 달라졌기 때문이에요.
동일한 코드로 같은 구간을 측정했지만 시세 백필 전후의 단기 매매 전략 결과는 달랐어요.
| 단기 매매 전략 측정값 | 백필 전 | 백필 후 |
|---|---|---|
| 시장 대표 지수 초과수익 | −7.86% | −3.58% |
| 최종 수익률 | −63.81% | −39.20% |
장기 보유 전략에서는 평균 보유 기간이 9일에서 91일로 바뀌었어요. 이전에는 120일 이동평균이 없어 정상적인 후보가 거의 나오지 않았고, 우연히 선택된 종목을 짧게 매매하는 결과로 이어졌어요.
기존 수십 회의 측정은 같은 전략을 불완전하게 측정한 정도가 아니었어요. 입력 지표가 결측된 탓에 다른 방식으로 움직인 시스템을 측정한 결과에 가까웠어요.
이 사실과 재측정 조건은 원장과 인수인계 문서에 기록했어요. 잘못된 숫자를 조용히 덮어쓰지 않고 왜 무효인지 추적할 수 있도록 남겼어요.
시장 벤치마크도 같은 기간으로 확장했다
개별 종목 시세를 5년으로 늘렸지만 곧바로 파라미터를 다시 측정할 수는 없었어요. 시장 국면을 상승·하락·횡보로 구분하고 초과수익을 계산하려면 같은 기간의 시장 대표 지수가 필요했어요.
당시 개별 종목 일봉 테이블에는 2020-12-03부터 약 330만 행이 있었지만 벤치마크 종가 테이블에는 2025-10-21 이후 약 200행만 있었어요. 기존 벤치마크 수집 작업 역시 최근 200봉을 한 번 조회하는 단발 호출이라 과거 구간을 채울 수 없었어요.
재측정 변경에서는 먼저 시장 벤치마크를 과거로 소급해 수집하는 경로를 마련했어요. 종목 데이터만 길고 벤치마크는 짧은 비대칭을 해소한 뒤에야 과거 구간의 시장 환경과 전략 초과수익을 함께 측정할 수 있었어요.
여섯 국면에서 선택하고 사용하지 않은 구간에서 검증했다
측정 전제를 복구한 뒤 거래대금 하한, 보유일수, 청산 밴드라는 세 파라미터 축을 다시 측정했어요. 한두 구간의 결과에 의존하지 않도록 상승·하락·횡보를 아우르는 여섯 시장 구간을 사용했어요.
검증할 때는 표본 내 결과만 보고 결론을 내리지 않는 것이 중요했어요. 먼저 일부 구간에서 후보 값을 비교하고, 그 결과를 바탕으로 고른 값을 파라미터 선택에 전혀 사용하지 않은 구간에 적용했어요. 이 표본 밖 구간에서 선택한 값이 이후에도 재현되는지 확인했어요.
표본 내에서 좋아 보이는 후보는 있었지만 그 우위는 표본 밖 구간에서 재현되지 않았어요. 특정 구간에서 높은 결과가 나왔다는 이유만으로 값을 바꾸면 데이터에 맞춘 선택을 운영 규칙의 개선으로 오해할 가능성이 컸어요.
최종 변경 사항은 ‘파라미터를 바꾸지 않는 것’이었다
재측정에서 새로운 최적값을 찾지는 못했어요. 세 파라미터 축 모두 현행값보다 안정적으로 낫다고 판단할 근거를 확보하지 못했어요.
운영 파라미터는 그대로 유지했어요. 파라미터를 바꾸지 않았다고 해서 작업 결과가 없는 것은 아니에요. 이번 작업으로 “현행값이 최적”임을 증명한 게 아니라, “현재 데이터로는 변경을 정당화할 수 없다”는 판단을 검증했어요.
측정값보다 먼저 확인해야 하는 것
이번 과정을 보면 백테스트 결과를 해석하기 전에 무엇부터 확인해야 하는지 알 수 있어요.
먼저 지표를 계산할 만큼 충분한 길이의 데이터를 확보했는지 확인해야 해요. 실행에 성공했다고 해서 지표까지 유효한 것은 아니에요.
그다음에는 데이터 수집이 끝난 상태를 구체적으로 분류해야 해요. 목표 기간에 도달하지 못했다는 이유만으로 공급자 이상이라고 판단할 수는 없어요. 상장일처럼 데이터가 실제로 시작되는 경계를 고려해야 해요.
전략 데이터와 벤치마크의 기간도 맞춰야 해요. 시장 국면과 초과수익을 계산할 기준이 없다면 장기간 시세만으로는 충분히 검증할 수 없어요.
마지막으로 표본 밖 검증에서 재현되지 않은 개선은 운영 변경의 근거로 삼지 않아야 해요. 백테스트의 목적은 가장 좋아 보이는 숫자를 찾는 것이 아니라, 보지 않은 데이터에서도 유지되는 판단을 찾는 데 있기 때문이에요.
이번에 내린 판단은 비변경이었어요. 데이터 수집부터 지표 가용성, 벤치마크, 표본 밖 재현성까지 확인했기에 내릴 수 있었던 결론이에요.