$

케이스 05 · 자율 시스템

Quant AI Lab — 스스로를 속일 수 없는 트레이딩 루프 만들기

뉴스 기반 트레이딩 시스템을 두 층으로 나눴다. LLM(Claude)이 리서치를 읽고 근거 있는 매매 시그널을 지식 볼트에 기록하면, 헤드리스 Python 워커가 검증된 시장 데이터로 게이트·채점·스테이지 승급을 판정한다. 실행 경로에는 LLM이 없다. 정작 어려운 건 시그널 생성이 아니라, 자기개선 루프를 정직하게 만드는 일이었다. 모든 실패 모드가 보수적으로 무너지고, 지표를 속여 봤자 스스로 손해가 되도록.

  • Autonomous Agent
  • Self-Improvement Loop
  • Fail-Closed Risk Gate

$

문제의식

LLM 기반 트레이딩에 실자본을 맡길 수 있나? 위험은 구체적이다: 진입가를 환각하고, 백테스트에 과적합하고, 적중률을 부풀리려 쉬운 시그널만 쓰고, 깨진 지표가 조용히 표류하게 둘 수 있다. 똑똑해 보이지만 증명 못 하는 시스템은 없느니만 못하다.

컨셉 — 사고와 측정의 분리

한 레포에 두 층이 함께 있다. 지식 층은 옵시디언 "LLM 위키"(카파시 패턴)로 테제와 결정, 시그널을 담고, Claude는 여기에만 쓴다. 실행 층은 헤드리스 Python 워커(스케줄 기반, LLM 클라이언트 없음)로, 시그널 파일을 읽고 리스크 게이트를 돌리고 만기된 시그널을 검증된 종가로 채점한다. LLM이 준 가격은 절대 쓰지 않는다. 사고와 측정이 설계상 물리적으로 분리돼서, 측정기가 나쁜 숫자에 설득당하지 않는다.

루프 구조

  1. signal

    Claude → pending/ 에만

  2. risk gate

    버딕트+스테이지 캡, fail-closed

  3. score

    검증 종가 대비, 경로 의존

  4. hit-rate

    윌슨 하한이 실자본을 게이트

  5. stage-gate

    조건 충족 시에만 자동 0→1

  6. lessons

    결과 → 교훈 → 다음 결정

진행 과정: 감사, 복구, 운영

  1. 1 · 감사: 루프가 끊겨 있었다

    멀티 에이전트 감사로 측정 층이 조용히 깨져 있던 걸 발견했다. 볼트 영어화 마이그레이션이 워커의 (한국어) 파싱 앵커를 깨뜨려, 적중률 카운터 갱신이 무의미한 no-op이 돼 있었다. 픽스처도 낡아서 303개 테스트가 죽은 계약 위에서 통과하고 있었다.

  2. 2 · 재연결 + 상태 정합

    파싱을 조용히가 아니라 시끄럽게 실패하도록 다시 고정했다. 그리고 오염된 상태를 바로잡았다. 같은 티커의 주식($22, 이더리움의 $2,309이 아니라)에 대고 채점된 가짜 "승리"가 있어서, 무효화하고 실제 종가로 다시 채점했다.

  3. 3 · 승급 머신러리 구현

    문서는 워커가 자동 승급한다고 약속했지만 코드엔 없었다. 졸업 조건을 구현했다. 시그널 N≥30, 적중률 >55%, 단측 95% 윌슨 하한 >0.50(엣지가 소표본의 운이 아니라 실재해야 한다), 게이트 위반 0, 메모리 루프 100% 폐쇄. 모호하던 "샤프>1.0"을 대체했다.

  4. 4 · 버딕트 레이어 견고화

    깨진 설정은 이제 fail-closed로 막힌다. 미검증·노후 티커는 재캘리브레이션 전까지 실매수를 차단한다. 워크포워드 실패도 버리지 않고 1급 버딕트로 영속시키는데, 검증 파이프라인의 부정적 지식이야말로 핵심이기 때문이다.

  5. 5 · 재귀 이음매 닫기

    레슨 다이제스트가 채점된 모든 결과를 다음 결정으로 되먹인다(시그널 작성 라운드는 인용이 코드로 강제됨). 인테이크 스탬핑은 게이트 버딕트를 첫 인식 시점에 고정해, 이후 테제 확신 변화가 적중률 모집단을 소급 재필터링하지 못하게 한다.

  6. 6 · 운영 + 의사결정 반쪽 자동화

    첫 실전 멀티 에이전트 라운드를 돌렸더니 전부 HOLD가 나왔다(교훈이 모든 이른 거래를 막았다). 이어 헤드리스 의사결정 루프를 더했다. 트리거가 실제 발동했을 때만 launchd 잡이 헤드리스 Claude를 깨우므로, 사고 반쪽도 무인으로 돌되 조용한 날엔 활동을 만들지 않는다.

