5 분 분량

지난 글에서 밸류 스크리닝 32가지를 21개월 돌렸습니다. 매달 20종목을 다시 뽑는 기본 설정이 누적 +53.6%였고, 같은 유니버스를 동일비중으로 들고 간 것이 +23.8%였습니다. 30%p 앞섰습니다.

이 숫자를 보면 보통 “통했다”고 결론 내립니다. 그런데 물어야 할 게 하나 더 있습니다. 아무 종목이나 20개 찍어도 이 정도는 나오지 않았을까요.

이번 글은 그걸 재는 방법입니다. 코드는 montecarlo.py에 있고, 데이터는 지난 글과 같은 KRX 월말 스냅샷과 구간별 등락률입니다. 함께 받아야 하는 파일과 데이터를 직접 받는 방법은 코드 페이지에 정리해 두었습니다.

비교 대상을 만드는 것이 전부입니다

몬테카를로 시뮬레이션이라고 하면 거창하게 들리지만 하는 일은 단순합니다. “실력이 전혀 없었다면 어떤 결과들이 나왔을까”를 수천 번 만들어 보고, 실제 결과가 그 더미 안 어디쯤인지 보는 것입니다.

여기서 중요한 건 “실력이 없는 경우”를 어떻게 정의하느냐입니다. 이번 전략의 짝은 명확합니다. 매달 같은 유니버스에서 20종목을 무작위로 뽑아 동일비중으로 담습니다. 유니버스도 같고, 종목 수도 같고, 재선정 주기도 같습니다. 다른 건 고르는 방식뿐입니다.

def random_paths(pop, trials, rng, n_pick=20):
    """무작위 20종목 동일비중을 매 구간 새로 뽑는 경로들."""
    paths = np.empty((trials, len(pop)))
    for i, arr in enumerate(pop):           # arr = 그 구간 유니버스의 수익률 배열
        idx = rng.integers(0, len(arr), size=(trials, n_pick))
        paths[:, i] = arr[idx].mean(axis=1)
    return paths

유니버스는 구간마다 1,226~1,514종목입니다. 3,000번 돌렸습니다.

1. 무작위 20종목의 성적표

무작위 포트폴리오 분포

  21개월 누적
하위 5% −9.2%
하위 25% +8.4%
중앙값 +21.5%
상위 25% +37.2%
상위 5% +62.7%
최고 / 최저 +129.2% / −34.2%

먼저 눈에 띄는 것은 분포가 엄청나게 넓다는 점입니다. 같은 유니버스에서 같은 규칙으로 20종목을 뽑았을 뿐인데 −34%부터 +129%까지 나옵니다. 20종목은 분산이 덜 된 포트폴리오라 뽑기 운이 크게 작용합니다.

무작위의 중앙값 +21.5%가 유니버스 +23.8%와 비슷한 것은 당연합니다. 무작위 추출의 기댓값은 전체 평균이니까요.

그리고 실제 전략의 +53.6%를 무작위가 넘어선 비율이 10.2%입니다. 1,000번 중 102번은 아무렇게나 찍어도 이만큼 나왔다는 뜻입니다.

이걸 어떻게 읽어야 할까요. 10%는 “흔한 일”은 아닙니다. 상위 10% 언저리에 있으니 그냥 운이라고 하기도 어렵습니다. 하지만 학술 논문이었다면 통과 못 할 숫자입니다. 보통 5%를 기준선으로 씁니다. “통했을 수도 있다. 하지만 이 데이터로는 확정할 수 없다”가 정직한 결론입니다.

2. 같은 전략을 다시 굴리면 얼마나 달라질까

다른 질문입니다. 전략의 월별 수익률 21개를 그대로 두고, 순서와 중복만 바꿔서 다시 뽑아 봅니다. 같은 성질의 시장을 다시 한번 겪는다면 어떤 결과가 나왔을지를 보는 것입니다. 부트스트랩이라고 부릅니다.

부트스트랩 분포

  값
누적수익률 90% 구간 −6.4% ~ +148.1%
중앙값 +54.8%
실제 +53.6%
손실로 끝날 확률 7.7%
유니버스보다 못할 확률 23.3%

90% 구간이 −6%에서 +148%입니다. 같은 전략, 같은 성질의 시장인데 결과가 이만큼 벌어집니다.

