所有研究
AutoClaw
Agent 评测 / 成本

我们做了一个大模型炒股排行榜,然后重跑了 18 次,把它拆了

四个模型、各 $50,000、130 个交易日。一个 8B 模型以 +72.6% 夺冠,领先第二名 71 个百分点。随后我们让每个模型在同样的日子里各重跑五次:每个模型自身的波动幅度(13–19 个百分点)竟是模型之间差距(7 个百分点)的两倍。排行榜是噪声。唯一可复现的差异是成本——最贵的模型每次决策要贵 121 倍。

研究实验,全程虚拟撮合。没有真实券商、没有真实下单,非投资建议。但推理费用是真实支出——总计 $33.14。

实验设置

四个 Amazon Bedrock 上的模型,各自管理 $50,000 虚拟本金,每个交易日做一次收盘决策,按历史收盘价撮合,区间为 2026-01-02 至 2026-07-10,共 130 个交易日。相同的中性提示词、相同的 16 支股票池、相同的工具(查行情、看持仓、买入、卖出、写日志)。网络搜索关闭,确保没有模型能读到未来的新闻。

我们想回答的,是所有做 Agent 的团队迟早会问的问题:为更强的模型多付钱,能换来更好的决策吗?

我们差点发布的那个排行榜

模型厂商期末净值收益成交每次决策成本
llama-8bMeta$86,289+72.6%3 笔$0.00036
nova-liteAmazon$56,562+13.1%7 笔$0.00041
claude-haikuAnthropic$53,855+7.7%29 笔$0.00706
sonnet-4-6Anthropic$50,767+1.5%46 笔$0.04402

一个 8B 模型,只交易了 3 次,把交易了 46 次的前沿模型甩开 71 个百分点。交易频率与收益几乎完全负相关。这是一个绝佳的头条,而且它长得很像一个真正的洞见。

我们不相信它。采样温度是 0.7,这里没有任何东西是确定的。而 llama-8b 跑完整的 130 天只要 $0.04。没有任何理由不去验证。

于是我们把每个模型都重跑了五次

同样的 130 天,同样的提示词。额外 18 次完整回测。

模型头条那次五次重跑重跑均值自身波动幅度
llama-8b+72.6%+10.8 / +8.0 / +18.9 / +16.6 / +5.9+12.0%13.0 pp
nova-lite+13.1%+3.7 / +9.3 / +1.8 / +13.4 / −0.1+5.6%13.5 pp
claude-haiku+7.7%+9.4 / +14.8 / +1.0 / +11.3 / +8.8+9.0%13.8 pp
sonnet-4-6+1.5%−3.0 / +15.6 / +2.2 (n=3)+5.0%18.6 pp

请把最后两列放在一起读,因为这就是整篇文章的全部:

  • 四个模型的均值全部落在 +5.0% 到 +12.0% 之间——彼此相差 7 个百分点
  • 而每个模型自己重跑一遍的波动幅度,是 13 到 19 个百分点

一个模型和它自己重跑的差距,约等于模型之间差距的两倍。 在收益这个维度上,这四个模型根本无法区分。我们排行榜上那个 71 个百分点的鸿沟是噪声,而我们距离把它当作研究发现推出去,只差一次部署。

llama-8b 的五次重跑,没有任何一次接近 +72.6%,最高也只有 +18.9%。它的典型水平是 +12.0%——与表格里其他所有模型统计意义上打平。

头条那一次,在每个维度上都不典型

有了分布之后我们才发现,我们恰好截图的那一次运行,不只是收益异常,行为也异常

模型头条那次的成交重跑的成交
llama-8b3 笔2 / 3 / 3 / 4 / 3
nova-lite7 笔28 / 46 / 46 / 43 / 43
claude-haiku29 笔5 / 3 / 12 / 4 / 17
sonnet-4-646 笔47 / 34 / 29

nova-lite 平时交易 2846 次,头条那次只交易了 7 次。claude-haiku 平时交易 317 次,头条那次交易了 29 次。我们基于「交易频率与收益负相关」讲了一个故事,而那次运行里,四个模型有两个的行为完全不像它们平时的样子。

这不是运气不好。这就是「样本量为 1」的真实模样。