감사에서 찾은 것과 수정

발견수정
영어화가 적중률 카운터를 조용히 파손; 303 테스트가 죽은 계약 위에서 통과구조적 fail-loud 파싱 + 실제 볼트 파일 회귀 테스트
잘못된 티커로 채점된 가짜 "승리"가 지표를 오염무효화 + 재채점; 진입은 검증된 종가에만 고정
문서는 없는 자동 승급을 약속; 샤프 기준 모호윌슨 하한 기반 졸업 구현(엣지가 실재해야)
워크포워드 실패는 버려짐 — 승자만 저장모든 버딕트 영속; 없는 티커 = 더 엄격한 기본값, 실매수 차단
교훈이 쓰기 전용; 루프가 닫히지 않음매일 다이제스트; 해당 교훈 인용을 코드로 강제

발견 — 정직한 보장

어떤 시스템도 수익을 보장할 수는 없다. 그건 테제에 엣지가 있느냐의 문제다. 이 루프가 보장하는 건 더 좁지만 더 중요하다. 모든 이음매가 닫혀 있고, 한 방향으로만 실패한다는 것이다. 모든 결과는 교훈이 되어야 하고, 모든 교훈은 다음 결정에 닿으며, 모든 지표는 워커가 시장 데이터로 계산한다(자기 보고가 아니다). 모든 설정은 만료된다. 어떤 입력을 속여도 결국 스스로 손해다. 환각한 진입가는 덮어쓰이고, 부풀린 확신은 상한에 걸리고, 버딕트로 막힌 종목은 거래되지 않는다. 실제로 존재하는 엣지가 무엇이든 졸업까지 정직하게 측정된다.

사고방식 — 활동보다 규율

시스템이 작동한다는 가장 분명한 신호는, 기준을 넘는 게 없을 때 시그널을 0개 낸다는 점이다. 트리거된 7종목의 첫 실전 리뷰에서는 7개 모두 HOLD가 나왔다. 코드화된 교훈이 그럴듯하지만 이른 거래를 전부 막았고, '불(bull)' 에이전트조차 미확인 돌파를 앞질러 사길 거부했다. 바빠 보이려 일을 벌이는 건 오히려 실패에 가깝다. 근거를 갖고 신중하게 기다리는 것, 그게 이 시스템이 내놓아야 할 결과다.