이 표를 본 뒤에는 “+53.6%”라는 숫자를 전처럼 말하기 어렵습니다. 그 숫자는 가능한 결과들 중 하나를 뽑은 것이고, 옆자리에는 +10%도 있고 +120%도 있습니다. 백테스트 결과를 한 숫자로 보고하는 관행 자체가 오해를 만듭니다.

21개월이라 불확실성이 큰 면도 있습니다. 표본이 길어지면 연평균으로 환산한 수익률의 구간은 좁아집니다. 그래서 이 표는 “전략이 나쁘다”가 아니라 “21개월로는 이 정도밖에 말할 수 없다”를 보여줍니다.

3. MDD는 대부분 순서 운입니다

세 번째 실험은 더 단순합니다. 월별 수익률의 순서만 섞습니다. 곱셈은 순서를 바꿔도 결과가 같으니 누적수익률은 +53.6%로 고정입니다. 달라지는 건 최대낙폭(MDD)뿐입니다.

  MDD
실제 −13.5%
섞었을 때 하위 5% −21.9%
섞었을 때 중앙값 −14.0%
섞었을 때 상위 5% −12.8%
최악 / 최선 −26.4% / −7.6%

같은 수익률 묶음인데 MDD가 −7.6%에서 −26.4%까지 나옵니다. 나쁜 달들이 연달아 오면 깊어지고, 흩어져 오면 얕아집니다. 그 순서는 전략이 정하는 게 아닙니다. 목돈을 한 번에 넣을지 나눠 넣을지도 수익률이 오는 순서에 달린 문제여서, 코스피로 본 일시 투자와 분할 투자에서는 승부가 대부분 첫해 시장 방향에서 갈렸습니다.

위험 지표 글에서는 MDD를 전 고점 대비 가장 깊이 떨어진 폭으로만 다뤘는데, 그 폭이 수익률이 어떤 순서로 왔느냐에 따라 크게 달라진다는 것이 이번에 숫자로 드러났습니다. 백테스트 MDD가 −13%라고 해서 실전 MDD가 그 근처일 거라고 기대하면 안 됩니다. 중앙값이 −14%이니 실제 값이 운이 좋았던 편도 아니지만, 같은 전략에서 −26%가 나올 수 있다는 사실은 미리 알고 시작해야 합니다.

4. 32개 중 1등을 골랐다는 사실의 값

여기가 이 글의 핵심입니다.

지난 글에서 32가지 설정을 돌렸고, 그중 1등이 +63.5%였습니다. 그 숫자를 성과로 내세운다면, “32개를 돌려서 그중 제일 좋은 것을 골랐다”는 사실도 같이 계산에 넣어야 합니다.

시뮬레이션으로 재봅니다. 무작위 포트폴리오 32개를 한 세트로 만들고, 그 세트에서 1등만 기록합니다. 이걸 3,000번 반복합니다. 실력이 하나도 없는 32개 중 1등은 얼마나 좋아 보일까요.

32개 중 1등의 분포

  21개월 누적
무작위 1개의 중앙값 +21.5%
무작위 32개 중 1등의 중앙값 +76.3%
그 1등의 90% 구간 +55.4% ~ +111.2%
실제 32개 중 1등 +63.5%

실력이 전혀 없어도 32개를 돌려 1등을 고르면 중앙값 +76.3%가 나옵니다. 하나만 돌렸을 때의 +21.5%에서 55%p가 그냥 “고르는 행위”에서 생깁니다.

그리고 실제 1등인 +63.5%는 이 분포에서 상위 81.5% 자리입니다. 다시 말해, 순전한 운으로 32개를 돌렸다면 열 번 중 여덟 번은 +63.5%보다 좋은 1등이 나왔을 것입니다.

지난 글의 “+63.5%”는 자랑할 숫자가 아니라 오히려 밋밋한 숫자였던 셈입니다.

이 검정이 공정한지 점검

여기서 한 가지 짚어야 합니다. 실제 32개 설정은 서로 겹치는 종목을 담습니다. 다 같은 밸류 스크리닝이니까요. 서로 비슷한 32개에서는 1등이 덜 튀고, 서로 독립인 32개에서는 1등이 더 높이 튑니다. 무작위 쪽이 더 독립적이면 위 비교는 무작위에 유리하게 기울어집니다.

재봤습니다.

  32개 사이의 월별 수익률 평균 상관
실제 설정 32개 0.912
무작위 포트폴리오 32개 0.846

