Chapter 17

백테스트의 함정

"10년 백테스트 연평균 40%." 이런 광고는 그래프까지 붙어 있어서 그럴듯해 보인다. 그래프는 거짓말을 하지 않는다. 다만 그 그래프를 만든 과정이 거짓말을 할 수 있다. 이 장에서는 규칙을 과거 가격에 돌려 보는 백테스트를 직접 돌려 보고, 수익 곡선을 부풀리는 함정을 하나씩 일부러 밟았다가 걷어 낸다. 마지막에는 그 "연 40%"를 해부해서 무엇이 남는지 본다.

백테스트란: 규칙을 과거에 돌려 보기

12장에서 한결은 유튜브에서 본 골든크로스 규칙을 지수에 시험해 보았다. 그것이 백테스트(Backtest)다. 매매 규칙을 미리 정해 두고, 그 규칙을 과거의 가격 위에서 하루씩 따라가며 "그때 이 규칙대로 샀다면 지금 얼마가 되었을까"를 계산하는 일이다. 결과는 보통 하나의 선, 자산 곡선(Equity curve)으로 나온다.

백테스트는 실제 돈을 걸기 전에 아이디어를 거르는 값싼 체다. 문제는 이 체가 너무 쉽게 만들어진다는 데 있다. 컴퓨터는 수천 개의 규칙을 몇 초 만에 돌릴 수 있고, 그중 가장 멋진 선 하나만 골라 보여 주면 광고가 된다. 그래서 백테스트를 읽는 사람이 알아야 할 것은 "수익이 얼마인가"보다 "이 선이 어떻게 만들어졌는가"다.

과거 데이터 가격·재무 신호 계산 i일까지 정보 가상 체결 i+1일, 비용 자산 곡선 수익·샤프·낙폭 결과를 보고 규칙을 고친다(반복) 생존 편향 사라진 종목이 빠진 데이터 미래 참조 그날 몰랐던 정보를 씀 비용 누락 수수료·세금· 슬리피지·유동성 과최적화 반복할수록 과거에 맞춰짐 기간 고르기(표본 기간 의존)는 이 전체를 감싸는 함정이다. 어느 구간을 돌렸는지에 따라 같은 규칙이 영웅도, 바보도 된다.
그림 17-1. 백테스트의 흐름과 함정이 끼어드는 자리. 위 줄은 백테스트가 하루하루 하는 일이고, 아래 줄은 각 단계에서 결과를 실제보다 좋게 만드는 함정이다. 네 함정 모두 수익을 부풀리는 쪽으로 작용한다는 점이 무섭다.

먼저 엔진을 돌려 보자. 아래는 이 책의 가상의 시장(교육용으로 만든 가짜 가격) SB 종합지수 10년에 12장의 이동평균 교차 규칙을 돌린 결과다. 단기 이동평균이 장기 이동평균보다 위에 있으면 지수를 전부 들고, 아래에 있으면 전부 현금으로 둔다. 두 기간을 바꿔 보면서 매매 표시(▲ 매수, ▼ 매도)와 아래쪽 자산 곡선이 어떻게 바뀌는지 보자.

SIMULATOR

백테스트 엔진: 이동평균 교차 규칙

연평균 수익(CAGR)—
샤프 비율—
최대 낙폭—
매매 횟수—
해볼 것: ① 기본값(20일·60일)에서 전략이 지수 보유보다 낫다. 이것만 보면 규칙을 믿고 싶어진다. ② 단기를 5일로 줄이면 매매가 몇 배로 늘고 수익이 줄어든다. ③ 50일·200일로 바꾸면 이번에는 보유보다 못하다. 같은 "골든크로스"인데 숫자 두 개로 결론이 뒤집힌다. (지수를 전부 사거나 전부 파는 규칙, 편도 비용은 수수료+거래세 절반 약 0.115%, 현금 이자 0)

기본값에서 전략의 연평균 수익은 약 7.1%로, 그냥 들고 있었을 때의 약 5.8%보다 높고 최대 낙폭도 −42%에서 −31%로 얕다. 그런데 단기 5일·장기 20일로 바꾸면 약 2.2%, 50일·200일이면 약 2.2%로 떨어진다. 이 장의 거의 모든 함정은 이 한 장면에서 출발한다. 어떤 숫자 조합이 과거에 잘 맞았다는 사실은, 그 조합이 앞으로도 잘 맞는다는 증거가 되기 어렵다.

엔진이 하루에 하는 일

백테스트 엔진이 정직하려면 한 가지 순서를 지켜야 한다. i일 장이 끝나고 종가가 나오면 그 종가까지의 정보로 신호를 계산한다. 그 신호로 주문을 낼 수 있는 가장 이른 때는 다음 거래일이다. 이 책의 엔진(ST.backtest)은 보수적으로 i일의 신호를 i+1일 종가에 체결한다. 아래에서 하루씩 넘기며 그 순서를 눈으로 따라가 보자. 오른쪽의 어두운 부분은 아직 오지 않은 날이다. 엔진도 그 안을 볼 수 없어야 한다.

SIMULATOR

하루씩 넘기는 백테스트: 신호는 오늘, 체결은 내일

5일선20일선
오늘—
오늘 종가로 낸 신호—
지금 비중—
자산(1,000만원 시작)—
해볼 것: ① 5일선이 20일선을 뚫고 올라가는 날(● 신호)을 찾고, 실제 매수(▲)가 하루 뒤에 찍히는지 본다. ② 급락 구간에서 하루 늦은 체결 때문에 얼마나 더 잃는지 본다. ③ 신호와 체결 사이의 하루를 없애면 어떻게 될지 예상해 본다. 다음 절의 주제다. (SB 종합지수 일봉, 5일·20일 이동평균 교차)

신호(●)와 체결(▲·▼) 사이에는 늘 하루가 있다. 급락이 시작된 날 신호가 나와도 실제로 파는 것은 다음 날이라서, 그 하루치 하락은 고스란히 맞는다. 이 하루가 귀찮다고 지워 버리면 결과가 좋아진다. 그리고 그것이 가장 흔한 실수다.

