Vibe Trading에 대한 고민: 언제 AI를 써야 하고, 언제 쓰지 말아야 하는가.
최근 Vibe Trading이라는 개념이 주목받고 있습니다. 자연어로 거래 의도를 설명하면 AI가 대신 실행해주는 방식입니다. "보수적 전략, 변동성 낮은 자산 우선"이라고 말하면 AI가 자동으로 포트폴리오를 구성해줍니다. 듣기에는 매력적입니다.
하지만 Vibe Trading에 대해 이야기하기 전에, 최근 있었던 한 가지 사례를 먼저 소개하고 싶습니다. 이 사례는 어떤 이론보다도 "AI를 어디에 써야 하는지"를 더 잘 설명해줍니다.
3월 31일, Anthropic의 Claude Code가 npm 업데이트 과정에서 실수로 소스 코드를 노출했습니다. 약 512,000줄의 TypeScript(참고: 이는 패키징된 전체 코드 양으로, 의존성 및 생성 코드를 포함합니다). 커뮤니티의 리버스 엔지니어링 분석이 빠르게 확산되었고, 전 세계 개발자들이 새로운 기능을 찾기 위해 코드를 뒤지기 시작했습니다.
하지만 제가 가장 놀랐던 발견은 AI와 전혀 관련이 없었습니다. 그 발견 자체는 거래와도 관련이 없었지만, 그 이면의 공학적 철학은 퀀트(계량적 거래)를 하는 사람들에게 공감을 줄 것입니다.
분석가가 userPromptKeywords라고 표시한 모듈에서, shit, wtf, fucking broken 같은 욕설을 감지하는 정규 표현식이 발견되었습니다. 이는 사용자가 화를 내는지 빠르게 판단하기 위한 것이었습니다.
세계 최고의 대규모 언어 모델(LLM) 회사가 정규 표현식을 사용해 감정을 감지하고 있었습니다.
Claude를 호출해 감정 분석을 하지 않았습니다. 분류기를 훈련시키지도 않았습니다. 마이크로초 단위로 실행되는 문자열 매칭이었습니다.
왜일까요?
1. 왜 Anthropic은 자체 AI를 사용하지 않았을까
이는 게으름의 결과가 아닙니다. 신중하게 내려진 엔지니어링 결정입니다.
Claude Code는 하루에 수십만 건의 사용자 상호작용을 처리합니다. 각 상호작용마다 "사용자가 좌절감을 표현했는지"를 판단하여 응답 전략을 조정해야 합니다. 만약 매번 LLM을 호출하여 이 판단을 내린다면:
- 지연 시간: LLM 추론 한 번에 최소 수백 밀리초, 정규 표현식 매칭은 몇 마이크로초
- 비용: LLM 호출은 토큰당 과금, 정규 표현식 매칭은 거의 무료
- 결정론: 정규 표현식은 매치되거나 되지 않거나, 결과가 100% 확정적; LLM의 출력은 확정적이지 않아 동일한 입력이 다른 판단을 낼 수 있음
따라서 Anthropic의 선택은: 정규 표현식으로 빠른 필터링(낮은 임계값, 빠른 속도, 강한 결정론)을 수행하고, LLM의 연산 능력은 진정한 의미 이해가 필요한 결정에만 사용하는 것.
이는 단순한 기술적 세부 사항이 아닙니다. 이는 아키텍처 철학입니다: 모든 문제가 AI로 해결할 가치가 있는 것은 아니다.
퀀트 거래를 하는 사람이라면 이 말에 특히 공감할 것입니다.
2. 퀀트 거래에서의 동일한 선택
여러분의 전략에는 두 가지 유형의 의사결정이 있습니다.
결정론적 의사결정 - "규칙"을 사용해야 하는 경우
FMZ에서 전략을 작성해본 사람이라면, 가장 핵심적인 거래 로직이 종종 몇 줄의 결정론적 코드로 구성된다는 것을 알고 있습니다.
javascript
// 이동평균선 교차 신호 — FMZ JavaScript 예시
var records = exchange.GetRecords(PERIOD_D1)
var ma5 = TA.MA(records, 5)
var ma20 = TA.MA(records, 20)
var idx = records.length - 1
// 골든크로스 매수
if (ma5[idx] > ma20[idx] && ma5[idx-1] <= ma20[idx-1]) {
exchange.SetDirection("buy")
exchange.Buy(records[idx].Close, 1)
Log("이동평균선 골든크로스, 매수")
}
조건이 명확하고, 결과가 확정적이며, 의미를 "이해"할 필요가 없습니다. if-else로 작성하면 100% 신뢰할 수 있고, 밀리초 단위로 실행됩니다.
Anthropic이 정규 표현식으로 감정을 감지한 것과 유사한 접근입니다. 결정론적 문제에는 결정론적 도구를 사용한다. 물론 정규 표현식은 문자열 매칭이고, 이동평균선은 수학적 계산이므로 도구는 다릅니다. 하지만 각 시스템에서 수행하는 역할은 유사합니다. 즉, AI 개입이 필요 없는 결정론적 판단입니다.
손절매는 if-else의 신뢰성이 100%이고, AI의 신뢰성은 '대부분'입니다. 여러분의 계좌는 그 작은 확률을 감당할 수 없습니다.
모호한 판단 의사결정 - AI를 사용해야 하는 경우
하지만 일부 의사결정은 if-else로 작성할 수 없습니다:
- 뉴스 감성 분석: 연준 성명이 나왔습니다. 매파적(긴축)인가요, 비둘기파적(완화)인가요? "현재 금리 수준을 유지하지만, 위원회는 데이터 변화를 면밀히 주시할 것" — 이 문장은 호재인가요 악재인가요? 이동평균선은 알려주지 않고, 정규 표현식도 이 판단을 할 수 없습니다.
- 이상 탐지: 어떤 알트코인의 소셜 미디어 언급량이 3시간 만에 800% 급증했지만, 가격은 아직 움직이지 않았습니다. 이는 '스마트 머니가 포지션을 구축 중'인가요, 아니면 '누군가 랠리 전에 분위기를 조성하는' 것인가요? 다차원 정보를 결합한 모호한 판단이 필요합니다.
- 전략 생성: "요즘 이런 패턴 다음에는 종종 급등이 나온다"는 직감이 있습니다. 하지만 구체적인 조건을 설명할 수 없습니다. 이 직감을 LLM에 설명하여 백테스트 가능한 퀀트 팩터로 변환하도록 할 수 있습니다.
이러한 시나리오의 공통점: 입력이 비정형적이고, 판단 기준이 모호하며, '매칭'이 아닌 '이해'가 필요합니다.
3. 참고할 수 있는 계층적 접근 방식
Claude Code의 아키텍처로 돌아가 보겠습니다. 커뮤니티 분석은 명확한 계층 구조를 보여주었습니다.
| 계층 | Claude Code의 메커니즘 | 퀀트 거래의 대응 |
|---|---|---|
| 빠른 필터링 계층 | 정규 표현식, 키워드 매칭 | 이동평균선 교차, 임계값 손절매, 포지션 제한 |
| 엔지니어링 인프라 계층 | 프로세스 관리, 메시징, 권한 제어 | 거래소 API, 주문 관리, 리스크 관리 엔진 |
| 의미 기반 의사결정 계층 | LLM 프롬프트 | 뉴스 감성 분석, 이상 패턴 인식, 전략 탐색 |
물론 Claude Code와 퀀트 거래는 완전히 다른 분야이므로, 여기서의 대응은 정확한 매핑이 아닙니다. 그러나 설계 철학에서의 공감대는 실제로 존재합니다. 각 계층에 가장 적합한 도구를 선택하고, 모든 문제를 해결하려고 하나의 망치만 사용하지 않는 것입니다.
오픈소스 커뮤니티도 유사한 접근 방식을 실천하고 있습니다. TradingAgents는 최근 주목할 만한 멀티 에이전트 퀀트 거래 프레임워크입니다(LangGraph 기반으로 구축되었으며, 관련 학술 논문도 있습니다). 이는 실제 트레이딩 회사의 팀 구조를 시뮬레이션합니다: 기술 분석가가 캔들 차트와 지표를 계산하고, 감성 분석가가 뉴스와 여론을 해석하며, 다양한 스타일의 트레이더가 여러 의견을 종합하여 최종 결정을 내립니다. 하나의 전능한 AI가 모든 것을 처리하는 것이 아니라, 각기 다른 역할이 각자의 임무를 수행합니다.
참고로 TradingAgents는 연구 프레임워크로, "AI가 어떻게 거래 결정을 내릴 것인가"라는 문제를 해결합니다. 하지만 실제 매매에서는 나머지 절반도 필요합니다: 거래소 연동, 주문 관리, 리스크 관리 실행, 로그 감사 등. 이러한 엔지니어링 인프라 작업은 다행히 FMZ와 같은 퀀트 플랫폼이 이미 처리해주고 있습니다.
4. Vibe Trading의 실제 구현: 계층형 아키텍처 예시
처음의 Vibe Trading으로 돌아가 보겠습니다. 방향은 맞지만, 전제는 계층이 명확해야 합니다.
오늘 BTC 이동평균선이 골든크로스가 났는데, 뉴스는 모두 규제 악재라고 가정해 봅시다. 어떻게 하시겠습니까? 순수하게 이동평균선만 보면 매수를 해야 하고, 뉴스만 들으면 움직이기 어렵습니다. 이것이 바로 계층화가 필요한 전형적인 시나리오입니다.
FMZ에서 간소화된 계층형 아키텍처는 다음과 같이 구현할 수 있습니다(참고: 아래는 간소화된 예시이며, 실제 매매 시에는 계약 설정과 리스크 관리를 직접 보완하시기 바랍니다):
javascript
/*
策略参数(在 FMZ 策略编辑页面的"参数"栏中添加):
OPENROUTER_API_KEY : string类型,填入你的 OpenRouter API Key
AI_MODEL : string类型,默认值 "google/gemini-2.5-flash",可换成其他模型
*/
// 语义决策层:通过 OpenRouter 调用 AI 获取市场情绪
function getAISentiment() {
var prompt = "分析当前加密货币市场新闻,给出情绪评分(-1到1,-1极度恐慌,1极度贪婪),只返回一个数字"
var response = HttpQuery("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
body: JSON.stringify({
model: AI_MODEL,
messages: [{role: "user", content: prompt}],
temperature: 0
}),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + OPENROUTER_API_KEY
},
timeout: 15000
})
var score = parseFloat(JSON.parse(response).choices[0].message.content)
// AI 返回异常时,回退到中性值——系统可靠性不依赖 AI 的每次正确输出
if (isNaN(score) || score < -1 || score > 1) {
Log("AI 返回格式异常,使用默认值 0")
score = 0
}
Log("AI 情绪评分:", score)
return score
}
function main() {
var lastSignalTime = 0 // 记录上次信号触发的K线时间,防止同一根K线重复触发
while (true) {
var records = exchange.GetRecords(PERIOD_D1)
if (!records || records.length < 20) { Sleep(1000); continue }
var ma5 = TA.MA(records, 5)
var ma20 = TA.MA(records, 20)
var idx = records.length - 1
var curTime = records[idx].Time
var isBullCross = ma5[idx] > ma20[idx] && ma5[idx-1] <= ma20[idx-1]
var isBearCross = ma5[idx] < ma20[idx] && ma5[idx-1] >= ma20[idx-1]
// 查持仓状态
var pos = exchange.GetPosition()
var hasPosition = pos && pos.length > 0
// 第一层:确定性信号做"门槛",金叉触发 + 无持仓 + 未在本根K线处理过,才去问 AI
if (isBullCross && !hasPosition && curTime !== lastSignalTime) {
lastSignalTime = curTime
var sentiment = getAISentiment()
// 第二层:AI 情绪做"参考",影响仓位但不独立触发交易
if (sentiment > 0.2) {
exchange.SetDirection("buy")
exchange.Buy(records[idx].Close, 1)
Log("金叉 + AI看多,全仓开")
} else if (sentiment > -0.3) {
exchange.SetDirection("buy")
exchange.Buy(records[idx].Close, 0.5)
Log("金叉 + AI中性,半仓开")
} else {
Log("金叉但 AI 看空,跳过本次信号")
}
}
// 死叉平仓:确定性规则,不经过 AI
if (isBearCross && hasPosition) {
exchange.SetDirection("closebuy")
exchange.Sell(records[idx].Close, pos[0].Amount)
Log("均线死叉,平仓")
}
// 第三层:止损是"铁律",不经过 AI
if (hasPosition) {
var curPrice = records[idx].Close
var entryPrice = pos[0].Price
if (curPrice < entryPrice * 0.97) { // 跌破开仓价 3%
exchange.SetDirection("closebuy")
exchange.Sell(curPrice, pos[0].Amount)
Log("止损触发,无条件平仓,亏损", ((curPrice/entryPrice - 1)*100).toFixed(2), "%")
}
}
Sleep(60 * 1000)
}
}
이 코드의 핵심 로직을 자세히 설명하자면 다음과 같다.
1. 이동평균선 골든크로스는 '문턱'이다. 확정적인 신호가 먼저 발생해야만 AI를 호출한다. 모든 캔들마다 대형 모델에 질의하지 않는다. 이는 비용을 절약하고(대형 모델 API는 토큰 기준 과금) 노이즈를 피하는 방법이다. 이는 Anthropic의 접근 방식과 일치한다. 정규 표현식으로 먼저 필터링하고, 일치하는 항목이 있을 때만 더 무거운 처리를 시작한다.
2. AI 감정은 '참고'이다. 포지션 크기와 신호 스킵 여부에 영향을 주지만, 독립적으로 거래를 트리거하지는 않는다. 코드에서 AI 반환값에 대한 예외 처리를 확인할 수 있다. 대형 모델이 해석 불가능한 내용을 반환하면 바로 중립값 0으로 대체한다. 시스템의 신뢰성은 AI의 매번 올바른 출력에 의존해서는 안 된다.
3. 손절매는 '철칙'이다. 진입가 대비 3% 하락 시 무조건 청산하며, AI의 의견을 묻지 않는다. AI가 '장기적으로 긍정적'이라고 말할 수 있지만, 계좌는 그 장기까지 버티지 못할 수 있다. 여기서는 가격 퍼센트 기반의 하드 손절매를 사용하며, 어떠한 모호한 판단도 거치지 않는다.
이것이 바로 Vibe Trading의 올바른 사용법이다. 자연어로 AI가 시장 분위기를 '감지'하도록 하고, 확정적인 코드로 거래 '실행'을 처리하도록 한다. 이 둘의 경계는 절대 흐릿해져서는 안 된다.
실전 조언: FMZ의 백테스팅 시스템에서 순수 이동평균선 전략을 먼저 베이스라인으로 실행하고, 그 위에 AI 감정 레이어를 추가하여 수익률과 최대 낙폭을 비교하라. AI를 추가했는데 오히려 성능이 나빠졌다면, 이는 계층화에 문제가 있음을 의미한다. AI가 개입해서는 안 될 부분에 개입한 것이다. AI가 반환한 결과는 매번 Log()로 기록해두면 사후에 각 결정을 분석하는 데 도움이 된다.
5. 한 마디로 정리
가장 진보된 AI 기업들이 정규 표현식을 사용해 감성을 감지하는 이유는 더 나은 AI를 만들 수 없어서가 아니다.
그 이유는 다음과 같다. 더 강력한 도구보다 적합한 도구를 선택하는 것이 더 중요하다는 것을 알기 때문이다.
이동평균선 전략은 화려하지 않고, 정규 표현식은 고급스럽지 않다. 그러나 그들의 영역에서는 어떤 AI보다도 신뢰할 수 있다.
반대로, 5000자 분량의 거시경제 보고서에서 '이 보고서가 BTC에 대해 낙관적인지 비관적인지'를 판단해야 할 때는 이동평균선도, 정규 표현식도 도움이 되지 않는다. 그것이 바로 AI가 투입되어야 할 순간이다.
'AI를 쓰느냐 마느냐'의 문제가 아니라, '어느 계층에서 사용하느냐'의 문제이다.
Claude Code 소스 코드 속 눈에 띄지 않는 정규 표현식 파일은 우리에게 자주 간과되는 질문에 대한 답을 제시한다. 그리고 FMZ는 이미 준비된 계층화 인프라를 제공한다. 거래소 인터페이스, 지표 계산, 실전 관리, 로그 감사 등이 모두 갖춰져 있어, 여러분은 다음 한 가지만 결정하면 된다. 어떤 결정을 TA.MA()에 맡기고, 어떤 결정을 AI에 맡길 것인지.
참고 출처:
- Alex Kim - Claude Code 소스 코드 유출 — 정규 표현식 좌절감 감지 분석
- FMZ - AI 기반 자동 거래 시스템 구축 — AI 두뇌 + FMZ 두 손 아키텍처
- TradingAgents - 다중 에이전트 LLM 금융 거래 프레임워크 — 다중 에이전트 퀀트 트레이딩 오픈소스 프레임워크
- TradingAgents 논문 — 다중 에이전트 금융 거래 프레임워크 학술 연구
- VentureBeat - Claude Code 소스 코드 유출
- 1