2단계 — 함께 산 6주

  1. 7 · 운영, 그리고 진짜 벽

    무인으로 돌리자 정직한 병목이 드러났다. 트리거가 걸리는 종목은 거의 다 버딕트로 막혀 있어서, 루프는 날마다 규율 있는 HOLD만 내놓고 표본은 거의 안 늘었다. '작동한다'는 건 '정확히 거절한다'는 뜻이었지 '전진한다'는 뜻이 아니었다. 그 차이를 소리 내어 이름 붙이는 게 어떤 기능보다 유용했다.

  2. 8 · 재검증, 그리고 답을 받아들이기

    당연한 해법은 거래 가능한 종목을 넓히는 것이라, 모든 단일 종목과 새 크로스에셋 후보 12개에 워크포워드를 새로 돌렸다. 두 번 다 답은 같았다. 아무것도 풀리지 않는다. 기계적 전략은 단일 주식에서 비용을 빼면 엣지가 없다. 결과와 싸우는 대신 그대로 받아들였다. 백테스트는 엣지의 원천이 아니라 안전 필터임이 확인됐다. 진짜 베팅은 추론이고, 그건 적중률로 따로 측정된다.

  3. 9 · 코드가 아니라 실험을 견고화

    졸업 로직에 논리적 허점이 없냐는 질문에 직접 찾아봤더니 여럿 있었다. 측정이 아니라 실험을 둘러싼 의사결정 이론 쪽이었다. 실패 출구가 없었고, 적중률만이 유일한 엣지 지표였고, 일회성 통계 경계를 매일 훔쳐보고 있었다. 양수 손익 기준(자주 맞아도 돈 잃는 프로세스는 졸업 불가), 확정 창(기준이 3건 더 유지돼야 함 — 한 번의 운을 무력화), 무용성 정지(낙관적 경계로도 못 넘으면 설계를 기각 선언)를 더했다. 모든 수정이 승급을 더 어렵게 만든다, 결코 쉽게가 아니라.

  4. 10 · 노트북과의 탯줄 끊기

    루프는 여전히 내 맥이 깨어 있어야 돌았다. 측정 반쪽을 스케줄된 클라우드 러너로, 사고 반쪽을 클라우드 루틴으로 옮겨, 노트북을 닫아도 아침 사이클이 돈다. 클라우드 스케줄러가 이틀 연속 조용히 누락하자, 아침 하트비트가 안 오면 소리치는 것만이 유일한 임무인 독립 머신에 데드맨 스위치를 달았다. 감시 대상과 운명을 공유하는 감시자는 감시자가 아니니까.

  5. 11 · 버그를 배포하고, 시스템에 붙잡히다

    루프가 안 바뀐 셋업을 반복 토론하지 않도록 스킵 규칙을 더했는데, 루틴의 다른 지시와의 우선순위를 모호하게 둔 채 배포했다. 트리거 12개가 걸린 아침에 결정을 조용히 0개 냈다. 하트비트는 '결정 루프가 곧 평가한다'고 약속했지만 지켜지지 않았고, 지켜보던 사람이 그 공백을 알아채고 물었다. 스킵을 정지가 아니라 명시적이고 커밋되는 1급 결과로 만들어 고쳤다. 교훈은 버그 자체가 아니라, 내가 만든 관측성이 조용한 실패를 하루 만에 보이는 실패로 바꿔줬다는 것이었다.

사고방식 — 안 더하는 규율

시스템을 운영하다 보니 인기 도구를 갖다 붙이고 싶은 유혹이 꾸준했다. 에이전트 프레임워크, 워크플로 오케스트레이터, LLM 관측 플랫폼. 하나같이 거의 맞다가 안 맞았다. 내가 소유하지 않은 API 호출을 계측하거나, 이미 git으로 버전 관리하는 위키의 상태를 다시 만들거나, 독립돼야 할 감시자를 감시 대상 안으로 되접어 넣었다. 그래서 각각에 대해 '나중에 채택을 정당화할 정확한 이벤트'를 적어두고, 지금은 아무것도 채택하지 않았다. 이 시스템의 신뢰성은 지루한 부품 — cron, git, REST, 플랫 파일 — 에서 나오고, 복잡도는 비용이지 기능이 아니다. 절제가 더 어려운 엔지니어링 결정이었다.

$

근거 · 깃·위키 인용

  • 위키 · 자기개선 루프 감사 (Q&A) · quant-ai-lab-wiki/00-System/references/q-and-a/2026-06-11-self-improvement-loop-audit.md
  • 커밋 da0672a · 스테이지게이트 파싱 재고정 · git:da0672a
  • 커밋 6aa5b7b · 승급 머신러리(윌슨 하한) · git:6aa5b7b
  • 커밋 01b6b72 · 버딕트 레이어 fail-closed · git:01b6b72
  • 커밋 a41dc09 · 재귀 이음매(다이제스트·인테이크 스탬핑) · git:a41dc09
  • 커밋 28dd7c8 · 의사결정 반쪽 자율화(헤드리스 루프) · git:28dd7c8
  • 커밋 4da8c8e · 졸업 로직 강화(손익·확정 창·무용성 정지) · git:4da8c8e
  • 커밋 68e909a · 맥 독립 클라우드 이전(Actions+루틴) · git:68e909a
  • 커밋 5d018dd · 2차 유니버스 확장 — 후보 12개, 해제 0 · git:5d018dd
  • 커밋 29775f3 · 배포 버그 수정(스킵을 1급 결과로) · git:29775f3
  • 위키 · 리스크 상향은 왜 사람 몫인가 (Q&A) · quant-ai-lab-wiki/00-System/references/q-and-a/2026-07-04-why-risk-increases-stay-human.md
  • 위키 · 레슨 다이제스트(재귀 이음매) · quant-ai-lab-wiki/00-System/lessons-digest.md