좋은 백테스트의 조건

함정을 하나씩 보기 전에, 믿을 만한 백테스트가 갖춰야 할 것을 먼저 적어 둔다. 광고나 보고서에서 백테스트를 볼 때 이 목록으로 하나씩 물어보면 된다. 이 장의 나머지는 각 줄을 어겼을 때 무슨 일이 생기는지 보여 주는 실험이다.

그날 알 수 있던 정보만신호는 그 시점에 실제로 공개된 데이터로만 계산했는가. 체결은 신호 다음이었는가.
그날 있던 종목 전부지금은 사라진 상장폐지 종목까지 포함한 데이터인가.
현실의 비용수수료, 거래세, 호가 차이, 내 주문이 가격을 미는 효과까지 넣었는가. 그 양을 실제로 살 수 있었는가.
여러 국면상승장만이 아니라 급락·약세·횡보가 섞인 충분히 긴 기간인가.
적은 손잡이맞춘 파라미터와 조건이 적은가. 이웃한 값에서도 비슷한 결과가 나오는가.
시험한 횟수의 공개이 결과가 몇 번째 시도에서 나온 것인가. 표본 밖에서 다시 확인했는가.

미래 참조: 그날 몰랐던 것을 쓰기

미래 참조 편향(Look-ahead bias)은 백테스트 속의 내가 그 시점에는 알 수 없었던 정보를 쓰는 것이다. 대놓고 미래 가격을 보는 사람은 없다. 미래 참조는 거의 언제나 날짜가 하루, 몇 주 어긋나는 실수로 숨어 들어온다.

① 실적 데이터 3/31 분기 끝 5/15 무렵 실적 공시 이 6주 동안 쓰면 미래 참조 여기부터 사용 가능 ② 종가 신호 i일 15:30 종가 확정·신호 i+1일 실제 체결 같은 종가에 체결(불가능)
그림 17-2. 정보가 생긴 날과 쓸 수 있는 날. 데이터에 찍힌 날짜는 그 정보를 알게 된 날이 아니다. 백테스트는 "그날 누가 이것을 알 수 있었나"를 기준으로 날짜를 다시 맞춰야 한다. (공시 기한은 2026년 기준 대표값이며 회사·보고서 종류에 따라 다르다)

미래 참조가 결과를 얼마나 바꾸는지 직접 켜 보자. 규칙 세 가지에 세 단계의 "엿보기"를 붙였다. 정상은 앞 시뮬레이터처럼 신호 다음 날 체결한다. 종가 체결은 신호를 낸 그 종가에 샀다고 기록한다. 내일 종가 섞임은 신호를 계산할 때 내일 종가가 실수로 하나 섞여 들어간 경우다. 데이터 배열에서 인덱스 하나가 밀리면 실제로 이렇게 된다.

SIMULATOR

미래 참조 스위치: 하루를 엿보면 생기는 일

규칙
엿보기
연평균 수익—
정상일 때—
샤프 비율—
최대 낙폭—
해볼 것: ① 이평 20·60에서 "종가 체결"만 켜도 연 수익이 1.7%p쯤 오른다. ② "20일 신고가"에 "내일 종가 섞임"을 켜면 손실 나던 규칙이 연 19%짜리 전략으로 바뀐다. ③ "오른 날 사기"에 내일 종가를 섞으면 곡선이 세로축을 뚫고 나간다. 이렇게 비현실적인 곡선은 버그의 신호다. (세로축은 로그 눈금, 편도 비용 약 0.115%)

마지막 경우는 우스워 보이지만 실제로 흔하다. 내일 종가가 섞인 규칙은 "내일 오를 날만 골라 들고 있는" 규칙이 되므로 비용을 내고도 곡선이 하늘로 솟는다. 반대로 미래 참조가 조금만 섞이면 곡선은 "조금 더 좋은" 정도라서 눈치채기 어렵다. 20일 신고가 규칙이 정확히 그렇다. 정상일 때는 연 −0.7%로 쓸모없던 규칙이, 하루치 엿보기로 연 약 19%, 최대 낙폭 −9%의 꿈같은 전략이 된다. 결과가 너무 좋으면 먼저 날짜부터 의심한다.

생존 편향: 사라진 종목이 빠진 데이터

오늘 증권사 앱에서 내려받을 수 있는 종목 목록은 "오늘까지 살아남은" 종목들이다. 10년 사이 상장폐지된 회사는 목록에 없다. 이 목록으로 10년 전부터 백테스트를 하면, 10년 전의 나는 어느 회사가 망할지 미리 알고 그 회사들만 피해 간 셈이 된다. 이것이 생존 편향(Survivorship bias)이다. 생존 편향은 미래 참조의 한 종류이기도 하다. "앞으로 살아남을 것"이라는 미래 정보를 쓴 것이기 때문이다.

아래는 이 책의 가상 유니버스(월간 수익률 10년, 가상의 300종목)다. 그중 일부는 주가가 무너지거나 부실해져 중간에 상장폐지된다. 매달 모든 종목을 같은 비중으로 사는 단순한 전략을, 상장폐지 종목까지 포함한 전체 데이터와 오늘 살아남은 종목만 있는 데이터로 각각 돌려 보자. 차트 위를 끌면 그 달까지 사라진 종목 수가 보인다.

SIMULATOR

생존 편향: 살아남은 종목만으로 돌린 백테스트

차트를 끌어 달을 고른다
종목 범위
살아남은 종목만상장폐지 포함 전체
살아남은 종목만(연)—
전체(연)—
부풀려진 몫—
고른 달까지 상장폐지—
해볼 것: ① 두 곡선이 처음에는 붙어 있다가 상장폐지가 하나둘 생길 때마다 벌어지는 것을 본다. ② 소형주만으로 바꾸면 차이가 더 커진다. 사라지는 회사는 대개 작은 회사다. ③ 소형주 전략을 백테스트한 결과라면 이 차이가 고스란히 "전략의 실력"처럼 보인다는 점을 생각해 본다. (상장폐지되는 달의 수익률은 −90%로 처리, 동일가중 매달 재조정, 비용 없음)

전체 300종목으로는 해마다 약 1.2%p, 소형주만 보면 약 1.6%p 차이가 난다. 1년에 1~2%p는 작아 보이지만 10년이면 누적으로 수십 %p다. 게다가 생존 편향은 방향이 늘 한쪽이다. 망한 회사를 빼면 성과는 좋아지기만 한다. 소형주, 저PBR주, 적자 기업처럼 상장폐지가 잦은 곳을 다루는 전략일수록 이 편향이 크다. 상장폐지 종목을 포함한 데이터를 생존 편향 없는 데이터(Survivorship-bias-free)라고 부르고, 믿을 만한 연구는 이것을 쓴다.

지수도 생존자다 SB 종합지수 같은 시장 지수는 구성 종목이 바뀌어도 그날그날의 실제 종목으로 계산되므로 생존 편향이 적다. 그러나 "지금 지수에 들어 있는 종목들로 10년 전부터 지수를 다시 만들어" 백테스트하면 생존 편향이 들어간다. 지금 지수에 있는 종목은 대개 지난 10년 동안 잘 커서 들어온 종목이기 때문이다.

비용, 슬리피지, 체결 가능성

백테스트 속의 매매는 공짜이고, 원하는 가격에, 원하는 양만큼 언제나 체결된다. 현실은 셋 다 아니다. 3장에서 본 것처럼 한 번 사고팔 때마다 수수료(약 0.015%씩)와 매도 때 증권거래세(2026년 기준 0.20%)가 나가고, 시장가 주문은 호가 차이(스프레드)만큼 불리하게 체결된다. 주문이 크면 호가를 여러 칸 먹으면서 가격을 밀어 올린다. 생각한 가격과 실제 체결 가격의 차이를 슬리피지(Slippage)라고 한다.

비용의 무게는 매매 횟수가 정한다. 1년에 한두 번 사고파는 규칙에는 0.3%의 비용이 별일 아니지만, 1년에 30번 사고파는 규칙에는 해마다 몇 %p가 사라진다. 아래에서 규칙의 빠르기를 고르고 비용과 슬리피지를 올려 보자.

SIMULATOR

비용과 슬리피지: 자주 사고팔수록 녹는 곡선

규칙의 빠르기
1년 매매 횟수—
비용 0일 때(연)—
비용 반영(연)—
해마다 사라진 몫—
해볼 것: ① 빠른 규칙에서 비용 두 개를 0으로 내리면 연 수익이 어떻게 되는지 본다. 광고 속 곡선은 대개 이 상태다. ② 슬리피지만 0.3%로 올리면 빠른 규칙은 손실 전략이 된다. ③ 느린 규칙은 같은 비용에도 거의 흔들리지 않는다. (편도 비용 = 사거나 팔 때마다 거래 금액에서 빠지는 비율. 수수료 0.015%와 매도 거래세 0.20%를 편도로 나누면 약 0.115%)

빠른 규칙은 1년에 열 번 넘게 사고판다(매수와 매도를 각각 한 번으로 센다). 편도 비용 0.215%(수수료·세금 0.115% + 슬리피지 0.1%)라면 그것만으로 해마다 3%p 넘게 빠진다. 많은 단기 전략의 "초과수익"은 정확히 이 정도 크기라서, 비용을 넣는 순간 사라진다.

그 양을 실제로 살 수 있었나

슬리피지는 주문 크기에 따라 달라진다. 백테스트가 "소형주 하나에 1억원어치를 종가에 샀다"고 적어도, 실제 호가창에 1억원어치 매도 물량이 없으면 그 가격에 살 수 없다. 이것이 체결 가능성, 다른 말로 유동성(Liquidity) 문제다. 아래 호가창의 매도 쪽(파랑)에 시장가 매수 주문을 넣는다고 생각하고, 차트를 좌우로 끌어 주문 금액을 바꿔 보자.

SIMULATOR

주문이 가격을 민다: 주문 금액과 평균 체결가

좌우로 끌어 주문 금액을 바꾼다
종목
주문 금액—
평균 체결가—
슬리피지(중간값 대비)—
호가에 없어 못 산 금액—
해볼 것: ① 대형주에 3억원을 넣어도 미끄러짐이 작다. ② 소형주로 바꾸면 3,000만원만 넣어도 호가 여러 칸을 먹는다. ③ 3억원이면 보이는 호가를 다 먹고도 못 산 금액이 남는다. 백테스트는 이 주문을 종가에 전부 샀다고 기록한다. (엔진의 호가창 ST.Book으로 만든 가상 호가 20단계, 시장가 매수만 계산)

운용 금액이 작은 개인에게 유동성은 대형주에서는 큰 문제가 아니다. 그러나 백테스트가 고른 종목이 거래가 적은 소형주라면 이야기가 다르다. 소형주 전략의 백테스트 수익이 유난히 좋다면, 그 수익의 상당 부분은 "실제로는 그 가격에 살 수 없었던" 데서 나왔을 수 있다. 이 장 끝의 광고 해부에서 소형주 전략에 편도 0.4%의 슬리피지를 붙이는 이유다.

표본 기간과 국면: 언제를 돌렸나

시장은 늘 같은 성격이 아니다. 이 책의 가상 시장 10년에도 완만한 상승, 조정, 강세장, 40일 만의 −34% 급락, 급반등, 약세장, 횡보가 차례로 들어 있다. 이런 시장의 성격이 바뀌는 것을 국면 변화(Regime change)라고 한다. 추세를 따라가는 규칙은 길게 오르거나 길게 내리는 국면에서 빛나고, 위아래로 흔들리는 국면에서 사고팔기만 반복하며 돈을 잃는다. 아래에서 규칙을 바꿔 가며 국면마다 전략과 보유를 비교해 보자.

SIMULATOR

국면별 성과: 전략 vs 그냥 보유

규칙
전략보유
보유보다 나았던 국면—
가장 크게 이긴 국면—
가장 크게 진 국면—
해볼 것: ① 급락과 약세장에서 전략이 손실을 줄이는지 본다. ② 횡보 구간에서는 어떤지 본다. ③ 급반등에서 전략이 얼마나 뒤처지는지 본다. 추세 규칙은 바닥에서 늦게 올라탄다. (각 국면 처음부터 끝까지의 구간 수익률, 비용 포함)

추세 규칙의 성적표는 "어떤 국면이 몇 번 들어 있었나"에 크게 달려 있다. 급락이 한 번 있었던 10년이면 낙폭을 피한 덕에 영웅이 되고, 같은 규칙도 횡보장 5년만 돌리면 비용만 내는 바보가 된다. 그러니 백테스트 기간을 고르는 일 자체가 결과를 고르는 일이 될 수 있다. 직접 해 보자. 아래 차트의 두 손잡이를 끌어 백테스트할 기간을 고른다.

SIMULATOR

기간 고르기: 손잡이 두 개로 결론 뒤집기

시작·끝 손잡이를 끈다
이평 20·60 전략보유
기간—
전략(연)—
보유(연)—
전략 − 보유—
해볼 것: ① 급락이 들어간 구간을 고르면 전략이 크게 이긴다. ② 급락 뒤 꾸준히 오르기만 한 구간을 고르면 전략이 크게 진다. ③ 두 버튼은 2년 이상인 모든 기간 중 차이가 가장 큰 것을 찾는다. 같은 규칙, 같은 데이터로 "연 몇 %p 이긴다"와 "연 몇 %p 진다"를 둘 다 말할 수 있다. (기간은 최소 2년)

광고 속 백테스트의 시작일이 이상하게 특정한 날짜라면, 그 날짜가 왜 골라졌는지 물어볼 만하다. 정직한 백테스트는 데이터가 있는 가장 긴 기간을 쓰고, 여러 국면에서 따로 성적을 보여 준다.

과최적화: 과거에 꼭 맞는 옷

첫 시뮬레이터에서 단기·장기 이동평균 기간을 바꿔 보았다. 그 두 숫자를 파라미터(Parameter)라고 한다. 파라미터를 바꿔 가며 가장 좋은 조합을 찾는 것을 최적화라고 하는데, 너무 열심히 하면 규칙이 시장의 원리가 아니라 그 기간의 우연한 소음에 맞춰진다. 이것이 과최적화(Overfitting)다. 과거의 몸에 꼭 맞춘 옷은 미래의 몸에 맞지 않는다.

확인하는 방법은 간단하다. 데이터를 둘로 나눠 앞부분(훈련 구간, In-sample)에서만 최적화하고, 손대지 않은 뒷부분(검증 구간, Out-of-sample)에서 그 파라미터를 시험한다. 아래 격자는 단기 8가지 × 장기 10가지 조합을 모두 돌린 결과다. 칸의 색은 샤프 비율(빨강일수록 좋고, 파랑이면 손실)이다. 칸을 눌러 그 조합의 훈련·검증 성과를 보자.

LAB

파라미터 격자: 훈련의 봉우리는 검증에서 어떻게 되나

칸을 눌러 조합을 고른다
칸 색의 기준
고른 조합—
훈련 샤프(순위)—
검증 샤프(순위)—
이웃 평균(훈련)—
해볼 것: ① "훈련 1등 고르기"를 누르고 검증 순위를 본다. ② 색 기준을 "검증 샤프"로 바꾸면 훈련 때의 빨간 봉우리가 어디로 갔는지 보인다. ③ "이웃 평균"은 각 칸을 주변 칸과 평균 낸 값이다. 홀로 솟은 봉우리는 낮아지고, 넓게 좋은 고원은 그대로 남는다. (SB 종합지수, 훈련 2017~2020년, 검증 2021~2025년, 비용 포함)

훈련 구간에서 가장 좋았던 조합이 검증 구간에서도 1등일 가능성은 낮다. 훈련 성과에는 진짜 원리와 우연이 섞여 있고, 1등은 대개 우연을 가장 많이 받은 조합이기 때문이다. 그래서 1등 칸 하나보다 넓게 좋은 지역을 본다. 주변 값을 조금 바꿔도 성과가 비슷한 고원(Plateau)은 규칙이 실제로 무언가를 잡고 있다는 신호이고, 한 칸만 솟은 봉우리(Peak)는 소음일 가능성이 크다.

이 가상 시장에서는 훈련 1등(15일·30일)이 훈련 샤프 1.09로 70개 중 1위였다가 검증에서 −0.23, 65위로 떨어진다. 고원 가운데(15일·40일)도 검증 샤프는 0 근처다. 고원은 필요조건이지 충분조건이 아니다. 훈련 구간 전체가 우연히 이동평균 규칙에 유리했다면 고원째로 무너진다. 그래서 다음 절의 표본 밖 검증이 따로 필요하다.

조건을 하나씩 붙이면

파라미터만이 손잡이가 아니다. "월요일에는 쉰다", "9월에는 안 산다" 같은 조건도 하나하나가 손잡이다. 아래에서는 지수를 그냥 들고 있는 전략에서 출발해, 훈련 구간의 샤프 비율을 가장 많이 올려 주는 조건을 하나씩 붙인다. 후보는 요일 다섯 개, 달 열두 개, 전날 오르거나 내린 날, 월초·월말 같은 21가지다. 가상 시장에는 요일이나 달에 따른 규칙성이 전혀 없도록 만들었다. 그러니 어떤 조건도 진짜일 수 없다.

LAB

조건 덧붙이기: 훈련 샤프는 오르고, 검증 샤프는