무작위 쪽이 조금 덜 묶여 있습니다. 둘 다 같은 시장을 타기 때문에 차이가 크지는 않지만, 그만큼 위의 81.5%는 실제보다 다소 후하게 나온 값입니다. 정확한 수치로 못을 박기보다는 “32개 중 1등이라는 성적은 전혀 특별하지 않았다” 정도로 읽는 것이 맞습니다.

이런 점검을 넣는 이유는 시뮬레이션이 결론을 정해 주는 기계가 아니기 때문입니다. 비교 대상을 어떻게 만드느냐가 결과를 정하고, 그 설계가 공정한지는 따로 확인해야 합니다.

5. 시장을 빼고 보면

마지막으로 가장 냉정한 숫자입니다. 전략 수익률에서 유니버스 수익률을 매달 빼면 순수한 초과수익만 남습니다. 시장이 올라서 번 부분이 사라집니다.

  값
월평균 초과수익 +0.85%
표준편차 6.23%
플러스인 달 21개월 중 12개월
t값 0.63

t값은 “평균이 0이 아니라고 말할 수 있는가”를 재는 값입니다. 보통 2를 넘어야 우연으로 보기 어렵다고 말합니다. 0.63은 그 근처도 아닙니다.

월평균 +0.85%는 연으로 환산하면 10%가 넘는 초과수익입니다. 숫자만 보면 훌륭합니다. 그런데 월별 변동이 6.23%나 되고 표본이 21개월뿐이라, 이 평균이 0과 다르다고 주장할 근거가 없습니다. 무작위 포트폴리오의 월평균 초과수익 분포에서도 16.8%가 +0.85%를 넘었습니다. 1번 실험의 10.2%와 같은 이야기를 다른 각도에서 하는 것입니다.

t값 2를 넘기려면 이 정도 평균과 변동성에서 표본이 215개월쯤 필요합니다. 18년입니다. 초과수익이 지금 수준으로 계속 이어진다고 가정해도 그렇습니다.

그래서 이 전략을 버려야 하나

아닙니다. 그리고 이게 이 글에서 제일 오해하기 쉬운 부분입니다.

“통계적으로 유의하지 않다”는 “효과가 없다”가 아닙니다. 표본이 짧아서 판단을 못 하겠다는 뜻입니다. 밸류 효과 자체는 수십 년치 데이터로 검증된 것이 많고, 이 블로그의 밸류 팩터 글에서도 긴 표본으로 확인했습니다. 여기서 부족한 것은 효과의 존재가 아니라 이 21개월 실험이 그 존재를 증명할 힘입니다.

몬테카를로가 주는 것은 결론이 아니라 눈금입니다. 이번에 얻은 눈금은 이렇습니다.

  • +53.6%는 무작위 상위 10% 자리다. 나쁘지 않지만 확정할 수 없다.
  • 같은 전략을 다시 굴리면 −6%에서 +148% 사이 어디든 나올 수 있다.
  • MDD −13.5%는 이 전략의 성질이라기보다 이번 순서의 결과다.
  • 32개 중 1등인 +63.5%는 운으로도 흔히 나오는 수준이다.
  • 초과수익 t값은 0.63이다.

백테스트를 보고할 때

이 다섯 개 실험은 돌리는 데 6초 걸립니다. 그런데 백테스트 결과를 내놓을 때 이런 걸 같이 붙이는 경우는 드뭅니다.

앞으로 어떤 전략의 성과를 보시거든 세 가지를 물어보시면 됩니다. 같은 조건에서 무작위로 뽑으면 얼마가 나오나, 몇 개를 돌려보고 그걸 고른 건가, 표본이 몇 개인가. 이 셋에 답하지 않은 수익률은 크기를 알 수 없는 숫자입니다.

제 것도 마찬가지라서 이 글을 썼습니다.

2026-09-28 수정: 32개 중 1등의 중앙값 +76.3%와 무작위 1개의 중앙값 +21.5%의 차이를 54%p에서 55%p로 고치고, 무작위가 실제 성적을 넘은 비율 10.2%를 “상위 10% 안”이 아니라 “상위 10% 언저리”로, 표본이 길어질 때 좁아지는 것은 연평균으로 환산한 수익률의 구간이라는 점을 바로잡았습니다.


이 글은 학습과 정보 공유 목적으로 작성되었으며, 특정 종목이나 상품에 대한 투자 권유가 아닙니다. 본문의 수익률은 거래비용과 세금을 반영하지 않은 과거 데이터이며 미래 성과를 보장하지 않습니다. 투자의 판단과 책임은 투자자 본인에게 있습니다.

최종 수정: