퀀트 / 트레이딩15 분 읽기

죽은 실험에서 배운 걸, 살아있는 봇 네 개에는 적용하지 않았다

실패한 실험 회고에 '검정력 계산 부재'를 결함으로 적어놨습니다. 그러고 살아있는 페이퍼 봇들은 감사하지 않았습니다. 열어봤더니 네 개 전부 같은 결함을 달고 돌아가고 있었고, 그중 하나는 판정까지 2.6년이 필요했습니다.

#trading#paper-trading#methodology#statistics#reality-check
부호 비교 게이트는 언제나 판정을 내놓지만, 실제로 판정하려면 24배 큰 표본이 필요하다는 2패널 도식
왼쪽: 내가 배포한 게이트는 항상 답을 내놓는다. 오른쪽: 그 답이 우연과 구분되려면 30건이 아니라 722건이 필요했다.

전부 페이퍼(모의) 실험입니다. 표본 수·표준편차·수익률은 실제 원장에서 나온 값입니다.

죽은 실험 하나를 정리하면서 회고를 썼습니다. 마지막 섹션 제목이 "게이트 설계 결함 — 다음 실험에 반드시 반영"이었고, 6번 항목은 이랬습니다.

착수 전 검정력 계산 부재 — 애초에 답이 나올 수 없는 표본율로 6개월을 태울 뻔했다.

문서를 커밋하고 만족했습니다. 그리고 며칠 뒤, 아직 살아서 돌아가고 있는 페이퍼 봇들을 점검하다가 이상한 걸 봤습니다. 한 봇의 대시보드가 "표본 수집 중 6/30, 판정까지 24건 더 필요"라고 띄우고 있었습니다.

그 30이라는 숫자가 어디서 왔는지 기억나지 않았습니다.

당신의 프로젝트에 "N개 모이면 판단한다"는 기준이 있다면, 그 N은 어떻게 정해졌습니까?

값싼 설명부터 의심한다

처음엔 "표본이 적어서 아직 모르는 것"이라고 생각했습니다. 그건 시간이 해결해 줍니다. 기다리면 됩니다.

확인차 계산을 해봤습니다. 완결 6건의 초과수익 평균은 +1.09%p, 표준편차는 9.59%p였습니다. 표준오차 3.91, t값 0.28.

여기까지는 "표본이 적다"가 맞습니다. 문제는 다음 줄이었습니다. n을 30으로 채워도 표준오차는 1.75까지밖에 안 줄어듭니다. 그러면 유의미하다고 말하려면 평균 초과가 3.50%p여야 합니다. 관측된 점추정의 세 배입니다.

즉 이 게이트는 30건을 채워도 답을 못 냅니다. 기다림이 해결하는 문제가 아니었습니다.

관측된 효과크기(1.09%p)를 80% 검정력으로 잡으려면 표본이 몇 개 필요한지 계산했습니다.

n = (1.96 + 0.842)^2 x sd^2 / effect^2
  = (2.802 x 9.59 / 1.09)^2
  = 607

경제적으로 의미 있는 하한(1.0%p)으로 다시 계산하면 722건. 완결 페이스가 하루 0.76건이니 약 2.6년입니다.

30이라는 숫자는 근거가 없었습니다. 그냥 "그쯤이면 되겠지"였습니다.

그리고 하나가 더 있었다

여기서 멈췄으면 봇 하나 고치고 끝났을 겁니다. 대신 나머지 세 개를 열어봤습니다.

KRX 저PBR 밸류 봇. 대시보드 상단 KPI에 이렇게 떠 있었습니다.

Sharpe 27.84 (벤치 12.93)

포워드 관측 1개월에서 나온 숫자였습니다. 관측 하나짜리 연율화 Sharpe는 잡음인데, 그게 게이트 지표 자리에 크게 떠 있으니 읽는 사람은 "이기고 있다"로 읽습니다. 게이트 규칙은 누적초과 > 0 AND Sharpe > 벤치Sharpe. 부호 비교입니다.