훈련 샤프검증 샤프
붙인 조건—
훈련 샤프—
검증 샤프—
방금 붙인 조건—
해볼 것: ① 조건을 하나씩 붙이며 훈련 샤프가 계단처럼 오르는 것을 본다. ② 검증 샤프가 따라 오르는지 본다. ③ 조건의 이름을 읽어 본다. 하나하나는 그럴듯한 "계절성"처럼 들린다. (훈련 2016~2020년, 검증 2021~2025년, 쉬는 날은 현금, 비용 제외, 훈련 샤프를 더 올리는 조건이 없으면 멈춘다)

조건 네 개(7월·목요일·1월·11월 쉬기)를 붙이자 훈련 샤프는 0.55에서 1.61로 세 배가 되었다. 그럴 수밖에 없다. 매번 훈련 구간에서 가장 좋은 조건을 골랐으니까. 그러나 검증 샤프는 0.24에서 오르락내리락하다 0.10으로 끝난다. 처음 그냥 들고 있던 것보다 못하다. 조건의 수가 늘수록 규칙은 훈련 구간의 우연한 무늬를 외운다. 손잡이가 많은 전략일수록 백테스트 성과를 깎아서 읽어야 한다.

데이터 스누핑: 많이 시험하면 하나는 맞는다

과최적화가 한 규칙의 손잡이를 너무 많이 돌리는 것이라면, 데이터 스누핑(Data snooping)은 너무 많은 규칙을 시험하는 것이다. 동전 1,000개를 열 번씩 던지면 열 번 모두 앞면이 나오는 동전이 평균 한 개쯤 나온다. 그 동전이 특별한 것은 아니다. 1,000번 시험했기 때문에 나온 것이다. 통계에서는 이것을 다중 검정(Multiple testing) 문제라고 부른다.

아래에서 완전히 무작위인 전략 1,000개를 만든다. 각 전략은 매달 동전을 던져 지수를 들고 있을지 현금으로 둘지 정한다. 어떤 전략에도 실력은 없다. 그래도 1,000개를 시험하면 그중 최고는 꽤 멋져 보인다. 그 최고 전략을 다음 기간에 돌리면 어떻게 될까.

LAB

무작위 전략 1,000개: 운의 최대값

훈련 기간 샤프같은 전략의 검증 기간 샤프
시험한 전략—
최고 훈련 샤프—
운만으로 기대되는 최고—
그 전략의 검증 샤프—
해볼 것: ① 시험이 쌓이면서 최고 기록(▼)이 오른쪽으로 밀려 가는 것을 본다. 시험이 많을수록 최고는 높아진다. ② 아래 분포에서 그 최고 전략(◆)이 어디에 떨어지는지 본다. ③ "다시 뽑기"를 여러 번 눌러 최고 전략의 검증 샤프가 평균 근처로 돌아가는지 확인한다. (훈련 약 5년, 검증 그 뒤 약 5년, 한 달 단위로 보유·현금을 무작위로 정함)

전략 하나하나의 샤프 비율은 운에 따라 평균 주위로 흩어진다. 그 흩어짐의 크기를 \(\sigma\)라고 하면, \(N\)개를 시험했을 때 운만으로 나오는 최고값은 대략 이렇다.

$$\text{최고값} \approx \text{평균} + \sigma\sqrt{2\ln N}$$
N = 10이면 평균 + 약 2.1σ, N = 1,000이면 평균 + 약 3.7σ. 이 식은 대략적인 위쪽 어림이고 실제 기대값은 조금 낮다(1,000개면 약 3.2σ). 시뮬레이터의 점선은 디플레이티드 샤프에서 쓰는 더 정확한 근사식으로 그렸다. 시험 횟수가 100배가 되어도 최고값은 크게 오르지 않지만, 늘 평균보다는 한참 높다.

최고 전략의 검증 성과는 평균 근처로 돌아간다. 처음부터 실력이 아니라 운이 만든 1등이었기 때문이다. 이것을 거꾸로 보면 중요한 질문이 생긴다. 어떤 백테스트 결과를 볼 때 "이것이 몇 번째 시도인가"를 모르면, 그 결과가 얼마나 대단한지 판단할 수 없다. 광고는 1,000개 중 1등만 보여 주고 나머지 999개는 말하지 않는다.

눈으로 가려낼 수 있을까

반대 방향도 시험해 보자. 아래 여덟 개의 자산 곡선 중 하나만 진짜 실력(샤프 0.5)이 있는 전략이고, 나머지 일곱은 실력이 0인 전략이다. 변동성은 모두 연 15%로 같다. 진짜를 골라 보자. 기간을 바꾸면서 몇 판씩 해 보면 감이 온다.

GAME

진짜 실력 찾기: 여덟 곡선 중 하나

진짜라고 생각하는 곡선을 누른다
데이터 기간
판—
맞힌 판—
적중률(찍기 12.5%)—
"가장 좋아 보이는 곡선"이 진짜인 비율—
해볼 것: ① 10년으로 몇 판 해 본다. 가장 높이 올라간 곡선을 고르는 전략이 얼마나 자주 맞는지 오른쪽 숫자로 본다. ② 3년으로 바꾸면 거의 찍기다. ③ 40년이면 비로소 진짜가 자주 보인다. (월간 수익률, 진짜 전략은 연 기대 초과수익 7.5%·변동성 15%, 나머지는 기대 초과수익 0)

"가장 높이 오른 곡선을 고른다"는 방법이 맞는 비율은 3년이면 약 34%, 10년이면 약 57%, 40년이면 약 94%다. 후보가 여덟 개만 되어도 10년 데이터로는 두 번에 한 번꼴로 운 좋은 가짜를 고른다. 후보가 1,000개라면 진짜는 운의 최대값 속에 묻혀 거의 보이지 않는다.

통계적 유의성: 샤프 0.5는 몇 년이면 보이나

