백테스트 vs 실전 매매: 실제 결과가 다르게 나오는 이유
실전 매매 결과가 백테스트와 다른 이유를 체결, 슬리피지, 수수료, 지연, 데이터 품질, 미래 참조 편향, 시장 국면 변화로 나눠 살펴보고, 올바른 사전 검증 방법을 알아봅니다.
전략을 만들어 본 트레이더라면 거의 누구나 이런 순간을 겪습니다. 백테스트는 훌륭해 보였는데, 실전에서 몇 주 돌려 보니 그림이 완전히 달라진 것이죠. 그렇다고 전략이 반드시 나쁘다는 뜻은 아닙니다. 백테스트는 현실의 모델이고, 모든 모델에는 가정이 있다는 뜻입니다. 이 글에서는 괴리의 주요 원인과 그 차이를 줄이는 방법을 살펴봅니다.
백테스트가 실제로 측정하는 것
백테스트는 과거 가격 데이터 위에서 전략의 규칙을 돌려, 그 규칙대로 매매했다면 어떤 결과가 나왔을지 계산합니다. 예를 들어 TradingView의 Strategy Tester는 Pine Script로 작성된 전략에 대해 이 작업을 합니다. 결과는 추정치이지, 과거를 녹화한 기록이 아닙니다.
문제는 백테스트가 데이터에 있는 것만 "안다"는 점입니다. 데이터가 5분봉이라면 봉 내부에서 무슨 일이 있었는지 모릅니다. 수수료를 설정하지 않았다면 매매가 공짜라고 가정합니다. 슬리피지를 설정하지 않았다면 모든 주문이 원하는 가격에 정확히 체결된다고 가정합니다. 이 가정 하나하나가 결과를 위쪽으로 부풀립니다.
체결과 슬리피지
대부분의 트레이더에게 이것이 괴리의 가장 큰 원인입니다.
- 시장가 주문은 판단 시점에 차트에 보이던 가격이 아니라 그다음 가능한 가격에 체결됩니다. 고용지표 발표 같은 변동성 큰 순간에는 그 차이가 여러 틱이 될 수 있습니다.
- 지정가 주문은 가격은 보장하지만 체결은 보장하지 않습니다. 많은 백테스트가 가격이 해당 레벨에 닿기만 하면 체결된 것으로 가정합니다. 실제로는 대기열 맨 뒤에 있어서 끝내 체결되지 않았을 수 있고, 그런 일은 종종 가장 좋은 매매에서 일어납니다.
- 스톱 주문은 발동되는 순간 시장가 주문이 되므로, 지정한 레벨에서 멀리 떨어져 체결될 수 있습니다.
가상의 예를 들어 보겠습니다. 어떤 전략이 MNQ에서 1년에 400번 매매합니다. 매 거래마다 진입에서 평균 1틱, 청산에서 1틱의 슬리피지가 발생하면, 백테스트에는 한 번도 나타나지 않은 800틱이 1년 동안 쌓입니다. 엣지가 작은 전략이라면 이것이 전부를 가를 수 있습니다. 자세한 내용은 슬리피지와 체결 비용을 참고하세요.
수수료, 거래소 수수료, 데이터 비용
선물 거래에는 항상 비용이 따릅니다. 브로커 수수료, 거래소 및 규제 수수료, 때로는 플랫폼 이용료도 있습니다. 비교적 매매 빈도가 높은 전략일수록 특히 민감합니다. 간단한 원칙은 백테스트에 보수적인 비용, 즉 실제로 낼 것으로 예상하는 금액보다 약간 높은 비용을 설정하는 것입니다.
지연(레이턴시)
조건이 충족된 순간부터 주문이 거래소에 도달하기까지는 시간이 걸립니다. 봉이 마감되고, 알림이 발송되고, webhook이 수신되어 처리되고, 주문이 브로커로 전달됩니다. 보통은 몇 초 이내의 일이지만, 빠른 장에서는 그것도 중요합니다. 봉 마감 시점에 정확히 진입하는 것을 전제로 만든 전략은 실제로는 항상 약간 다른 가격을 받게 됩니다.
데이터 품질과 편향
- 미래 참조 편향(look-ahead bias): 판단 시점에는 알 수 없었던 정보를 코드가 사용하는 경우입니다. 대표적인 예는 봉의 종가를 보고 판단했는데 같은 봉의 시가에 진입하는 것입니다. 상위 타임프레임 데이터를 부주의하게 쓰는 것도 원인이 될 수 있습니다.
- 리페인팅(repainting): 나중에 과거 값을 바꾸는 지표입니다. 차트상으로는 신호가 완벽해 보이지만, 실시간으로는 나타났다가 사라졌던 신호입니다.
- 생존 편향: 주로 주식에 해당하며, 오늘날까지 살아남은 종목만으로 테스트하는 문제입니다. 선물에서 이에 해당하는 문제는 서로 다른 계약을 이어 붙인 연속 차트(NQ1! 등)로, 롤오버 날짜에 인위적인 가격 점프가 생길 수 있습니다.
- 누락되거나 잘못된 데이터: 빠진 봉, 잘못된 세션 시간, 틀린 시간대 설정 등입니다.
시장 국면 변화
기술적으로 완벽한 백테스트라도 과거를 설명할 뿐입니다. 시장은 고변동성과 저변동성, 추세장과 횡보장을 오갑니다. 특정 성격을 가진 한 해를 중심으로 테스트한 전략은 다음 기간에 전혀 다르게 움직일 수 있습니다. 테스트 기간이 길고 다양할수록 그림은 더 믿을 만해지지만, 결코 보장되지는 않습니다. 이와 밀접한 문제가 과최적화이며, 트레이딩 전략의 과최적화에서 다룹니다.
포워드 테스트와 시뮬레이션
괴리를 메우는 가장 좋은 방법은 중간 단계를 두는 것입니다. 실전에서 사용할 것과 똑같은 실행 경로로, 시뮬레이션 계좌에서 전략을 실시간으로 돌리는 것이죠. 이를 포워드 테스트 또는 페이퍼 트레이딩이라고 합니다.
이 단계에서 확인할 것:
- 알림이 제때, 올바른 형식으로 도착하는가?
- 신호 가격과 체결 가격 사이의 평균 차이는 얼마인가?
- 매매 횟수가 백테스트에서 예상한 것과 비슷한가?
- 중복되거나 누락된 매매, 또는 "고아" 포지션이 있는가?
- 장 시작, 장 마감, 지표 발표 전후의 동작이 합리적인가?
모든 매매를 매매일지에 기록하고 같은 기간의 백테스트와 비교하세요. 측정한 괴리는 귀중한 정보입니다. 이를 현실적인 슬리피지 가정으로 백테스트에 다시 반영할 수 있습니다.
현실적인 기대치
- 실전 결과는 백테스트보다 약할 것이라고 가정하고 그에 맞춰 계획하세요.
- 수수료와 슬리피지가 없어야만 수익이 나는 전략이라면 실제 엣지는 없는 것입니다.
- 짧은 시뮬레이션 기간은 어느 쪽으로도 아무것도 증명하지 못합니다. 주로 연결 구조를 점검하는 용도입니다.
- 실전 초기 포지션 규모는 작게 시작하고, 실행이 예상대로 동작하는 것을 확인한 뒤에만 늘리세요.
핵심 정리
- 백테스트는 가정이 들어간 모델이며, 그 가정 대부분이 결과를 위쪽으로 부풀립니다.
- 슬리피지, 지정가 주문 체결, 수수료가 괴리의 가장 큰 원인입니다.
- 미래 참조 편향과 리페인팅은 실시간으로는 결코 달성할 수 없었던 결과를 만들어 낼 수 있습니다.
- 같은 실행 경로를 사용한 시뮬레이션 포워드 테스트는 필수 단계입니다.
- 실제 괴리를 측정하고 그것을 테스트에 다시 반영하세요.
TradingView 알림을 사용한다면, WeCore로 알림을 본인 계좌에 연결하고 먼저 시뮬레이션 모드에서 돌려 볼 수 있습니다. 실계좌로 넘어가기 전에 체결, 타이밍, 리스크 규칙을 점검할 수 있죠. 기본 개념은 알고리즘 트레이딩이란을 참고하세요.