백테스트가 거짓말하는 가장 흔한 방식

2026-07-16

수익률 400%짜리 전략 백테스트를 보게 되면, 물어야 할 질문은 "어떻게 그렇게 벌었나"가 아닙니다. "이 전략은 각 시점에, 그 시점까지의 정보만으로 종목을 골랐는가"입니다.

대부분의 환상적인 백테스트는 이 질문에서 무너집니다. 오늘 아는 정보가 과거의 선택에 스며들어 있기 때문입니다. 이걸 미래 데이터 누수(lookahead bias)라고 부릅니다. 그리고 이 함정의 가장 큰 특징은, 일부러 속이려는 사람만 빠지는 게 아니라는 겁니다. 성실하게 만든 백테스트에도 조용히 스며듭니다.

가장 노골적인 형태 — 그리고 그게 바로 이 사이트입니다

미래 데이터 누수의 가장 순수한 형태는 이것입니다. "지난 5년간 가장 많이 오른 종목을 5년 전에 샀다면?"

답은 당연히 환상적입니다. +3,582%. 하지만 이 계산에는 사기가 하나 숨어 있습니다 — "가장 많이 오른 종목"이라는 목록 자체가 5년이 지난 오늘에야 알 수 있는 정보라는 것. 5년 전의 당신은 그 목록을 가질 수 없었습니다. 목록을 아는 순간 이미 수익률은 확정돼 있습니다. 이건 전략이 아니라 채점이 끝난 답안지입니다.

눈치채셨겠지만, FomoBot이 매일 하는 일이 정확히 이것입니다. 이 사이트는 미래 데이터 누수의 전시장입니다. 의도적으로요. "그때 샀어야 했는데"는 결국 다 지나고 나서야 아는 것(hindsight)이고, 우리는 그 사후의 앎에 정직한 라벨을 붙여 보여줍니다 — 이건 기록이지 전략이 아니라고.

위험한 건 라벨이 떨어질 때입니다. "5년 1위 목록"이 "앞으로 5년 유망주 목록"으로 읽히는 순간, 그리고 "이 전략의 과거 수익률"에 미래 정보가 몰래 섞여 들어가는 순간. 전자는 이미 다뤘으니, 이 글은 후자 — 검증 과정에 누수가 스며드는 방식 — 을 다룹니다.

몰래 스며드는 형태들

노골적인 누수는 오히려 잡기 쉽습니다. 문제는 교묘한 쪽입니다.

선택의 누수. "우량주 100개로 전략을 검증했다"는 백테스트에서, 그 100개를 어떻게 골랐는지 물어보십시오. 지금 시점의 우량주라면 — 지난 10년을 살아남아 커진 회사들이라면 — 목록 자체에 이미 미래가 들어 있습니다. 그 종목들이 잘될 것을 알고 고른 것과 같습니다. 생존 편향도 이 계열입니다. 상장폐지된 종목이 빠진 유니버스는 "끝까지 살아남는다"는 미래 정보가 반영된 유니버스입니다.

겹침의 누수. 검증 구간들이 서로 겹치면 같은 상승분이 여러 번 계산됩니다. 우리도 한 번 걸릴 뻔했습니다 — 1주 수익률 상위와 1개월 수익률 상위의 교집합으로 "랭킹의 지속성"을 재려 했는데, 1주 창이 1개월 창 안에 통째로 들어 있어서 교집합이 높게 나오는 건 지속성이 아니라 산수였습니다. 그래서 급등주 검증에서는 앵커를 30~35일씩 벌려 구간이 겹치지 않게 만들었습니다. T 시점의 포트폴리오는 T까지의 데이터로만 구성하고, 평가는 그 이후 구간에서만 합니다.

값 자체의 누수. 가장 교묘한 형태입니다. 수정주가는 소급 조정되는 값입니다. 오늘 조회한 "3년 전 종가"에는 그 사이의 분할·배당 정보가 반영돼 있습니다. 수익률 계산에는 이게 맞는 처리지만, "그날의 투자자가 화면에서 본 가격"과는 다른 숫자라는 건 알고 써야 합니다. 과거 데이터라고 해서 과거에 존재했던 데이터인 건 아닙니다.

부동산 랭킹의 창이 비대칭인 이유

이 원칙이 FomoBot 설계에 실제로 박혀 있는 곳이 부동산 랭킹의 앵커 윈도우입니다.

앞서 설명했듯 아파트는 거래가 드물어서, 시점의 가격 대신 그 시점 둘레의 창에 담긴 실거래로 대표 가격을 만듭니다. 여기서 설계 질문이 하나 나옵니다. 창을 어느 방향으로 열 것인가.

기준 시점 앞뒤로 대칭으로 여는 게 통계적으로는 좋습니다. 표본이 두 배가 되니까요. 하지만 FomoBot의 창은 비대칭입니다.