마지막 게임이 어려웠던 이유는 숫자로 설명할 수 있다. 관측한 샤프 비율은 진짜 샤프 비율의 추정값이고, 추정값에는 오차가 있다. 연 단위 샤프 비율 SR을 T년 데이터로 잴 때, 그 오차(표준오차)는 대략 다음과 같다.

$$\text{SE}(\widehat{SR}) \approx \sqrt{\frac{1 + SR^2/2}{T}}$$
T는 햇수. 수익률이 정규분포에 가깝고 서로 독립이라는 가정의 근사식이다. 꼬리가 두껍거나 수익률이 이어지는 성질이 있으면 오차는 더 커진다.

진짜 샤프가 0.5인 전략을 10년 동안 재면 표준오차는 약 \(\sqrt{1.125/10} \approx 0.34\)다. 관측값은 대략 0.5 ± 0.67(±2 표준오차), 즉 −0.2에서 1.2 사이 어디든 나올 수 있다. 실력이 전혀 없는 전략(진짜 샤프 0)도 10년이면 관측 샤프가 0.5 이상 나올 확률이 약 6%다. 위의 무작위 전략 1,000개라면 그런 것이 수십 개다. 아래에서 진짜 샤프와 데이터 길이를 바꿔 보자.

SIMULATOR

샤프 비율의 불확실성: 진짜 값과 관측값

표준오차—
관측값 95% 범위—
관측 샤프가 0 이하일 확률—
t값 2에 필요한 햇수—
해볼 것: ① 진짜 0.5, 10년에서 점(같은 전략을 200번 다른 운으로 잰 관측값)이 얼마나 넓게 퍼지는지 본다. 일부는 0 아래다. ② 기간을 40년으로 늘리면 분포가 좁아진다. ③ 진짜 샤프를 1.0으로 올리면 몇 년이면 0과 구분되는지 본다. (월간 수익률을 정규분포에서 뽑아 잰 관측 샤프, 곡선은 위 근사식)

진짜 샤프 0.5짜리 전략이 "운이 아니다"라고 말하려면(관측값이 표준오차의 두 배를 넘으려면) 대략 \(4(1+SR^2/2)/SR^2 = 4 imes 1.125 / 0.25 = 18\)년이 필요하다. 지수 자체의 샤프 비율이 0.3~0.5 언저리라는 것을 생각하면, 지수를 이긴다는 전략의 초과 성과는 이보다 훨씬 작아서 수십 년 데이터로도 증명하기 어렵다. 10년 백테스트 하나로 "이 전략은 검증되었다"고 말하는 것은 대개 지나친 말이다.

시험한 횟수까지 따지는 샤프: 디플레이티드 샤프 데이터 스누핑과 표준오차를 합치면 이런 질문이 된다. "N개를 시험해서 고른 최고 전략의 관측 샤프가 운만으로 나올 수 있는 최고값보다 의미 있게 높은가?" 이 생각을 식으로 만든 것이 디플레이티드 샤프 비율(Deflated Sharpe Ratio)이다. 기준선을 0이 아니라 "N개 중 최고가 운으로 나올 기대값(앞 절의 식)"으로 올리고, 데이터 길이와 수익률 분포의 꼬리까지 반영해 그 기준을 넘을 확률을 계산한다. 같은 관측 샤프 1.0이라도 한 번 시험해서 나온 것과 1,000번 시험해서 고른 것은 전혀 다른 증거다.

대책: 백테스트를 의심하는 방법

함정을 다 피하는 백테스트는 없다. 다만 함정에 덜 빠지는 습관은 있다. 가장 중요한 것은 결과를 보기 전에 규칙을 정하고, 손대지 않은 데이터에서 다시 확인하는 것이다.

① 한 번 나누기(표본 밖 검증) 훈련: 여기서만 고른다 검증: 한 번만 본다 ② 워크포워드(창을 밀며 반복) 훈련 검증 검증 조각을 이은 표본 밖 성적
그림 17-3. 훈련·검증 분리와 워크포워드. ①은 데이터를 한 번 나눠 뒷부분을 한 번만 본다. ②는 그 시점까지의 데이터로 고르고 다음 조각에 적용하는 일을 창을 밀며 반복한다. 매 순간 "그때 알 수 있던 것"만으로 고르므로 실제로 운용했을 때와 가장 비슷하다.

훈련과 검증을 어디서 나누나

나누는 위치도 결과를 바꾼다. 아래 차트의 세로선을 끌어 훈련·검증의 경계를 옮겨 보자. 그때마다 훈련 구간에서 1등인 조합을 다시 찾고, 아래쪽 점 그림에 모든 조합의 훈련 샤프(가로)와 검증 샤프(세로)를 찍는다. 점들이 오른쪽 위로 비스듬히 늘어서면 훈련 성적이 검증 성적을 예측한다는 뜻이고, 둥글게 흩어지면 예측하지 못한다는 뜻이다.

LAB

훈련·검증 경계 끌기

세로선을 좌우로 끈다
훈련 1등 조합—
훈련 샤프—
검증 샤프(순위)—
훈련·검증 샤프 상관—
해볼 것: ① 경계를 급락 직후(2019년 말쯤)에 두면 훈련 1등이 검증에서 몇 위가 되는지 본다. ② 경계를 약세장 직전으로 옮기면 1등 조합이 바뀌는지 본다. ③ 상관이 음수인 경계도 있다. 훈련에서 좋았던 조합일수록 검증에서 나빴다는 뜻이다. (이동평균 70개 조합, 비용 포함, 훈련은 2017년부터)

경계를 조금만 옮겨도 1등 조합이 바뀌고, 1등의 검증 순위는 위아래로 크게 흔들린다. 검증 구간도 결국 한 번의 표본이라는 뜻이다. 그래서 검증 구간을 여러 번 들여다보며 규칙을 고치면, 검증 구간마저 훈련 구간이 되어 버린다. 검증 데이터는 마지막에 한 번만 본다.

워크포워드: 실제로 운용했다면

한 번 나누기보다 현실에 가까운 방법이 워크포워드(Walk-forward) 분석이다. 그 시점까지의 데이터(훈련 창)로 1등 조합을 고르고, 다음 반년 동안 그 조합으로 운용한다. 반년이 지나면 창을 반년 밀어서 다시 고른다. 이렇게 이은 성적은 "그때그때 최선을 다해 최적화했다면 실제로 받았을 성적"이다. 재생을 눌러 창이 미끄러지는 것을 보자.

SIMULATOR

워크포워드: 창을 밀며 다시 고르기

워크포워드사후 1등(전체 기간)보유
다시 고른 횟수—
지금 쓰는 조합—
워크포워드(연)—
사후 1등(연) / 보유(연)—
해볼 것: ① 재생하며 고르는 조합이 창마다 바뀌는 것을 본다. 안정적인 규칙이라면 비슷한 조합이 계속 뽑혀야 한다. ② 끝까지 돌린 뒤 워크포워드 곡선을 "사후 1등"과 비교한다. 그 차이가 과최적화의 크기다. ③ 훈련 창 길이를 바꿔도 결론이 같은지 본다. (반년마다 재선택, 조합을 바꿀 때의 추가 비용은 무시)

사후 1등 곡선은 같은 기간을 다 보고 고른 조합이다. 광고에 나오는 곡선은 대개 이것이다. 훈련 창 3년에서 사후 1등은 연 약 12.2%, 보유는 약 9.2%인데 워크포워드는 약 3.8%다. 둘 사이의 간격이 "과거를 알고 고른 덕"이다. 창 길이를 바꾸면 더 놀랍다. 1년이면 약 7.7%, 2년이면 약 10.0%, 4년이면 약 0.4%다. 훈련 창 길이라는 손잡이 하나에 결과가 이만큼 흔들린다면, 그 규칙에는 믿고 기댈 만한 무엇이 없다는 뜻이다.

의심하는 습관 다섯 가지

  1. 먼저 정하고, 나중에 본다. 규칙과 평가 기준을 적어 둔 뒤 돌린다. 결과를 보고 규칙을 고칠 때마다 검증 구간은 조금씩 훈련 구간이 된다.
  2. 표본 밖에서, 한 번만. 훈련·검증을 나누고, 가능하면 워크포워드로 실제 운용을 흉내 낸다.
  3. 봉우리보다 고원. 이웃 파라미터에서도 성과가 비슷한지 본다. 한 칸만 좋은 규칙은 버린다.
  4. 단순한 규칙. 손잡이가 적을수록 우연에 맞출 여지가 적다. 조건 하나를 더할 때마다 "왜 그래야 하는가"에 대한 경제적 이유가 있어야 한다.
  5. 시험한 횟수를 센다. 시험을 많이 했다면 기준을 올린다. 관측 샤프의 표준오차와 "N개 중 최고"의 기대값을 같이 본다.

"연 40% 전략" 해부

이제 처음의 광고로 돌아가자. 한결이 본 광고는 이랬다.

"소형주 모멘텀 전략, 7년 백테스트 연평균 +40% 내외. 최근 몇 달 많이 오른 소형주 다섯 종목을 매달 바꿔 담기만 하면 된다." (이 책이 만든 가상의 광고다. 아래 숫자는 모두 가상 유니버스로 계산했다.)

규칙 자체는 단순하다. 매달 말, 소형주 가운데 지난 L개월 동안 가장 많이 오른 k종목을 같은 비중으로 사서 한 달 들고 있는다. 16장의 모멘텀이다. 광고를 만든 사람은 L과 k를 여러 가지로 돌려 가장 좋은 것을 골랐고, 오늘 살아 있는 종목 데이터만 썼고, 순위를 매긴 데이터에 다음 달 첫날 종가가 섞여 있었고, 비용은 넣지 않았다. 아래에서 함정을 하나씩 걷어 내 보자.

LAB

광고 해부: 함정을 하나씩 걷어 내는 폭포

남은 연 수익걷어 낸 몫시장 동일가중
지금 단계—
연평균 수익—
이번에 걷어 낸 몫—
시장 동일가중(연)—
해볼 것: ① 버튼을 한 번씩 누르며 어느 함정이 가장 큰 몫을 차지했는지 본다. ② 아래 자산 곡선이 광고의 곡선에서 어떻게 주저앉는지 본다. ③ 마지막 단계의 숫자를 시장 동일가중과 비교한다. (가상 유니버스 소형주, 평가 기간 7년, 비용은 왕복 0.23% + 편도 슬리피지 0.4%, 과최적화 제거는 해마다 그때까지의 데이터로 L·k를 다시 고르는 워크포워드)

남는 것은 광고의 숫자와 거리가 멀다. 연 약 40%가 미래 참조를 빼자 30.5%, 상장폐지 종목을 넣자 29.8%, 비용과 슬리피지를 넣자 20.9%, L·k를 그때그때 고르게 하자 11.6%가 된다. 미래 참조(하루치였을 뿐인데 연 9%p 넘게), 비용(소형주를 매달 갈아타는 전략은 비용에 가장 약하다), 과최적화가 거의 같은 몫씩 나눠 가졌다. 생존 편향은 이 기간에는 1%p도 되지 않았지만, 기간과 종목에 따라 훨씬 커질 수 있다. 마지막 숫자는 시장 동일가중(약 10.1%)과 비슷하다. 이 가상 유니버스에는 모멘텀이 실제로 조금 있도록 만들었다. 그런데도 남은 초과수익은 앞 절에서 본 표준오차 안에 쉽게 숨는 크기다.

숫자는 바뀐다 이 장의 거래세(0.20%), 수수료(약 0.015%), 공시 기한(분기 말 후 45일)은 2026년 기준 대표값이다. 제도와 증권사 수수료는 바뀌므로 실제로 계산할 때는 그때의 값을 확인한다. 이 장의 시장과 종목은 모두 교육용 가상 데이터이고, 과거의 수익은 앞으로의 수익을 보장하지 않는다. 어떤 전략도 권하지 않는다.
NOTE 한결한결의 투자 노트 · 17장