那么,什么活了下来

两件事。它们是这篇文章里我们唯一愿意为之辩护的结论。

1. 收益不可复现,但行为可复现。 llama-8b 在每一次运行中都只交易 2~4 笔。它稳定地在早期下几注,然后一动不动——这是模型真实、稳定的性格。但它买什么,以及因此赚多少,是抛硬币。(需要说清楚:极少交易不是缺陷。在这个窗口里,什么都不做恰恰是最好的策略。我们要说的是,它的收益告诉你的是 NVDA 的走势,而不是 Meta 的模型。)

2. 成本是确定的。 它完全不在乎行情往哪边走:

sonnet-4-6 每次决策的成本是 llama-8b 的 121 倍——$0.04402 对 $0.00036。

这是结果表里唯一一个「看起来是什么意思、就真的是那个意思」的数字。把它和上面的收益分布放在一起,就得到了我们真正敢于站在后面的那个结论:

你多付了 121 倍的钱,买到的是同一个分布里的另一次抽样。

这不是在反对前沿模型。这是在反对「假设溢价一定能在这个任务上换来东西」,并主张去测量,而不是去假设。换一个需要真正推理深度的任务,答案很可能反过来——但它不会免费反过来,而且你不去看就永远不会知道。

由此得到的一条规则

如果你用单次运行的结果去给 LLM Agent 排名——无论是我们的还是任何人的——你排的是运气。修复方法并不高深:重跑几次,看看离散度。 如果单个模型内部的波动,比模型之间的差距还大,那你手上就没有排名。你手上是噪声,只不过在上面画了一个排行榜。

两个早已停止工作的 Agent

这次实验里最昂贵的发现,不在收益表里。

一个编造了六个月交易记录的模型

更早一轮模拟里包含 mistral-small-2402。它从 1 月运行到 5 月,执行了零笔交易。净值:每一天都精确地停在 $50,000。现金:$50,000。持仓:无。

它看起来像一个极度保守的策略。但它根本不是策略。这个模型无法发出工具调用,而它的日志显示了三种层层递进的失败形态:

它用散文描述自己正在调用工具:

I begin by reviewing my current portfolio using the "get_portfolio" tool...

它把工具调用的 JSON 当作普通文本写了出来:

{"name": "read_journal", "arguments": {"entry": "Reviewed portfolio and quotes. Decided to hold positions."}}

它清楚地知道一个工具调用长什么样。它只是把它打字打了出来,而没有返回真正的 toolUse 结构——于是 stopReason 永远不会是 tool_use,我们的 runTool() 永远不会被触发,订单永远不会成交。

而且它编造了从未发生的交易,用的还是真实存在的股票:

Bought 100 shares of AMZN based on strong momentum... Found positive news on AMD, bought 100 shares at market price.

AMZN 和 AMD 都在我们的股票池里。只扫一眼日志,这些记录看起来完全合理。但成交记录是零笔,持仓为空,现金分毫未动。

这不是一个关于 Mistral 的故事。mistral-small-2402 是 2024 年 2 月的快照,早于可靠的 function calling 出现;Mistral 后续的模型是支持的。这是一个关于 Agent 可以死得多么安静、而你的监控面板对此又多么无话可说的故事。

是我们自己的代码在掩护它

Bedrock 封装层捕获了模型错误,然后把它当作正常输出返回:

} catch (e) {
  return { finalText: `[${spec.id}] model error: ${e.message}`, ... };
}

一个根本调不通的模型,和一个今天决定不交易的模型,产出的数据完全一样:零成交、净值不变。没有任何可供告警的信号。于是模拟愉快地跑了几个月,一个早已死去的 Agent 的推理账单,每个月都和其他账单一起如期而至。

然后 fail-fast 又抓出了第二个

在我们把「调用失败」改成抛异常之后,一次重跑在第 17 天崩溃了:

ModelCallFailed: [sonnet-4-6] The content field in the Message object
at messages.8 is empty.

这是一个真实的 bug,出在我们的循环里,而不是模型身上:当 sonnet-4-6 在推理中途被 maxTokens 截断时,它会返回一条不含任何内容块的助手消息。我们把这条空消息原样塞回了对话历史,于是 Bedrock 在下一次调用时判定消息非法,直接 400。