듀얼모멘텀 로테이션 봇. 사전등록된 판정 기준이 "페이퍼 기간 최대낙폭 < 지수 보유 최대낙폭"이었습니다. 방어형 전략이니 타당한 기준입니다. 그런데 그 주장은 지수가 실제로 빠져야만 시험됩니다. 관측 기간 중 지수 최대낙폭은 1.5%였습니다. 아무 일도 일어나지 않았습니다. 그런데 화면에는 누적 +3.7%가 찍혀 있었고, 그건 "잘 되고 있다"로 읽힙니다.

레버리지 ETF 분할매수 봇 2종. 판정 기준에 비교 대상 자체가 없었습니다. 이건 따로 다룰 만큼 이야기가 길어서 별도 글로 뺐습니다.

네 개 중 네 개. 전부 같은 모양이었습니다.

게이트가 언제나 판정을 내놓는다. 그 판정이 우연과 구분되는지는 묻지 않는다.

왜 죽은 것에만 적용했나

이게 이 글의 진짜 주제입니다. 검정력이라는 개념을 몰라서 생긴 일이 아닙니다. 저는 이미 그걸로 실험 하나를 착수 전에 접었고, 자기학습 루프에 최소 표본 문턱을 달았고, 다중검정 보정으로 제 엣지를 스스로 기각하기까지 했습니다.

교훈은 전부 부검 대상에 적용됐습니다. 실패를 정리하면서 배웠고, 실패를 정리하는 문서에 적었습니다.

살아있는 프로젝트는 감사 대상이 아니었습니다. 초록불이 켜져 있었으니까요. 그런데 초록불의 출처가 바로 그 결함 있는 게이트였습니다. 잘 돌아간다는 신호 자체가 검증 안 된 규칙에서 나오고 있었습니다.

같은 점검에서 이런 것도 나왔습니다. 3주 전에 와인드다운한 봇의 일일 리포트 잡이 여전히 매일 아침 텔레그램을 보내고 있었고, 2주 전에 멈춘 실주문 봇이 대시보드에 시작 버튼과 함께 등록돼 있었습니다. 오클릭 한 번이면 무엣지 라이브가 재가동됩니다.

저는 봇을 깨끗이 죽이는 체크리스트를 글로 쓴 적이 있습니다. 그 체크리스트에 "대시보드 등록 제거"가 들어 있습니다. 제가 쓴 걸 제가 안 지켰습니다.

당신이라면 어떻게 하겠습니까

여기서 갈림길이 있습니다. 계산해보니 판정까지 2.6년입니다.

  1. 봇을 끈다 — 2.6년은 너무 길다
  2. 게이트 문턱만 올린다 — 30을 722로 바꾸고 계속 돌린다
  3. 게이트의 모양을 바꾼다

1번은 틀렸습니다. 페이퍼 봇의 운영비는 사실상 0입니다. 느린 건 중단 사유가 아닙니다.

2번도 부족합니다. 722건을 다 모아도 여전히 "평균 부호가 양수냐"만 묻는다면, 꼬리 한 건이 판정을 만드는 문제는 그대로입니다. 실제로 이 봇은 완결 6건 중 최대 1건을 빼면 평균이 +1.09%p에서 -2.07%p로 부호가 뒤집힙니다.

3번을 택했습니다.

판정 불가를 1급 상태로 만든다

네 봇에 공통으로 넣은 구조입니다.

첫째, 최소효과(MDE)를 데이터 보기 전에 고정합니다. 마찰 비용 위로 "이 아래면 돌릴 이유가 없다"는 값입니다. 내부자 매수 봇은 건당 1.0%p, 밸류 봇은 연 초과 5%p. 데이터에서 뽑은 값이 아니라 먼저 박는 값입니다.

둘째, 필요 표본을 계산해 화면에 상시 노출합니다. 그게 2.6년이면, 그 숫자 자체가 결론입니다. 숨기면 안 됩니다.

셋째, PASS는 세 축을 동시에 요구합니다.

  • 부트스트랩 95% CI 하한 > 0 — 크기
  • 상하 10% 절사평균 > 0 — 꼬리 면역
  • 부호검정 p < 0.05 — 방향 일관성

