읽는 데 약 7분
AI한테 내 돈을 맡겨도 될까?
자동매매를 만들며 주문 버튼만은 안 준 이유

주식 자동매매 프로그램을 혼자 만들고 있습니다. 뉴스와 공시가 뜨면 AI가 읽고 “이건 호재다, 오래 갈 재료다”를 판단하고, 조건이 맞으면 사고팝니다.

만들면서 가장 오래 고민한 질문은 하나였습니다. AI한테 주문 버튼까지 줘도 될까? 결론은 “안 준다”였습니다. AI는 판단하고 제안까지만 합니다. 돈이 실제로 나가는 길은 미리 정한 규칙대로만 움직이는 코드가 지킵니다.

먼저 밝혀 둘 것이 있습니다. 이 프로그램은 아직 실제 돈으로 거래하지 않았습니다. 10월 12일에 처음 켜고, 11월에 증권사 모의투자로 2주를 돌린 뒤 실전 여부를 정합니다. 그래서 이 글은 “써 보니 안전했다”가 아니라 “맡기지 않도록 이렇게 설계했다”는 기록입니다.

10월 9일 덧붙임: 일정을 3주 앞당겼습니다. 10월 12일 주에 증권사 모의서버로 리허설을 하고, 10월 19일부터 모의투자 2주를 돌립니다.

비유로 보면: 애널리스트와 회계팀#

회사에 비유하면 이렇습니다.

  • 애널리스트(AI): 뉴스를 읽고 의견을 냅니다. “이 공시는 호재일 확률 80%” 같은 식입니다. 의견은 내지만 회사 통장에는 손을 못 댑니다.
  • 회계팀(코드): 정해진 규정대로만 돈을 움직입니다. 애널리스트가 아무리 확신해도 한도를 넘는 지출은 결재하지 않습니다.
  • 팀장(AI): 하루가 끝나면 성적표를 보고 “내일은 이 전략 비중을 줄이자”고 제안합니다. 다만 규정집 자체는 고칠 수 없고, 제안도 정해진 범위 안에서만 받아들여집니다.
  • 사장(나): 규정집을 바꿀 수 있는 사람은 한 명뿐입니다.

AI가 두 자리에 앉아 있지만 둘 다 통장 비밀번호를 모릅니다. 이 구조가 글 전체의 요지입니다.

AI가 할 수 없게 막은 것#

1. 주문을 직접 내는 것#

AI 판단기는 숫자 몇 개만 돌려줍니다. 호재일 확률, 재료가 오래 갈 확률, 기사가 이 종목과 관련 있을 확률, 찌라시일 확률입니다. 이 숫자가 높아도 주문은 바로 나가지 않습니다. 코드가 정한 진입 조건을 통과하고, 그다음 리스크 검사까지 통과해야 주문이 나갑니다.

AI가 멈추면 새로 사는 것만 멈춥니다. 이미 산 종목의 손절과 익절은 코드가 계속 처리합니다.

2. 얼마나 살지 정하는 것#

가격, 등락률, 수량, 날짜 계산은 전부 코드가 합니다. 언어 모델은 계산을 틀리기 쉽고, 틀려도 그럴듯하게 틀리기 때문입니다. AI에게는 “이 뉴스가 무슨 뜻인가”만 묻습니다.

3. 손실 한도를 바꾸는 것#

손실 한도는 코드에 고정해 두었습니다.

  • 한 종목이 3% 떨어지면 바로 팝니다.
  • 하루에 계좌가 3% 줄면 그날은 새로 사지 않습니다.
  • 한 주에 7% 줄면 매매를 멈춥니다.
  • 15% 줄면 전부 멈추고, 제가 직접 풀기 전까지 다시 켜지지 않습니다.
  • 한 종목에 계좌의 40%를 넘게 넣지 않고, 동시에 3종목까지만 들고 있습니다.

팀장 AI는 매일 전략의 목표 수익이나 손절 폭을 조정할 수 있습니다. 하지만 위 한도보다 느슨하게는 못 바꿉니다. 전략이 손절을 5%로 잡아도 실제로는 더 촘촘한 3%가 적용됩니다. 허용 범위를 벗어난 제안은 거부되고, 리포트에 “거부됨”으로 남습니다.

4. 열쇠를 보는 것#

증권사 API 키, 공시 API 키, 알림용 주소 같은 비밀값은 AI가 도는 환경에서 아예 지운 채로 AI를 실행합니다. AI에게 넘기는 자료에도 넣지 않습니다. 보여 주지 않으면 실수로 흘릴 일도 없습니다.

