Problems in Backtesting and Biases in Data
2023년 초, 간단한 모멘텀 전략을 5년 백테스트했더니 연평균 18% 수익이 나왔습니다. 흥분해서 실전 계좌에 넣었는데, 6개월 만에 -7%였죠. 나중에 알고 보니 백테스트 데이터에 상장폐지된 종목 200여 개가 빠져 있었습니다. 이걸 생존편향(survivorship bias)이라고 하는데요. 야후 파이낸스 같은 무료 데이터는 현재 살아있는 종목만 제공하거든요. 10년 기간 북미 주식의 75%가 이런 식으로 누락되면 백테스트 결과는 현실보다 훨씬 좋게 나옵니다. 이 글을 읽고 나면 상장폐지 종목을 포함한 point-in-time 데이터로 전환해서, 과대평가된 수익률을 실제 수준으로 교정하는 방법을 알게 됩니다.
준비물
백테스트 전략 코드를 돌릴 수 있는 환경이 필요합니다. Python 3.x에 pandas가 설치돼 있거나, 클라우드 백테스트 플랫폼 계정이면 됩니다. 비교 실험을 하려면 같은 전략을 두 번 돌릴 수 있게 데이터 로더가 분리돼 있어야 해요. 현재 쓰는 데이터가 편향돼 있는지 30초 만에 확인하는 방법은 이렇습니다. 5년 전 날짜로 종목 리스트를 뽑아서 개수를 세본 뒤, 그 시점 공식 구성종목 수와 비교해보세요. 차이가 10% 이상 나면 상장폐지 종목이 누락된 거예요. 최소 5년치 일별 데이터와 리밸런싱 날짜 기준도 필요합니다.
현재 데이터에서 얼마나 많은 종목이 빠졌나요?
S&P 500 지수를 예로 들어볼게요. 2020년 1월 시점 S&P 500 구성종목은 500개였습니다. 그런데 2026년 현재 시점에서 야후 파이낸스로 2020년 데이터를 조회하면 450개 정도만 남아있어요. 나머지 50개는 상장폐지되거나 인수합병으로 사라졌거든요.
입력: 야후 파이낸스 API로 S&P 500 종목 2020년 1월 1일 종가 요청 출력: 450개 종목 데이터만 반환 (실제로는 500개여야 함)
KOSPI200도 마찬가지예요. KRX 정보데이터시스템에서 2015년 1월 KOSPI200 구성종목 200개를 조회한 뒤, 2026년 현재 증권사 API로 같은 날짜 데이터를 받으면 165개 정도만 남습니다. 35개는 상장폐지·합병·지수 제외로 사라진 거죠. 이런 종목들은 대부분 -50% 이상 하락 후 사라지기 때문에, 이들을 빼고 백테스트하면 수익률이 부풀려집니다 (출처: Quantified Strategies).
상장폐지 종목을 어디서 구하죠?
point-in-time 데이터는 특정 시점에 실제로 거래 가능했던 종목만 담고 있어요. Norgate Data는 미국·호주·캐나다 주식의 상장폐지 종목까지 포함한 데이터를 월 구독으로 제공합니다. QuantConnect는 클라우드 백테스트 플랫폼이라 데이터가 자동으로 붙어 나오고요. 한국 주식은 KRX 정보데이터시스템 '과거 지수 구성종목' 메뉴에서 KOSPI200, KOSPI100 등의 특정 날짜 구성종목 리스트를 CSV로 받을 수 있습니다.
제가 2024년에 Norgate Data로 전환했을 때 2015-2025년 10년 백테스트 기준으로 상장폐지 종목이 312개 더 들어있더라고요. 이 312개를 제외하고 돌린 전략은 연 12% 수익이었는데, 포함하고 돌리니 연 6.8%로 떨어졌습니다.
동일 전략을 두 데이터셋으로 재실행하기
이제 실제 비교 작업을 해봅시다. 간단한 월간 모멘텀 전략을 예로 들게요. 매월 말일에 S&P 500 종목 중 최근 1개월 수익률 상위 20종목을 동일 비중으로 매수하고, 다음 달 말일에 리밸런싱하는 전략입니다. 조건은 2018-2023년 5년, 월 1회 리밸런싱, 수수료 0.1%, 슬리피지 0.05%로 통일했어요.
생존편향 데이터(야후 파이낸스)로 돌렸을 때:
- 총 거래 횟수: 약 1200회
- 연평균 수익률: 15.2%
- MDD: -28%
point-in-time 데이터(Norgate Data)로 재실행:
- 총 거래 횟수: 약 1450회 (상장폐지 종목 매도 포함)
- 연평균 수익률: 8.1%
- MDD: -35%
차이가 왜 이렇게 클까요? 상장폐지되는 종목들은 보통 주가가 -70%, -90% 폭락한 뒤 사라지거든요. 모멘텀 전략은 하락 종목을 자동으로 걸러내지만, 급락 구간에서 일시적으로 보유하게 되는 경우가 생깁니다. 생존편향 데이터는 이런 폭락 구간 자체를 기록에서 지워버리니까, 백테스트 결과가 실제보다 좋게 나오는 거예요 (출처: QuantConnect 공식 문서).
흔한 실수와 해결법
실수 1: "지수 구성종목만 거래하면 괜찮겠지" S&P 500도 매년 20~30개 종목이 편입·제외됩니다. 2020년 12월에 Tesla가 편입됐고, 2023년에는 SVB Financial이 파산으로 제외됐죠. 현재 시점 데이터로 2020년 상반기를 백테스트하면 Tesla를 포함해버리는데, 실제로는 그때 지수에 없었거든요.
실수 2: "무료 데이터로 충분해" 초기 아이디어 검증은 무료 데이터로 가능합니다. 하지만 실전 투입 전에는 유료 데이터로 재검증이 필수예요. 제 경험상 무료→유료 전환 후 수익률이 30~50% 하락하는 게 일반적이었습니다.
마무리: 데이터부터 고치세요
지금 쓰는 전략이 있다면, 내일 아침 KRX 정보데이터시스템에서 KOSPI 과거 구성종목 엑셀을 한 번 받아보세요. 현재 증권사 API 데이터와 비교하면 얼마나 많은 종목이 누락됐는지 바로 보입니다.
자주 묻는 질문
Q. 백테스트 기간을 얼마나 길게 잡아야 생존편향 왜곡을 제대로 측정할 수 있나요? A. 최소 5년은 필요합니다. 기간이 짧으면 사라진 티커 수가 통계적으로 유의미하지 않거든요. 10년 이상 돌려야 연평균 수익률 차이가 3~7%p 수준으로 명확하게 드러나요.
Q. 사라진 티커의 마지막 거래일 가격을 0원으로 처리해야 하나요, 아니면 마지막 종가 그대로 두나요? A. 플랫폼마다 다릅니다. QuantConnect는 마지막 종가를 유지하고 청산 시그널을 보내요. Norgate는 폐지일 전날 종가를 마지막 값으로 기록하죠. 0원 처리는 비현실적이에요 — 실전에서는 그 전에 청산하거든요.
Q. ETF나 인덱스 추종 전략에도 생존편향이 적용되나요? A. ETF 자체는 이 왜곡에서 자유롭습니다. 다만 바스켓을 직접 복제하는 전략이라면 편출입 이력이 point-in-time이어야 해요. KODEX200을 따라 하려면 과거 KOSPI200 편입·제외 기록이 필요하거든요.