t-분포 CI 대신 부트스트랩을 쓴 이유는 이벤트 수익 분포의 꼬리가 두꺼워서입니다. 절사평균과 부호검정은 서로 다른 방식으로 "한 건이 다 만든 평균"을 걸러냅니다.

넷째, futility 조항. 초과 CI 상한이 MDE보다 작으면 표본을 다 채우기 전에 중단합니다. 이겨도 남는 게 없다는 게 확정됐는데 계속 모을 이유가 없습니다.

다섯째, 이게 핵심인데 — 판정 불가를 별도 상태로 만듭니다. 표본이 필요치에 못 미치면 PASS도 FAIL도 선언하지 않습니다. "졌다"고 말할 검정력도 없기 때문입니다. 그 상태에서 승률·수익률·Sharpe는 화면에서 회색 "참고치"로 격하되고, 경고 배너가 붙습니다.

게이트 v2: 표본 수집 — 판정 개시까지 24건
  초과 CI95 [-5.28, +8.68]%p · 절사평균 +1.09%p · 부호검정 p=1.000
  최소효과 1.0%p 검출에 필요한 표본 722건 (현재 6건, sd 9.59%p)
  판정 미확정 — 위 승률·평균은 참고치이며 채택 근거가 아님

방어형 전략에는 조항이 하나 더 붙습니다. 시험 성립 조건입니다. 낙폭 방어를 주장하는 봇은 실제로 하락 구간이 와야 시험됩니다. 지수 최대낙폭이 기준치에 못 미친 채 관측 기간이 끝나면 성공도 실패도 아닌 무판정 종료로 정의했습니다. 이 조항이 없으면 강세장만 겪은 방어 전략이 "12개월 수익 났으니 성공"으로 기록됩니다.

자가진단 3줄

지금 돌리고 있는 자동화·실험·봇에 대해:

  1. "N개 모이면 판단한다"의 N이 어디서 왔습니까? 검정력 계산이 아니라 감이라면, 그 게이트는 결론을 내놓겠지만 그 결론은 근거가 없습니다.
  2. 당신의 대시보드는 "판정 불가"를 표시할 수 있습니까? PASS와 FAIL만 있는 화면은 표본이 1개일 때도 둘 중 하나를 고릅니다.
  3. 가장 큰 관측치 하나를 빼면 결론이 뒤집힙니까? 뒤집힌다면 지금 보고 있는 건 전략이 아니라 그 한 건입니다.

솔직한 부분

게이트를 고쳤다고 전략이 좋아진 건 하나도 없습니다. 오히려 반대입니다. 고치기 전엔 네 봇 다 "순조롭게 진행 중"이었고, 고친 뒤엔 넷 다 "판정 불가, 필요 표본 미달"입니다. 한 봇은 판정까지 2.6년이 걸린다는 답이 나왔습니다.

이게 개선입니다. 이전 화면은 정보가 아니라 위안이었습니다.

그리고 이 글의 결함도 적어둡니다. 저는 이미 6건의 데이터를 본 뒤에 MDE를 정했습니다. 사전등록의 원칙대로라면 데이터를 보기 전이어야 합니다. 그래서 MDE를 관측된 효과크기(1.09%p)가 아니라 마찰 비용에서 역산한 값(1.0%p)으로 잡았습니다. 완전한 사전등록은 아니고, 차선책입니다.

마지막으로, 네 봇의 현재 상태를 한 줄로 요약하면 이렇습니다. 전부 하락장을 기다리는 중입니다. 방어를 주장하는 전략은 방어할 일이 생겨야 시험되고, 그게 언제 올지는 제가 정할 수 없습니다.

지금 돌리는 실험이 하나라도 있다면, 딱 한 줄만 계산해 보세요. (2.802 * sd / 최소효과)^2. 그 숫자가 당신의 계획보다 크다면, 지금 보고 있는 초록불은 아직 아무 의미가 없습니다.

관련 글