"연 40%" 광고를 해부하다

위성(satellite) 몫으로 무엇을 살지 고민하던 한결에게 "소형주 모멘텀, 백테스트 연 40%" 광고가 떴다. 12장의 골든크로스 때와 달리 이번에는 그래프가 너무 매끈했다. 한결은 이 장의 체크리스트를 들고 광고의 백테스트를 가상 유니버스에서 다시 돌렸다.

광고 그대로면 연 약 40%. 순위 데이터에 섞인 하루치 미래를 빼자 30.5%, 상장폐지 종목을 넣자 29.8%, 비용과 슬리피지를 넣자 20.9%, 마지막으로 L·k를 그때그때 고르게 하자(과최적화 제거) 11.6%가 남았다. 같은 기간 시장 동일가중은 약 10.1%. 남은 1.5%p의 차이는 10년 데이터로는 운과 가려내기 어려운 크기였다. 표본 밖에서 무너진 것은 전략이 아니라 광고였다.

이 장에서 정한 것백테스트 숫자를 볼 때 미래 참조·생존 편향·비용·시험 횟수·표본 밖 성과를 먼저 묻는다. 확인할 수 없으면 믿지 않는다.
아직 남은 문제그렇다면 1,000만원과 매달 70만원을 실제로 언제, 얼마씩, 어떤 규칙으로 넣을 것인가.
다음 단계18장에서 분할 매수, 적립, 위성 비중, 리밸런싱 규칙을 정한다.

핵심 정리

  1. 백테스트는 규칙을 과거 데이터에 하루씩 돌려 자산 곡선을 만드는 일이다. 정직한 엔진은 i일 종가까지의 정보로 신호를 내고 i+1일에 체결하며, 비용을 뺀다.
  2. 미래 참조는 날짜가 어긋나는 실수로 숨어 든다(종가 보고 종가 체결, 공시 전 실적 사용). 하루만 엿봐도 쓸모없는 규칙이 꿈의 전략이 된다. 결과가 너무 좋으면 날짜부터 의심한다.
  3. 생존 편향은 상장폐지 종목이 빠진 데이터에서 생기며 늘 성과를 부풀린다. 소형주·부실주를 다루는 전략일수록 크다.
  4. 비용·슬리피지는 매매 횟수에 비례해 수익을 깎는다. 유동성이 적은 종목에서는 백테스트 가격에 그 양을 살 수 없다.
  5. 성과는 표본 기간과 국면에 크게 의존한다. 기간을 고르는 것만으로 결론을 뒤집을 수 있다.
  6. 파라미터와 조건을 많이 맞출수록 훈련 성과는 오르고 검증 성과는 나빠진다(과최적화). 많이 시험하면 운만으로도 멋진 결과가 나온다(데이터 스누핑).
  7. 샤프 비율의 표준오차는 약 √((1+SR²/2)/T)다. 진짜 샤프 0.5도 10년으로는 운과 구분하기 어렵고, 0과 구분하려면 약 18년이 필요하다.
  8. 대책: 결과 전에 규칙을 정하고, 표본 밖·워크포워드로 확인하고, 봉우리보다 고원을 고르고, 단순한 규칙을 쓰고, 시험 횟수만큼 기준을 올린다(디플레이티드 샤프).

확인 퀴즈

1. 어떤 백테스트가 "오늘 종가가 20일 이동평균을 넘으면 오늘 종가에 산다"고 계산했다. 무엇이 문제인가?

종가는 장이 끝나야 확정되므로, 그 종가로 계산한 신호는 빨라야 다음 거래일에 체결할 수 있다. 같은 종가에 체결했다고 기록하면 실제로는 불가능한 거래가 되고 결과가 부풀려진다.

2. 지금 상장되어 있는 종목만으로 10년 전부터 소형주 전략을 백테스트했다. 결과는 실제보다 어떻게 나오기 쉬운가?

생존 편향이다. 중간에 망해 사라진 종목은 대개 큰 손실을 낸 종목이고, 이것이 빠지면 성과는 좋아지는 쪽으로만 바뀐다. 상장폐지가 잦은 소형주에서 특히 크다.

3. 파라미터 격자에서 훈련 구간 샤프가 가장 높은 칸 하나가 주변 칸들보다 홀로 높게 솟아 있다. 어떻게 해석하는 것이 가장 알맞은가?

훈련 1등은 대개 우연을 가장 많이 받은 조합이다. 파라미터를 조금 바꿔도 성과가 비슷한 고원은 규칙이 실제 원리를 잡고 있다는 신호이고, 홀로 솟은 봉우리는 표본 밖에서 무너지기 쉽다. 격자를 더 촘촘히 하는 것은 시험 횟수를 늘려 스누핑을 키운다.

4. 실력이 전혀 없는 무작위 전략 1,000개를 시험해 가장 좋은 것을 골랐다. 그 전략을 새 기간에 돌리면 어떻게 될 가능성이 가장 큰가?

최고 성과는 실력이 아니라 많이 시험한 데서 나온 운의 최대값이다. 운은 이어지지 않으므로 새 기간에는 평균 근처로 돌아간다. 반드시 손실이 나는 것도 아니다. 평균이 기준이다.

5. 진짜 샤프 비율이 0.5인 전략을 10년 데이터로 잴 때, 관측 샤프 비율의 표준오차로 가장 가까운 것은? (SE ≈ √((1+SR²/2)/T))

√((1 + 0.125)/10) = √0.1125 ≈ 0.34. 관측값의 95% 범위는 대략 0.5 ± 0.67로, 0 아래도 포함한다. 그래서 10년 백테스트 하나로는 샤프 0.5 전략을 운과 구분하기 어렵다.