[TOC]

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 这类脏话的正则表达式——用来快速判断用户是不是在骂人。
全世界最顶尖的大语言模型公司,用正则表达式来检测情绪。
不是调 Claude 来做情感分析。不是训一个分类器。是一个跑在微秒级的字符串匹配。
为什么?
这不是偷懒。这是一个深思熟虑的工程决策。
Claude Code 每天处理几十万次用户交互。每次交互都要判断”用户是否表达了挫败感”,以便调整响应策略。如果每次都调用 LLM 来做这个判断:
所以 Anthropic 的选择是:用正则做快速筛选(门槛低、速度快、确定性强),把 LLM 的算力留给真正需要语义理解的决策。
这不是个技术细节。这是一个架构哲学:不是所有问题都值得用 AI 解决。
做量化的人,应该对这句话特别有感。
你的策略里有两类决策:
在 FMZ 上写过策略的人都知道,最核心的交易逻辑往往就是几行确定性代码:
// 均线交叉信号 —— 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 的可靠性是”大概率”。你的账户承受不起那个小概率。
但有些决策不是 if-else 能写的:
这些场景的共同特点:输入是非结构化的,判断标准是模糊的,需要”理解”而不只是”匹配”。
回到 Claude Code 的架构。社区分析揭示了一个清晰的分层:
| 层级 | Claude Code 中的机制 | 量化交易中的对应 |
|---|---|---|
| 快速筛选层 | 正则表达式、关键词匹配 | 均线交叉、阈值止损、仓位限制 |
| 工程基建层 | 进程管理、消息传递、权限控制 | 交易所 API、订单管理、风控引擎 |
| 语义决策层 | LLM prompt | 新闻情绪分析、异常模式识别、策略探索 |
当然,Claude Code 和量化交易是两个完全不同的领域,这里的对应不是精确映射。但设计哲学上的共鸣是真实的——在每个层级选择最合适的工具,而不是一把锤子敲所有钉子。
开源社区也在实践类似的思路。TradingAgents 是最近一个值得关注的多 Agent 量化交易框架(基于 LangGraph 构建,有配套学术论文)。它模拟了真实交易公司的团队结构:技术分析师负责 K 线和指标计算,情绪分析师负责解读新闻舆情,不同风格的交易员综合各方意见做最终决策。不是一个全能 AI 包揽一切,而是不同角色各司其职。
值得注意的是,TradingAgents 是一个研究框架,它解决的是”AI 怎么做交易决策”的问题。但在实盘中,你还需要另一半:交易所对接、订单管理、风控执行、日志审计——这些工程基建的事,恰好是 FMZ 这类量化平台已经帮你做好的。
回到开头的 Vibe Trading。方向是对的,但前提是分层要清楚。
假设今天 BTC 均线金叉了,但新闻全是监管利空。你怎么办?纯看均线,该开多;纯听新闻,不敢动。这就是需要分层的典型场景。
在 FMZ 上,一个简化的分层架构可以这样实现(注:以下为简化示例,实盘请自行完善合约设置和风控):
/*
策略参数(在 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。不会每根 K 线都去问大模型——既省钱(大模型 API 按 token 计费),又避免噪音。这和 Anthropic 的思路一致:正则先过滤,匹配到了才启动更重的处理。
2. AI 情绪是”参考”。 它影响仓位大小和是否跳过信号,但不独立触发交易。注意代码里对 AI 返回值做了异常处理——如果大模型返回了不可解析的内容,直接回退到中性值 0。系统的可靠性不应该依赖于 AI 的每一次正确输出。
3. 止损是”铁律”。 跌破开仓价 3% 无条件平仓,不问 AI 的意见。AI 可能说”长期看好”,但你的账户等不到长期。这里用价格百分比做硬止损,不经过任何模糊判断。
这就是 Vibe Trading 的正确打开方式:用自然语言让 AI 帮你”感知”市场氛围,用确定性代码帮你”执行”交易动作。 两者的边界不能模糊。
实操建议:在 FMZ 的回测系统里,先跑一遍纯均线策略作为基准线,然后加上 AI 情绪层,对比收益和回撤。如果 AI 加进来反而变差了——说明分层有问题,可能 AI 在不该干预的地方干预了。每次 AI 返回的结果,用 Log() 记下来,方便事后复盘每一次决策。
最先进的 AI 公司用正则表达式检测情绪,不是因为它们造不出更好的 AI。
是因为它们知道:选对工具比选强工具更重要。
均线策略不性感,正则表达式不高级。但它们在自己的领域里,比任何 AI 都可靠。
反过来,当你需要从一份 5000 字的宏观研报里提取出”这篇对 BTC 是偏多还是偏空”的判断时——均线帮不了你,正则也帮不了你。这才是 AI 该上场的时候。
不是”用不用 AI”的问题,是”在哪一层用”的问题。
Claude Code 源码里那个不起眼的正则表达式文件,替我们回答了一个常被忽略的问题。而 FMZ 给你的,是一个现成的分层基建——交易所接口、指标计算、实盘管理、日志审计都帮你做好了,你只需要想清楚:哪些决策交给 TA.MA(),哪些决策交给 AI。
参考来源: - Alex Kim - The Claude Code Source Leak — 正则表达式挫败感检测分析 - FMZ - Building an AI-Powered Automated Trading System — AI 大脑 + FMZ 双手架构 - TradingAgents - Multi-Agents LLM Financial Trading Framework — 多 Agent 量化交易开源框架 - TradingAgents 论文 — 多 Agent 金融交易框架学术研究 - VentureBeat - Claude Code Source Code Leak