5. 기사 속 “강력 매수”에 넘어가는 것#

뉴스에는 “지금 사야 할 종목” 같은 홍보성 문구가 섞여 있습니다. AI는 이런 문장을 읽고 판단이 흔들릴 수 있습니다. 그래서 “이 기사는 찌라시인가”를 따로 묻고, 그 확률이 높으면 다른 점수가 아무리 좋아도 사지 않습니다.

그래도 AI가 틀린 순간들#

막아 두었는데도 개발하는 동안 AI가 틀린 장면을 여러 번 봤습니다.

“4조원”이 “$4 Billion”이 됐습니다. 판단 모델이 영어로 읽을 때 더 정확해서 한국어 뉴스를 먼저 영어로 번역합니다. 그런데 번역 AI가 원화 금액을 달러로 바꿔 버렸습니다. 4조원은 약 30억 달러이니 규모가 엉뚱해집니다. 판단기는 번역문만 보기 때문에 아무도 모른 채 틀린 판단이 나올 수 있었습니다. 번역 지시에 “원화는 원 단위 그대로 두고 달러로 바꾸지 말라”를 넣어 고쳤습니다.

관련성 점수가 엉터리였습니다. “이 기사가 이 종목 이야기인가”를 01로 물었더니, 멀쩡한 기사에도 0.030.2가 나왔습니다. 질문 문구를 조금 바꾸면 점수가 크게 출렁였습니다. 기준을 0.7로 두면 거의 아무것도 사지 못합니다. 기준을 0.3으로 낮추고, 실제 기사 50건에 직접 정답을 붙여 다시 맞춰 보기로 했습니다. AI가 내는 점수는 믿는 숫자가 아니라 검증할 숫자라는 걸 여기서 배웠습니다.

AI가 읽으면 안 되는 파일을 읽을 수 있었습니다. 팀장 AI가 새 전략 코드를 쓰는 기능이 있습니다. 이때 AI가 수집한 뉴스 원문 기록과 로그인 토큰 파일까지 읽을 수 있다는 걸 뒤늦게 발견했습니다. 증권사 뉴스는 약관상 제3자에게 넘길 수 없는 자료라 문제가 됩니다. 해당 폴더를 읽기 금지 목록에 넣어 막았습니다.

약관 때문에 뉴스 출처를 뺐습니다. 처음에는 포털 뉴스 검색 API를 쓰려 했습니다. 약관을 읽어 보니 AI 입력과 저장을 금지하는 조항이 있었습니다. 그래서 공시(DART)와 증권사 뉴스 제목만 남겼습니다. AI에게 무엇을 보여 줄지는 보안 문제이기도 하지만 약관 문제이기도 했습니다.

돌아보면 주문 쪽 코드에서 고친 버그가 AI 쪽보다 더 많았습니다. 주문 응답이 사라졌을 때 같은 주문이 두 번 나가지 않게 하는 처리 같은 것들입니다. 규칙 기반 코드라고 저절로 안전해지지는 않습니다. 다만 규칙 코드는 테스트로 확인할 수 있고, 틀린 걸 찾으면 같은 방식으로 다시 틀리지 않습니다.

개발자용: 구조#

여기부터는 설계 이야기입니다.

자동매매 구조: AI는 판단과 제안까지, 주문은 코드만