而在旧的「错误吞噬」代码下,这个 400 会被捕获、当作文本写进日志。这意味着在此前的每一轮回测中,sonnet-4-6 几乎必然在某些天悄无声息地什么都没做——而我们永远不会知道。mistral-small-2402 同一个病因,只是症状不同。

两次静默失败,同一个根因:我们在自己的数据里,把「调用失败」和「Agent 选择不行动」变成了同一个东西。

我们做了哪些修改

1. 花钱之前先体检。 开跑前用一次 1-token 调用探测每个模型,任何一个调不通就拒绝启动。几乎不花钱,而它本可以在第零天就拦下整起事故。

2. 失败必须立即中断并报错。 现在调用失败会抛出 ModelCallFailed 并终止运行。「调用失败」和「Agent 决定持有」,绝不能在数据里长成同一行。

3. 给工具循环加护栏。 绝不把空内容的消息塞回对话历史。

4. 按 Agent 分别记账。 我们的预算追踪器只记录了一个总数。我们能告诉你这次实验花了 $8.07,却答不出这笔钱是被哪个模型花掉的——而那恰恰是整个实验唯一要问的问题。更讽刺的是,doCheckin() 一直在计算分模型成本,只是被随手丢弃了。

请注意 preflight 拦不住什么:mistral-small-2402 能通过它。这个模型调得通的,它只是不会行动。HTTP 200 不能证明 agentic 能力。 如果你需要模型使用工具,你的检查必须断言「返回了一个真正的工具调用结构」,而不仅仅是「API 有响应」。

这一切花了多少钱

我们认为这个价签很重要,因为对「评测一定要重跑」最常见的反驳就是:听起来很贵。

花费
头条那一轮(4 模型 × 130 天)$8.07
每次决策成本的校准跑$1.20
重跑 llama-8b × 5$0.19
重跑 nova-lite × 5$0.27
重跑 claude-haiku × 5$4.40
重跑 sonnet-4-6 × 3$17.75
失败与废弃的运行约 $1.30
Bedrock 总花费$33.14

把两个真正重要的数字并排放在一起:

产出那个错误的头条,花了 $8.07。推翻它,花了 $0.19。

不存在任何一种预算水平,能让「跳过重复实验」成为理性选择。

但请注意这里的不对称,因为这是一项没有任何厂商会写进价目表的、前沿模型的真实成本:推翻一个关于 llama-8b 的错误结论只要 1 毛 9;推翻一个关于 sonnet-4-6 的错误结论要 $17.75。 模型越贵,用同样的证据标准去检验它就越贵——于是「跑一次就发布」的诱惑也就越大。

(一处必须坦白的缺口:sonnet-4-6 是 n=3,不是 n=5。一次 AWS 会话过期加上预算断路器把运行截断了,而为剩下两次再花 $12 我们认为不值——它的波动幅度已经是四个里最大的。其余每个模型都是 n=5。)

可以带走的结论

  • 绝不要用单次运行给 Agent 排名。 如果单个模型内部的离散度超过了模型之间的差距,那就没有排名可言。重跑几次——离散度本身就是结果
  • 不要靠价目表或排行榜来选 Agent 模型。 用一次真实的工具调用去验证它确实会行动。流畅和有能力是两回事,而这个差距从外面完全看不出来。
  • 更贵的模型不会自动成为更好的 Agent。 在这个任务里,121 倍的单次决策成本买到的是更多的操作、并不更高的收益,以及更大的方差。请在你自己的任务上测量它,而不是假设它。
  • 从第一天就按 Agent 分别记录成本。 一个总额,回答不了你真正会问的那个唯一的问题。
  • 静默失败是 Agent 的默认失败方式。 服务崩溃会把你叫醒;而一个安静地什么都不做的 Agent,看起来和一个谨慎行事的 Agent 一模一样——而且无论哪种,它都照常向你收费。

这个模拟仍在运行,每个交易日决策一次。下方的排行榜会自动更新。现在,你知道它值多少了。

数据是活的,自己去看

这项实验每个交易日仍在自动运行,排行榜实时更新。

打开实时排行榜