1. 지금 하고 있는 것
퀀트 전략을 Claude Code와 함께 직접 구현하고 있습니다. 전략 아이디어는 있는데 코딩을 전문으로 하는 사람이 아니다 보니, 에이전트에게 "이렇게 짜줘"라고 지시하면서 백테스트를 만들어나가는 방식으로 진행 중입니다.
결과물은 나옵니다. 수익률도 찍히고, 포트폴리오 비중도 나오고, 월별 로그도 보입니다.
문제는 그게 맞는 건지 모른다는 겁니다.
2. 뭐가 불안했냐면
퀀트 전략은 규칙이 꽤 많습니다. 시장 상황에 따라 포트를 어떻게 구성할지, 어떤 기준으로 종목을 고를지, 비중은 어떻게 잡을지. 이걸 에이전트가 코드로 옮기는 과정에서 제가 의도한 것과 살짝 다르게 구현되어도 숫자는 그냥 나옵니다. 오류 메세지가 뜨는 게 아니라, 조용히 틀린 채로 돌아가는 거죠.
데이터도 마찬가지입니다. 전략에 쓰이는 종목 풀이 있는데, 거기 들어간 데이터가 전부 유효한지 사실 한 번도 제대로 점검을 안 했습니다. "괜찮겠지"라고 넘어간 게 많았어요.
이 상태에서 수익률 숫자를 믿는 건 위험하다는 걸 알고 있었는데, 어떻게 검증해야 하는지 방법을 몰랐습니다.
3. 강의와 자료에서 가져온 것
「Claude Code·Codex로 평가·리뷰 하네스 만들기」를 들으면서 방향이 잡혔습니다. 리토 님이 보여주신 구조가 제 상황에 딱 맞았거든요.
핵심은 검증을 세 단계로 나누는 겁니다.
L1: 코드가 기계적으로 잡을 수 있는 것 — 숫자 합이 맞는지, 금지된 항목이 들어오지 않았는지 같은 것들
L2: LLM이 전략 규칙과 실제 결과를 비교해서 판정하는 것
L3: 일부러 틀린 케이스를 만들어서 L1과 L2가 실제로 잡는지 확인하는 것
강의 외에 Github 자료도 같이 봤는데, 거기서 얻은 게 하나 있습니다. 코드보다 문서가 먼저라는 것. 전략 규칙을 한 곳에 명확하게 써두지 않으면 LLM judge에게 "이게 맞냐"고 물어봐도 기준이 없어서 대답을 못 합니다. 그래서 RUNBOOK.md라는 전략 명세 문서를 먼저 만들었습니다.
4. 해보니 이랬습니다
RUNBOOK.md 작성하면서 데이터 점검을 같이 했더니, 종목 풀에 오래된 데이터가 꽤 많이 남아있었습니다. 파산한 회사, 합병으로 없어진 회사들이 상태 표시만 달려있고 실제로 걸러지진 않았던 거예요. 코드가 특정 라벨만 필터링하게 되어있었는데, 나머지 라벨들은 그냥 통과시키고 있었습니다.
숫자는 정상처럼 나왔는데, 안에서는 죽은 회사들이 돌아다니고 있었던 셈입니다.
이걸 정리하고 나서 L1 체크를 만들었습니다. 비중 합이 맞는지, 종목 수가 규칙 내에 있는지, 걸러져야 하는 항목이 결과에 들어오지 않았는지 같은 것들. 9개 항목을 코드로 자동으로 확인합니다.
L3는 강의에서 리토 님이 "일부러 틀린 답을 심어서 검증기가 잡는지 확인한다"고 하신 부분에서 바로 가져왔습니다. 의도적으로 잘못된 케이스 8개를 만들어서, L1이 각각을 실제로 잡는지 테스트하는 파일을 만들었습니다. 검증 도구를 검증하는 거죠.
실행 결과는 이렇습니다:
✅ PASS G01: 비중 합 1.05 → C2 (비중 합 오류) 탐지
✅ PASS G02: 섹터 내 종목 5개 → C3 (종목 수 초과) 탐지
✅ PASS G03: 레짐 판정 오류 → C5 (레짐 불일치) 탐지
✅ PASS G04: 섹터/Flat 배분 합 = 1.20 → C6 (배분 합 오류) 탐지
✅ PASS G05: 파산 종목이 포트에 편입됨 → C7 (금지 종목 편입) 탐지
✅ PASS G06: 단일 종목 비중 25% → C8 (종목 캡 초과) 탐지
✅ PASS G07: 단일 종목 실효비중 21% → C9 (집중도 경고) 탐지
✅ PASS G08: 합병 소멸 종목이 포트에 편입 → C7 (금지 종목 편입) 탐지
결과: 8/8 PASS — L1이 모든 오류 유형을 정상 탐지8개 오류 케이스를 전부 잡았습니다. 이게 중요한 이유는, L1 체크가 실제로 동작한다는 걸 검수기 자체를 검수해서 확인했다는 겁니다. 그냥 "만들었다"와 "만들고 틀린 케이스로 검증까지 했다"는 다릅니다.
5. L2까지 실제로 돌렸고, 불일치가 나왔습니다
설계만 해두면 의미가 없을 것 같아서 바로 실행해봤습니다. 특정 월의 포 트폴리오를 RUNBOOK.md와 함께 두 모델(Claude Sonnet, Claude Opus)에 각각 넣고, 9개 클레임 판정 결과를 비교했습니다.
6/9 일치, 3건 불일치가 나왔습니다.
불일치 내용을 들여다보니 원인이 다 달랐습니다.
C05·C06은 Sonnet이 insufficient, Opus가 supported를 줬습니다. 종목이 SPY 초과 상위 4개인지, 비중이 초과수익 비례인지를 묻는 클레임인데 — Sonnet은 원본 모멘텀 수치가 제공된 재료에 없으니 판단 불가라고 했고, Opus는 최종 비중 비율을 역산해서 비례 원칙이 맞는 것 같다고 추론해버렸습니다. 판정 자체가 틀린 게 아니라 judge에게 넘긴 재료가 부족했던 겁니다.
C07은 반대로 Sonnet이 supported, Opus가 contradicted를 줬습니다. 종목 비중 캡이 지켜졌는지를 묻는 클레임인데, 해당 종목이 16.7%로 캡 한도인 16.67%에 딱 걸려있었습니다. 부동소수점 반올림 차이 하나로 모델마다 통과·위반 판정이 갈린 거예요.
C04는 RUNBOOK 자체의 문구 문제였습니다. "신규 섹터가 현 보유 섹터를 교체하려면 모멘텀 차이 > 1%p 필요"라고만 써있었는데, 어느 방향의 차이인지가 명시되지 않아서 Sonnet이 방향을 반대로 읽었습니다. "신규 섹터의 모멘텀 > 현 보유 섹터의 모멘텀 + 1%p이어야만 교체 가능"으로 방향을 명시했습니다.
세 가지를 각각 수정했습니다. L2 입력 생성 코드에 전체 섹터 ETF 점수 순위표와 종목별 모멘텀 원값을 추가했고, C07 클레임 문구에 "±0.1%p 허용 오차" 명시를 추가했으며, RUNBOOK §4 버퍼 방향 조건을 명확히 했습니다.
재검증 결과:
일치율: 9/9 (100%)
C01~C04, C06~C09: ✅ supported — 두 모델 일치
C05: ⚠️ insufficient — 두 모델 일치9/9 중 8개가 supported 일치, 1개(C05)는 두 모델 모두 insufficient로 일치했습니다. C05는 "선택된 4개 종목 외 후보들의 모멘텀값이 없어서 실제 상위 4위인지 확인 불가"라는 이유였는데, 모델이 동일하게 판단했다는 건 재료 부족 신호가 일관성 있게 나온 거라 오히려 검증기가 제대로 동작하는 증거입니다.
6. 이게 맞게 한 건지 여쭤보고 싶습니다
결국 "계산으로 떨어지는 건 L1, 맥락과 해석이 필요한 건 L2"라는 원칙은 맞는 것 같은데, 그 경계를 실제로 어떻게 잡으시는지 궁금합니다. 나아가 수학적으로 검증 가능한 연구(퀀트, 실험 등)와 사회·문화·학술적 판단이 필요한 연구를 검증하는 하네스는 설계 방향 자체가 달라야 하는 건지도 여쭤보고 싶습니다.