흐름#

  1. 수집: DART 공시와 증권사(한국투자증권 KIS Open API) 뉴스 제목을 주기적으로 가져와 중복을 지우고 종목 코드를 붙입니다.
  2. 판단기: 한국어 기사를 로컬 LLM(Ollama, qwen3:8b)으로 영어로 번역한 뒤, 로컬 판단 모델(Laya)에 질문 묶음을 한 번에 던집니다. 질문은 방향, 지속성, 관련성, 찌라시 네 가지입니다. 재료의 강도는 AI에게 묻지 않고 규칙으로 정합니다(공시 3, 실적·계약 키워드 기사 2, 그 밖의 기사 1). 시험해 보니 AI가 매긴 강도는 기사마다 거의 같아서 변별력이 없었습니다.
  3. 전략 엔진: 전략마다 YAML로 진입 조건, 수량, 청산 규칙을 정의합니다. 판단기를 쓰지 않는 대조군 전략도 하나 같이 돌려서, AI 판단이 실제로 도움이 되는지 비교합니다.
  4. 리스크 게이트: 진입 직전에 한도를 검사합니다. 한도표는 변경 불가 dataclass로 두었고, 이 경로의 코드는 AI가 자동으로 고칠 수 없게 “보호 경로”로 지정했습니다.
  5. 주문: 멱등 키로 중복 주문을 막고, 응답이 유실된 주문은 다시 내지 않고 체결 조회로 확인합니다. 장부와 증권사 잔고가 다르면 증권사 잔고를 기준으로 맞춥니다.
  6. 장부와 리포트: 전략별 가상 장부에 비용을 뺀 손익을 기록하고, 장 마감 후 메일로 리포트를 보냅니다. 경고는 디스코드로 옵니다.
  7. 매니저: 장 마감 후 Claude Code를 헤드리스(claude -p)로 실행해 리포트를 읽히고, 전략 파라미터 변경안을 JSON 스키마로 받습니다. 엔진과는 파일과 DB로만 연결되어 있어서 Claude가 응답하지 않아도 매매는 계속됩니다.

모르면 멈춘다 (fail-closed)#

애매할 때 어느 쪽으로 넘어질지를 정해 두었습니다.

  • 기준 자산을 모르면 비상 정지로 취급합니다.
  • 평균 매입가를 모르면 들고 있지 않고 청산 쪽으로 갑니다.
  • data/HALT 파일이 있으면 전부 멈추고, 사람이 해제 명령을 실행해야 다시 돕니다.
  • 금지 종목 목록은 제가 파일로 쓰고, 엔진이 60초마다 다시 읽습니다.

리플레이: 수익이 아니라 안전을 보는 시험#

증권사 조회 응답을 날짜별로 그대로 기록해 두고, 그 하루를 다시 재생할 수 있게 했습니다. 시계는 기다리지 않고 바로 다음 시각으로 넘어가고, 판단기는 저장된 응답을 다시 씁니다.

이 재생의 합격 기준은 수익이 아닙니다.

  • 예외 없이 끝까지 돌아야 합니다.
  • 한도를 넘는 주문이 0건이어야 합니다. 체결마다 한도표와 다시 대조합니다.
  • 장부 합계가 맞아야 합니다.

AI가 쓴 코드를 받아들이는 관문#

매니저 Claude는 새 종목 감지 로직을 코드로 제안할 수 있습니다. 이 코드는 사람 검토 없이 반영되지만, 기계 관문을 차례로 통과해야 합니다.

  1. 별도 git worktree에서 Claude가 작성합니다. 쓸 수 있는 파일은 플러그인 파일, 그 테스트, 전략 YAML뿐입니다. 셸은 pytest 한 줄만 허용하고, 커밋은 Claude가 아니라 빌더 코드가 합니다.
  2. AST 정적 검사로 허용 목록 밖의 import, open, exec, eval, getattr, 이중 밑줄 접근을 거부합니다.
  3. 전체 테스트를 돌립니다.
  4. 리플레이를 통과해야 main에 병합되고, 디스코드로 알림이 옵니다.

AI가 고칠 수 있는 범위는 “종목을 찾아내는 로직”으로 한정했습니다. 판단, 진입, 청산, 수량, 리스크는 기존 부품을 YAML로 조립하는 것만 허용합니다.

솔직히 적어 둘 한계가 있습니다. 정적 검사는 우회 방법이 나올 때마다 막았습니다(별칭 import, while, del, BaseException 등). 그래도 이건 샌드박스가 아닙니다. 무한 루프나 아주 큰 range 같은 건 정적 검사로 못 막습니다. 그래서 문서에도 “격리가 아니라 매니저 AI의 실수를 막는 장치”라고 적어 두었습니다. 대신 실행 중에 플러그인 호출이 2초를 넘기거나 예외가 나면, 그날 그 전략의 신규 진입을 끕니다.

다음 글#

10월 12일 주에 리허설을 하고, 10월 19일부터 모의투자 2주를 돌립니다(처음 이 글을 쓸 때는 11월이었는데 3주 앞당겼습니다). 다음 글에서는 AI 판단이 실제로 대조군보다 나았는지, 리스크 게이트가 몇 번 막았는지를 숫자로 정리하겠습니다.

AI한테 내 돈을 맡겨도 될까?
https://leean.dev/posts/ai-trading-no-order-permission/
저자
leean
게시일
2026-10-09
라이선스
CC BY-NC-SA 4.0