종료 창이 과거로만 나 있는 이유가 바로 누수 방지입니다. 어느 날짜의 랭킹은 그 날짜에 만들 수 있었던 랭킹이어야 합니다. 창이 기준일 너머로 열려 있으면, 그 랭킹은 미래의 거래를 미리 보고 만든 순위가 됩니다. 그 순위로 백테스트를 하면 그날 알 수 없었던 정보가 성과에 섞입니다.

반면 시작 창은 사정이 다릅니다. 시작 시점은 이미 깊은 과거라, 그 앞뒤의 거래는 전부 랭킹 기준일보다 앞선 데이터입니다. 대칭으로 열어도 미래를 보는 게 아닙니다. 그래서 표본을 위해 벌립니다 — 단, 벌린 시작 창이 종료 창과 겹치지 않을 만큼 전체 기간이 길 때만입니다. 이건 우연히 그렇게 된 게 아니라, 계산 로직의 주석이 "종료 앵커와 겹치지 않게"라고 그 의도를 명시하고 있습니다. 두 창이 겹치면 같은 거래가 시작 가격과 종료 가격 양쪽에 들어가 상승률이 뭉개지기 때문입니다.

이 비대칭에는 대가가 있습니다. 종료 창은 한쪽 방향의 표본밖에 못 쓰므로, 시작 창보다 구조적으로 더 불안정한 추정치입니다. 정확도를 일부 포기하고 정직함을 산 겁니다. 미래를 슬쩍 보면 더 매끈한 숫자가 나오지만, 그 숫자는 그날 존재할 수 없었던 숫자입니다.

같은 원칙이 종료월을 고르는 데도 적용됩니다. 국내 아파트 실거래는 계약 후 신고까지 최대 30일이 걸려서, 이번 달과 지난달 데이터는 아직 다 채워지지 않은 상태입니다. 이 미완성 최근월을 랭킹 기준으로 쓰면, "지금 보면 낮지만 신고가 다 들어오면 달라질" 숫자로 순위를 매기는 셈이 됩니다. 그래서 FomoBot의 부동산 랭킹은 종료월로 언제나 "전전월"을 씁니다. 신고 기한 30일에 다시 한 달의 여유를 더 얹어, 거래가 충분히 신고된 달만 순위에 올립니다. 최신 데이터를 포기하는 대신 다 채워진 데이터를 택한 겁니다. 이것도 같은 종류의 맞교환입니다.

남의 백테스트에서 누수를 찾는 법

어떤 전략의 과거 성과를 보게 되면, 세 가지를 물으십시오.

1. 종목 목록은 언제 시점의 지식으로 만들어졌는가. "우량주", "대표 종목", "주요 코인" 같은 표현이 나오면 그 목록의 선정 시점을 물으십시오. 지금 기준으로 골랐다면 이미 누수입니다.

2. 각 매매 시점에 그 정보가 실제로 존재했는가. 재무제표는 분기가 끝나고 한참 뒤에 공시됩니다. "1분기 실적이 좋은 종목을 4월 1일에 산다"는 규칙은 아직 공시되지 않은 실적을 보는 것일 수 있습니다.

3. 검증 구간이 서로 겹치는가. 겹치는 창에서 나온 통계는 표본 수가 부풀려져 있고, 같은 사건을 여러 번 셉니다. 독립된 구간 수가 진짜 표본 수입니다.

그리고 마지막으로 — 이 사이트의 숫자를 볼 때도 같은 질문을 던지십시오. FomoBot의 랭킹은 지나고 나서 되짚은 것이고, 우리는 그걸 숨기는 대신 라벨을 붙였습니다. 라벨이 안 붙은 채 "전략"으로 포장된 뒷북이 세상에는 훨씬 많습니다.

방법론 전체 보기 →

이 글에 관하여 — 부동산 앵커 윈도우의 비대칭 구조(종료 창 과거 방향 고정, 시작 창은 전체 기간이 창 폭의 2배를 넘을 때만 대칭)와 종료월을 전전월로 두는 처리는 FomoBot의 실제 랭킹 계산 로직이며, 계산 코드의 주석에 그 의도가 명시돼 있습니다. 창의 소급 폭은 3개월이며, 시작·종료 월이 포함되므로 실제 집계 폭은 약 4개월입니다. 자세한 내용은 방법론관련 글을 참고하십시오.

투자 판단에 대하여 — FomoBot은 이미 지나간 가격을 정리해 보여주는 도구입니다. 특정 종목·단지의 매수·매도를 권유하지 않으며, 이 글의 어떤 내용도 투자 자문이 아닙니다. 투자 손익의 책임은 투자자 본인에게 있습니다.