백테스트는 돌리는 데 몇 초, 결과를 믿을 만하게 만드는 데 며칠이 걸립니다. 그 며칠은 대개 코드가 아니라 데이터에 들어갑니다. 같은 조건을 같은 엔진에 넣어도 어느 기간의 어떤 종목을 어느 시간봉으로 담았느냐에 따라 답이 갈리고, 그 차이가 조건을 바꿨을 때의 차이보다 큰 경우가 흔합니다.
이 글은 백테스트 코드를 짜는 법이 아니라 돌리기 전에 정해 두어야 하는 입력 규격을 다룹니다. 숫자는 바이낸스 USDⓈ-M 무기한 선물 354종목을 90일간 기록한 값을 씁니다. 2026년 8월 18일 11시 22분(KST)까지 32,232건입니다. 성과 수치는 여기 나오지 않습니다 — 이 사이트는 그것을 계산하지도 싣지도 않고, 이 글이 다루는 범위도 조건이 얼마나 자주 성립하는가까지입니다.
표본이 몇 건인지부터 셉니다 — 조건에 따라 열 배 차이가 납니다
백테스트 방법을 정할 때 첫 질문은 "어떤 조건을 걸까"가 아니라 "그 조건이 몇 번이나 성립했나"입니다. 같은 감시 목록과 같은 기간인데도 조건별 기록 수는 이만큼 벌어집니다.
| 조건 | 90일 기록 | 하루 평균 | 종목당 90일 |
|---|---|---|---|
| 5이평 다이버전스 | 20,985건 | 233건 | 59건 |
| 10이평 다이버전스 | 9,304건 | 103건 | 26건 |
| 삼박자 | 1,943건 | 22건 | 5.5건 |
세 조건의 성격이 다르니 수가 다른 것은 당연한데, 문제는 이 수를 다시 쪼갤 때 생깁니다. 삼박자 1,943건을 방향으로 나누면 매수 쪽 1,317건, 매도 쪽 626건입니다. 여기서 다시 시간봉으로 나누고 종목으로 나누면 한 칸에 남는 것은 두 자리 수가 됩니다. 90일 기준으로 가장 자주 나온 종목이 QNT 16건, 그다음이 더그래프(GRT)·코스모스(ATOM)·매직에덴(ME) 각 13건입니다.
백테스트 표를 종목별·시간봉별·방향별로 갈라 놓고 그중 제일 좋아 보이는 칸을 고르는 방식이 위험한 이유가 이것입니다. 칸을 나눌수록 한 칸의 표본은 줄고, 표본이 줄면 우연히 좋아 보이는 칸이 반드시 하나는 생깁니다. 칸을 나누기 전에 그 칸에 몇 건이 남는지를 먼저 계산하는 편이 낫습니다.
시간봉을 섞어 담으면 결과의 83%가 1시간봉 몫이 됩니다
시간봉을 지정하지 않고 기록을 전부 모으면 결과가 한쪽으로 쏠립니다. 같은 90일 기록을 시간봉으로 가른 값입니다.
| 시간봉 | 기록 | 비중 |
|---|---|---|
| 1시간봉 | 26,728건 | 82.9% |
| 4시간봉 | 5,504건 | 17.1% |
4.85배 차이입니다. 1시간봉은 하루 24번, 4시간봉은 6번 판정하니 산술적으로 나올 수밖에 없는 격차인데, 백테스트 결과표에는 이 사실이 안 적혀 있습니다. 시간봉을 섞어 돌린 결과는 사실상 1시간봉 결과이고, 4시간봉은 전체 평균을 6분의 1만큼만 흔듭니다.
이 사이트는 여섯 개 시간봉으로 계산하고 그중 두 개를 공개합니다. 백테스트를 여러 시간봉으로 돌릴 계획이라면 결과를 합치지 말고 시간봉별로 따로 두는 편이 읽기 쉽습니다. 시간봉이 무엇을 정하는지는 시간봉에, 각 봉이 한국 시간 몇 시에 닫히는지는 봉 마감 시간표에 있습니다.
진행 중인 봉을 넣으면 그 시점에 없던 정보를 쓰게 됩니다
백테스트 결과가 실제와 달라지는 원인 중 가장 흔한 것은 엔진도 조건도 아니고 봉 하나의 시점입니다.
차트에서 지금 그려지는 봉은 아직 닫히지 않았습니다. 고가와 저가가 계속 바뀌고, 그 봉으로 계산한 이동평균선과 지표값도 같이 바뀝니다. 그런데 백테스트 데이터를 내려받으면 모든 봉이 이미 닫힌 상태로 들어옵니다. 과거 어느 시점을 재현할 때 그 시점의 마지막 봉을 완성된 값으로 쓰면, 그 순간에는 알 수 없었던 종가를 미리 아는 셈이 됩니다.
이 사이트가 조건 성립을 봉이 닫힌 뒤에만 기록하는 이유가 여기 있습니다. 자세한 내용은 확정 시각에, 진행 중인 봉에서 신호가 나타났다 사라지는 현상은 리페인팅에 정리해 두었습니다.
점검 방법은 간단합니다. 백테스트가 어떤 시각에 조건 성립을 기록했다면, 그 시각에 사용한 마지막 봉의 마감 시각이 그보다 앞서 있어야 합니다. 두 값이 같으면 그 봉을 미리 쓴 것입니다. 내려받은 데이터에 진행 중인 마지막 봉이 한 줄 섞여 들어오는 경우도 흔해서, 파일을 받은 시각과 마지막 봉의 마감 시각을 대조해 한 줄을 잘라내고 시작하는 편이 안전합니다.
앞 구간을 버리지 않으면 덜 채워진 평균으로 계산됩니다
이동평균선은 앞선 봉이 있어야 계산됩니다. 10봉 평균을 쓰는데 데이터가 시작된 지 세 봉밖에 안 됐다면, 그 자리의 값은 세 봉짜리 평균이거나 아예 비어 있습니다. 지표 대부분이 그렇고, 계산은 조용히 성공합니다.
그래서 백테스트 데이터는 실제로 검증할 구간보다 앞을 더 받아 두고, 앞쪽 일부를 버리고 시작해야 합니다. 버릴 길이는 쓰는 지표 중 가장 긴 것을 기준으로 잡습니다. 워밍업에 적어 둔 대로 200봉짜리 이동평균선을 쓴다면 4시간봉에서는 33일치가 필요합니다. 90일을 검증하려면 123일치를 받아야 한다는 뜻입니다.
이걸 빠뜨리면 결과의 앞머리에만 이상한 값이 몰립니다. 기간을 나눠 비교할 때 첫 구간만 유독 다르게 나온다면 조건이 그 구간에 안 맞은 것이 아니라 지표가 덜 채워진 것일 수 있습니다.
오늘의 종목 목록으로 90일 전을 돌리면 목록이 결과를 고릅니다
354종목은 오늘 기준으로 살아 있는 목록입니다. 90일 전에는 이 중 일부가 상장 전이었고, 그 사이 거래가 끊긴 종목은 목록에 없습니다.
이 목록으로 90일을 돌리면 두 가지가 동시에 일어납니다. 신규 상장 종목은 상장 이후 구간만 데이터가 있으니 기간이 짧고, 사라진 종목은 처음부터 세어지지 않습니다. 90일 기록에서 5이평 다이버전스가 자주 나온 상위 종목을 보면 MEGA 80건, 소닉(S)·ETHW·HOME·트럼프코인(TRUMP) 각 78건인데, 이름이 낯선 쪽이 많습니다. 신규 상장 직후의 변동이 큰 구간이 그대로 표본에 들어갔기 때문입니다.
대응은 둘 중 하나입니다. 종목 목록을 검증 시작일 기준으로 다시 만들거나, 종목별 데이터 시작일을 따로 기록해 두고 결과를 종목당 평균으로 환산하거나입니다. 어느 쪽이든 "전체 몇 건" 하나만 보는 것보다는 낫습니다. 10이평 다이버전스 9,304건을 354로 나눈 종목당 26건도, 종목마다 데이터 길이가 다르면 평균으로서의 뜻이 흐려집니다. 조건별 기준이 다르다는 점은 5이평 · 10이평 다이버전스에 적어 두었습니다.
주식 백테스트의 틀이 어긋나는 자리
주식으로 백테스트를 해 본 사람이 코인 쪽으로 옮길 때 그대로 가져오면 안 되는 것이 몇 가지 있습니다.
장이 안 닫힙니다. 주식은 하루 단위로 봉이 끊기고 그 사이에 갭이 생기지만, 무기한 선물은 주말에도 계속 돌아갑니다. "전일 종가" 같은 기준이 없고, 대신 어느 시각을 하루의 경계로 볼지를 직접 정해야 합니다.
보유 비용의 성격도 다릅니다. 주식은 들고만 있으면 비용이 없는데 무기한 선물은 8시간마다 펀딩비를 주고받습니다. 이걸 빼고 계산하면 오래 들고 있는 방식일수록 실제와 멀어집니다. 방향과 부호에 따라 받는 쪽이 되기도 해서, 단순히 비용을 더 빼는 것으로 끝나지 않습니다.
가격 제한이 없다는 점도 있습니다. 상한가·하한가가 없으니 한 봉에서 벌어지는 폭이 주식보다 큽니다. 손절 폭을 고정된 퍼센트로 잡은 백테스트는 이 지점에서 실제와 갈라지고, 그래서 변동폭 자체를 기준으로 삼는 ATR 같은 값을 쓰는 방식이 나왔습니다.
한 가지 덧붙이면, 요즘은 거래소에 주식 티커를 이름으로 단 종목도 있습니다. 이 사이트의 90일 기록에도 나스닥100 ETF(QQQ) 12건, TSMC(TSM) 12건이 삼박자 상위에 들어 있습니다. 이름은 주식이지만 거래되는 방식은 무기한 선물이라 위의 세 가지가 그대로 적용됩니다.
엔진을 고르기 전에 체결 가정과 비용을 정합니다
백테스트 엔진을 무엇으로 쓸지는 대개 마지막 문제입니다. 어떤 엔진이든 아래 세 가지를 어떻게 잡았는지가 결과를 더 크게 흔듭니다.
- 체결 시점 — 조건이 성립한 봉의 종가로 처리할지, 다음 봉 시가로 처리할지. 앞쪽으로 잡으면 그 봉이 닫히기 전에 알았다고 가정하는 것이라 앞 절의 문제로 돌아갑니다.
- 체결 가격의 어긋남 — 호가가 얇은 종목일수록 표시 가격과 실제 체결 가격이 벌어집니다. 354종목에는 거래가 활발한 비트코인(BTC)·이더리움(ETH)부터 이름이 생소한 종목까지 섞여 있어서, 한 값을 전부에 적용하면 어느 쪽이든 틀립니다.
- 수수료와 펀딩비 — 짧게 자주 드나드는 방식일수록 수수료 쪽이, 오래 들고 있는 방식일수록 펀딩비 쪽이 결과를 좌우합니다.
이 세 가지를 정하지 않은 채 엔진만 바꿔 가며 돌리면, 바뀐 숫자가 조건 때문인지 가정 때문인지 구분할 수 없게 됩니다.
비교 대상이 없으면 결과를 읽을 수 없습니다
마지막이 제일 자주 빠집니다. 어떤 조건이 90일에 몇 건 나왔다는 사실만으로는 그 조건이 무엇을 골라냈는지 알 수 없습니다. 아무 조건 없이 세어도 비슷한 수가 나왔다면 그 조건은 아무것도 고르지 않은 것입니다.
그래서 조건을 건 결과 옆에 조건 없이 센 값을 같이 둡니다. 이 평소 빈도를 기저율이라고 부릅니다. 5이평 다이버전스 20,985건은 그 자체로는 크지도 작지도 않은 수이고, 354종목 90일이라는 분모와 하루 233건이라는 밀도를 같이 놓아야 읽힙니다.
백테스트를 다시 정리하면 이렇습니다. 표본 수를 먼저 세고, 시간봉을 섞지 않고, 봉이 닫힌 뒤에 판정하고, 앞 구간을 버리고, 종목 목록의 시점을 맞추고, 체결과 비용의 가정을 적어 둡니다. 여기까지 맞춘 다음에야 조건을 비교하는 일이 의미를 갖습니다. 순서를 뒤집으면 조건을 아무리 바꿔 봐도 무엇 때문에 숫자가 움직였는지 끝내 알 수 없습니다.
처음 보는 말이 있으면 용어 사전에 다이버전스·펀딩비·미결제약정 등을 풀어 두었습니다.