어떤 종목이 5일 동안 3% 올랐다고 합시다. 잘한 걸까요? 같은 기간 시장 전체가 8% 올랐다면 3%는 뒤처진 것이고, 시장이 5% 빠졌다면 3% 상승은 대단한 성과입니다. 그래서 수익률을 평가할 때는 시장 수익률을 빼고 보고, 이 차이를 초과수익이라고 부릅니다. 여기서 “시장”의 자리에 어떤 지수를 놓느냐가 벤치마크 선택입니다.
이 글의 답은 이렇습니다.
코스닥 종목의 초과수익은 코스피200으로 재면 안 되고, 종목이 속한 시장의 지수(코스닥150)로 재야 합니다.
저는 코스닥 종목 150개를 코스피200으로 재고 있었습니다.
두 지수가 79.9%p 벌어진 석 달 반 동안 코스닥 종목의 20일 초과수익이 17.7%p 왜곡됐습니다.
아래는 무엇이 잘못됐는지, 얼마나 잘못됐는지, 고친 뒤에도 남은 것, 그리고 고치다 밟은 함정 둘입니다.
무엇이 잘못됐나?
제가 관측하는 종목 목록(유니버스)은 코스피 201개와 코스닥 150개, 처음부터 두 시장이 섞여 있었습니다.
코스닥이 43%입니다.
그런데 초과수익을 계산하는 코드에는 벤치마크가 한 줄로 박혀 있었습니다.
BENCHMARK_TICKER = '069500' // KODEX 200 — 코스피200 추종 ETF
코스닥 종목의 수익률에서도 코스피200 지수의 수익률을 뺐다는 뜻입니다.
더 나빴던 건 애초에 대안이 없었다는 점입니다.
가격 데이터베이스에 코스닥150 ETF(229200)가 아예 존재하지 않았습니다. 코스피 지수만 수집하고 있었으니 시장별로 나누고 싶어도 나눌 재료가 없었습니다.
얼마나 잘못됐나?
오류의 크기는 두 지수가 얼마나 다르게 움직였는지에 달려 있습니다.
두 시장이 나란히 갔다면 벤치마크를 잘못 골라도 티가 안 납니다.
문제의 기간에는 나란히 가지 않았습니다.
| 지수 ETF | 2026-03-24 | 2026-07-06 | 수익률 |
|---|---|---|---|
| 코스피200 (069500) | 83,505원 | 130,125원 | +55.8% |
| 코스닥150 (229200) | 19,410원 | 14,730원 | −24.1% |
같은 3개월 반 동안 한쪽은 56% 오르고 다른 쪽은 24% 빠졌습니다. 격차가 79.9%p입니다.
이 기간 코스피는 소수 대형주가 끄는 급등장이었고 코스닥은 그 반대였습니다. 하필 그 구간에서 저는 코스닥 종목을 코스피 자로 재고 있었습니다.
결과는 예측할 수 있습니다.
코스닥 종목은 무슨 짓을 해도 초과수익이 나쁘게 나옵니다. 폭등하는 지수를 빼고 있으니까요.
발견은 2026년 6월 20일, 시장별 평균 초과수익을 나눠 보다가 이상해서였습니다.
코스닥 이벤트(공시나 뉴스 한 건) 606건의 5일 평균 초과수익이 −6.20%로 코스피의 −2.26%보다 4%p 가까이 나빴습니다.
여기서 틀린 결론으로 갈 수 있는 갈림길이 있었습니다.
이 숫자를 그대로 믿으면 “코스닥 종목은 뉴스 반응이 나쁘니 유니버스에서 빼자”는 결론이 자연스럽습니다. 데이터도 통계도 그럴듯한 설명(코스닥은 유동성이 낮아 정보 반영이 비효율적이다)도 붙습니다.
그 결론은 완전히 틀렸을 겁니다. 차이의 상당 부분은 종목의 성질보다 자가 틀렸다는 사실에서 나왔으니까요.
측정 도구의 결함은 이렇게 나타납니다. 오류 메시지도 크래시도 없이 그럴듯하게 틀린 숫자가 나오고, 그 숫자에 붙일 설명은 항상 만들어낼 수 있습니다.
고치는 일은 세 단계였습니다.
① 코스닥150 ETF 가격을 코스피200 ETF와 같은 기간, 같은 날짜로 소급 수집
② 종목의 시장에 따라 벤치마크를 분기
③ 과거 전건을 재계산
7월 7일에 돌린 재계산에서 코스닥 932행이 이렇게 움직였습니다.
| 지표 (코스닥, 2026-07-07 기준) | 교정 전 | 교정 후 |
|---|---|---|
| 5일 평균 초과수익 | −4.95% | −0.92% |
| 20일 평균 초과수익 | −19.78% | −2.07% |
20일 기준으로 17.7%p가 순전히 측정 오류였습니다.
기간이 길수록 두 지수의 격차가 누적되므로 20일 왜곡이 5일보다 훨씬 큰 것도 앞뒤가 맞습니다.
재계산 결과에서 가장 중요했던 건 교정된 값보다 교정되지 않은 값이었습니다.
코스피 종목의 초과수익은 단 한 행도 바뀌지 않았습니다. 벤치마크가 원래도 코스피200이었으니 당연합니다.
그런데 이 당연함이 검증에서는 결정적입니다.
처치군(코스닥)만 움직이고 대조군(코스피)은 완전히 정지한 통제 실험과 같은 구조입니다.
코스피 쪽이 조금이라도 움직였다면 재계산 코드에 부작용이 있다는 뜻이고, 교정 결과 전체를 믿을 수 없었을 겁니다.
고친 뒤에도 무엇이 남았나?
교정 후에도 두 시장의 차이가 0이 되지는 않았습니다.
2026년 9월 12일 기준으로 다시 뽑으면 코스피 8,840건과 코스닥 1,146건의 5일 격차는 0.32%p(코스닥이 낮음), 20일 격차는 1.97%p인데 부호가 뒤집혀 코스피 쪽이 낮습니다(표는 부록에). 남은 갭에 대한 제 해석은 이렇습니다.
지수는 시가총액 가중입니다. 시가총액이 큰 종목이 지수를 더 많이 움직이는 방식이라 소수의 대형주가 지수를 끕니다.
반면 제가 재는 건 개별 종목 하나하나입니다.
지수가 몇몇 리더 덕에 오르는 국면에서는 중간쯤 되는 종목이 지수를 못 따라가고, 지수를 이기는 종목의 비율이 절반보다 훨씬 적습니다.
이건 벤치마크를 바꿔서 해결되는 문제가 아닙니다. 시총가중 지수를 개별 종목의 기준선으로 쓰는 한 남는 구조적 편향입니다.
그래서 저는 초과수익의 절대값을 그대로 믿지 않습니다.
같은 기간 미분류 이벤트의 평균을 한 번 더 빼서 상대 비교를 합니다. 편향이 모든 이벤트에 공통으로 걸린다면 차감으로 상쇄되니까요.
이게 해결이 아닌 완화라는 점이 중요하고, 그 사실을 알고 쓰는 것과 모르고 쓰는 것은 다릅니다.
고치다 밟은 함정 둘
둘 다 같은 부류입니다.
“당연히 그럴 것”이라고 가정한 게 그렇지 않았던 경우입니다.
데이터 출처는 종목의 시장을 모릅니다
시장별로 벤치마크를 나누려면 종목이 코스피인지 코스닥인지 알아야 하는데, 가격 데이터 API의 종목 코드 접미사(.KS / .KQ)로 판별하면 될 거라 생각했습니다. 안 됩니다. 그 접미사는 데이터 제공처의 내부 규칙일 뿐이라 실제 상장 시장과 일치한다는 보장이 없습니다. 결국 별도의 국내 출처에서 시장 라벨을 따로 받아와야 했습니다.
벤치마크를 종목 목록에 등록하면 안 됩니다
가격을 수집하려면 수집 대상에 넣어야 하고, 가장 쉬운 방법은 종목 마스터 테이블에 코스닥150 ETF를 추가하는 것이었습니다. 그러면 그 ETF가 포트폴리오 매수 후보가 됩니다. 리밸런싱 로직이 “활성 종목 전체”를 후보로 삼기 때문입니다. 코스피200 ETF가 같은 이유로 이미 포트폴리오에 편입돼 있었다는 걸 이때 발견했습니다. 그래서 벤치마크는 종목 마스터에 등록하지 않고 수집 목록에만 별도로 추가했습니다. 측정 도구와 측정 대상을 같은 테이블에 넣으면 도구가 대상이 됩니다.
자주 묻는 질문
왜 종목 코드 접미사로 시장을 판별하면 안 되나요
.KS 와 .KQ 는 데이터 제공처의 내부 규칙일 뿐이라 실제 상장 시장과 일치한다는 보장이 없습니다. 저는 별도의 국내 출처에서 시장 라벨을 따로 받아왔습니다.
벤치마크 ETF 를 종목 마스터에 넣으면 왜 안 되나요
리밸런싱 로직이 “활성 종목 전체”를 후보로 삼기 때문에 그 ETF 가 매수 후보가 됩니다. 실제로 코스피200 ETF 가 같은 이유로 이미 포트폴리오에 편입돼 있었어요. 측정 도구와 측정 대상을 같은 테이블에 넣으면 도구가 대상이 됩니다.
교정 뒤에도 두 시장 차이가 남는 건 왜인가요
지수는 시가총액 가중이라 소수의 대형주가 끌고, 저는 개별 종목 하나하나를 잽니다. 지수가 몇몇 리더 덕에 오르는 국면에서는 중간쯤 되는 종목이 지수를 못 따라갑니다. 벤치마크를 바꿔서 해결되는 문제가 아니라 구조적 편향입니다.
그럼 초과수익 절대값은 못 쓰나요
그대로 믿지 않습니다. 같은 기간 미분류 이벤트의 평균을 한 번 더 빼서 상대 비교를 합니다. 편향이 모든 이벤트에 공통으로 걸린다면 차감으로 상쇄되니까요. 해결이 아니라 완화입니다.
남는 것
초과수익 계산에서 벤치마크 선택은 부수적인 설정이 아니라 결과를 지배하는 변수입니다. 여기서는 20일 기준 17.7%p가 벤치마크 하나로 움직였습니다. 오류의 크기는 두 지수가 갈라진 정도에 비례해서, 나란히 가는 구간에서는 몇 년을 잘못 써도 티가 안 나다가 갈라지는 순간 한꺼번에 드러납니다.
측정 도구의 결함은 그럴듯한 숫자로 나타납니다. “코스닥은 뉴스 반응이 나쁘다”는 결론은 데이터와 설명을 모두 갖추고 있었습니다. 이 오류는 몇 달간 아무 문제 없이 작동하는 것처럼 보였고, 코드는 정상이었고, 숫자는 나왔고, 대시보드도 잘 그려졌습니다. 틀린 자로 재도 눈금은 읽힙니다.
교정을 검증할 때는 바뀌지 않아야 할 것이 바뀌지 않았는지를 함께 봅니다. 코스피 쪽 무변화가 교정 결과를 믿을 수 있게 만든 근거였습니다.
완전히 해결되지 않은 부분은 해결됐다고 쓰지 않습니다. 시총가중 지수 대 개별 종목이라는 구조적 편향은 남아 있습니다.
부록 1: 시점별 수치
증상을 발견한 6월 20일 값, 재계산한 7월 7일 값, 지금 값이 서로 다른 이유는 날짜와 표본입니다. 그 사이 이벤트가 쌓였고, 교정 전 값은 재계산이 덮어써서 지금 DB로는 다시 만들 수 없습니다. 그 값들의 출처는 당시 작업 일지이고, 발행 전 자동 대조가 가능한 건 현재 값뿐이라 2026년 9월 12일 기준으로 다시 뽑아 둡니다.
| 시점 | 시장 | 이벤트 수 | 5일 평균 초과수익 | 20일 평균 초과수익 |
|---|---|---|---|---|
| 2026-06-20 (증상, 교정 전) | 코스피 | 미기록 | −2.26% | 미기록 |
| 2026-06-20 (증상, 교정 전) | 코스닥 | 606 | −6.20% | 미기록 |
| 2026-07-07 (재계산, 교정 전 → 후) | 코스닥 | 932 | −4.95% → −0.92% | −19.78% → −2.07% |
| 2026-09-12 (현재) | 코스피 | 8,840 | −0.86% | −4.40% |
| 2026-09-12 (현재) | 코스닥 | 1,146 | −1.18% | −2.43% |
코스닥150 가격을 채운 뒤 두 벤치마크의 데이터 행 수가 정확히 일치하는지 확인했고(현재도 일치합니다), 겹치는 구간에서는 서로 다른 두 출처의 값이 같은지 교차검증했습니다.
이 글에서 고친 것 1개
- 2026-09-12 — 처음 발행본은 두 표의 기준 시점과 표본 수를 적지 않아, 같은 “교정 전 5일 평균”이 −6.20%와 −4.95%로 두 번 나오는데 이유가 없었습니다. 날짜와 표본을 붙이고, 옛 값이 재현 불가라는 사실을 밝히고, 현재 값을 대조 항목으로 추가했습니다.
이 사이트의 수치는 주 1회 DB와 다시 대조하고, 판단이 바뀌면 지우지 않고 글 안에 덧붙입니다. 갱신은 RSS로 받을 수 있습니다.