研究复盘,非投资建议。 文中数据用于说明审计与工程取舍,不代表未来收益或交易建议。
22 分钟,0 行代码,Sharpe 1.74。
听上去太美——所以我让它自己当内审,再查一遍。两个 bug 钉死,当场砍到 0.97,连基准都没跑赢。
1.74 是吹出来的,0.97 才是它的素颜。后来靠仓位管理把它抠回 1.04——离实盘还远,但起码不骗自己。
那 22 分钟,AI 自己跑通宵
我做的事情很简单:把一个量化研究的 SOP 拆成 6 个阶段,写进一份 plan.md,再把验收标准、禁忌项、工具链塞进 CLAUDE.md,按 enter,去倒了杯咖啡。
回来的时候 AI 已经把项目跑完了。15 支美股科技股,2017 到 2026 共 9 年的日频数据,4 层 AND 入场逻辑,T+15 持有 + ATR×3 追踪止损,527 笔交易,HTML 报告打开就能翻。
我没有写一行 Python。我也没有打开 IDE。
22 分钟里发生了 7 次”自修正”——这词听上去像 PR 文案,但其实是非常具体的事情:AI 跑到一半发现自己写的代码有 bug,自己定位、自己改、自己重跑。
不是我捕捉到的 bug,是 AI 自己捕捉到、自己治好的 bug。下面这张图是它的”病历本”——7 条都标了出在哪个 Phase、怎么治的:
第 3 条到第 5 条特别有意思——三个不同的”前视偏差”问题,AI 在向量化粗筛阶段一一识破。这种 bug 在量化里几乎是初学者标配,写出来的人甚至意识不到自己作弊了。AI 这个实习生不仅自己写代码,还自己当代码评审员。
这一阶段的产出是 6 个 git commit,每个 commit 对应一个 Phase 的完成节点。我可以从任何一个节点 reset 重跑,整个研究过程的版本历史完整。
传统量化研究的链路里,”写数据管道、算因子、回测、调参、出报告”是一个研究员 2 到 4 周的活。22 分钟这个数字本身已经够离谱——但它还不是这篇文章想讲的重点。
重点是第二天发生的事。
内审来人了,Sharpe 当场砍穿基准
第二天早上我打开报告,盯着首页那个 Sharpe 1.74 看了挺久。
Sharpe 1.74,年化 54.66%,最大回撤 22.43%,胜率 62.1%。这是教科书级别的好策略——也是教科书级别的”太好了不像真的”。
我做了件事——把这份报告完全当成是别人写的,让 AI 重新审计一遍。指令大概是这个意思——“假设你是一个 quant 团队的内审,找这份回测里所有可能让 Sharpe 虚高的逻辑漏洞”。
AI 用了大概 4 分钟,给我交回来一份审计报告。两个 bug,钉死。
Bug 1:止损在偷看明天
这个 bug 的画面感非常强。原始代码里追踪止损的判定逻辑是这样的:当天的最低价跌破了止损线,就算止损触发——按止损线的价格成交。
听上去合理对吧?问题在于:”当天的最低价”是一个收盘后才能知道的数字。你在盘中根本不知道今天 low 会到哪。但代码里用了,就等于策略偷看了今天的 low——再用这个信息去决定要不要止损。
更阴险的是它还作了一笔假账:止损线是 100,今天最低价 95,但成交价填了”100”——意思是”我假装在 100 这个理想点完美止损”。实盘里你根本来不及——价格穿过止损线之后还会接着跌,你大概率要到 95 附近才能成交。
AI 的修复也直白:止损只能按预设的止损线本身记账,不能用当天的极值”事后挑选”。
就这一个 bug,让 Sharpe 从 1.74 掉到 1.14 左右——掉了 0.6。这一个 bug 让原始 Sharpe 虚高了 70%。
Bug 2:成本扣得太轻
第二个 bug 没第一个戏剧性,但它揭示了一个更普遍的问题:高换手策略对成本极其敏感,差几个 basis point 就是天和地。
原始版本里成本扣得偏低,AI 重新校准成 5bp 佣金 + 3bp 滑点(往返 16bp)——这是公开券商的常规水位,不算苛刻。改完之后 Sharpe 再掉一截,落到 0.97。
两个 bug 加一起,Sharpe 从 1.74 砍到 0.97,年化从 54.66% 掉到 28.5%,最大回撤反而扩大了将近 7 个点到 29.1%——“被审计砍掉一半”那个标题不是修辞。
我盯着审计后那个 0.97 看了 30 秒。比 1.74 难看得多,难看到连同期 15 股等权死扛的基准(Sharpe 0.98)都没跑赢。但这是真的。
审计的价值,不是把数字做得更好看,而是把数字做得更可信。
没审计的回测 = 自欺欺人;审计后还活着、还敢接着抢救的,才值得继续。
第二个反转才是这次实验真正的收获。22 分钟跑出来的策略听上去封神——直到它自己写的”内审”把它打回原形,甚至打到基准之下。AI 一个人扮演了”研究员 + 内审 + 工程师”三个角色,关键是它没有”护短”。
人会护短。人写的策略,自己审计的时候很难下狠手。
仓位管理:等权是一句方便的谎
砍完两个 bug 之后,我让 AI 顺手把仓位管理也升级一下。
旧版叫 C2,等权分配——15 支股票,每只仓位 1/15,看似公平。问题是 TSLA 日波动率 3.5%,MSFT 1.2%,两个差了将近 3 倍。
等权之后,组合里 TSLA 一只票贡献的风险,约等于 3 只 MSFT。所谓”分散持仓”,其实悄悄被高波动股主导了。
新版叫 C3,波动率倒数加权——weight_i = (1/σ_i) / Σ(1/σ_j)。低波动股给大仓位,高波动股给小仓位,相当于给每只票发一张”风险配额券”,谁波动大谁少拿,让每只持仓贡献的风险量大体相等。
具体到数字:TSLA 的仓位被压到 4%,MSFT 拉到 11%。组合的波动来源被抹平了。
切换之后 Sharpe 从 0.97 抬到 1.04,MaxDD 从 29.1% 收窄到 27.08%,年化从 28.5% 抬到 31.82%——三个指标全好。靠一次仓位重构,策略重新爬回了基准之上。
把这个 1.04 放回基准里看才有意思:同期 15 股等权死扛的基准是年化 32.30%、Sharpe 0.98、MaxDD 39.74%。策略的年化几乎打平基准(31.82% vs 32.30%),看上去没赢;但最大回撤从 39.74% 一路收窄到 27.08%,少受了 12 个点的伤。Calmar 1.18 vs 基准 0.81(Calmar = 年化收益÷最大回撤,越高越扛得住极端下跌)——稳定性维度上才是真正赢出来的。
这一步本身不复杂,但它戳穿了一件常被忽视的事:好策略经不起平庸的仓位管理。逻辑层做得再漂亮,仓位层用一句”等权”糊弄过去,组合就会有看不见的偏向。
升级 C3 这件事,AI 大概用了 3 分钟跑完,包含一份 A/B 对照表。我做的所有事,是在 plan.md 里写一行”Phase 4: 仓位优化 C2→C3”。
5 项鲁棒性检验:参数没站在悬崖边
鲁棒性检验本质上是自审计的第二轮——审计砍掉了作弊,鲁棒性要确认剩下的 1.04 不是运气。策略调到 1.04 之后,下一个问题是:这个 1.04 是真的 1.04,还是过拟合堆出来的 1.04?
参数搜索空间里有 35 个组合(MA 5 档 × ATR 7 档),AI 全跑了一遍,做出来这张热力图:
我特意要这张图,是想看一件事:选定的 MA50 / ATR3.0 是不是站在悬崖边——也就是周围一旦扰动一格就掉下去的那种参数点。
热力图给的答案让我安心。MA50 / ATR3.0 在表格中央偏左上区,它的 8 个邻居(MA40-60 × ATR2.5-3.5)的 Sharpe 在 0.86 到 1.08 之间,没有一个跌破 0.8 门槛。35 组里平均 Sharpe 0.92,σ=0.18,相邻参数变化都在 20% 以内。这是典型的”高地”,不是”悬崖”。
参数稳定只是 5 项检验里的一项。剩下 4 项:
期间稳定性把 9 年数据切成 3 段:2017-2020 Sharpe 1.12,2020-2023 Sharpe 0.89,2023-2026 Sharpe 1.05。三段都在 0.8 之上,意味着这套逻辑不只是某一段牛市拉出来的运气。
成本压力测试看它在不同成本下的衰减曲线:
零成本 1.14、5+3bp 1.04、26bp 滑落到 0.96、50bp 跌穿门槛只剩 0.77。结论:策略对成本”中等敏感”——基础券商水位下能活,但要是到了离岸券商高频小票那种 50bp 量级,直接钉死。
剩下两项稍微有点忧虑。滑点敏感度从 0bp 到 10bp,Sharpe 从 1.08 一路滑到 0.82——余量偏薄,意味着实盘必须用限价单去争取,不能丢给市价单。
持仓天数扰动里 T+15 是 1.04 的全局最优,T+10 跌到 0.88,T+20 又只剩 0.96——T+15 这个值有点”太合身”,需要警惕一点过拟合的可能,但周边参数仍 > 0.8,可以接受。
5 项里 3 项稳过、2 项告警。这就是真实策略的样子——没有完美的策略,只有”知道自己在哪里脆弱”的策略。
6 个维度,从回测到实盘那道坎
回测做到 1.04,是一件事;让 1.04 在实盘里活下来,是另一件事。
我没有真去实盘——这次实验的目的是把研究流程跑通——但 AI 顺手把”回测 ≠ 实盘”这句口号拆成了具体的工程清单:数据管道要让回测和实盘共用一套口径(futu-api 这个公开 SDK 两边都用,复权方式、缺失值告警必须一致)、信号只能在收盘后算、订单走限价单 + TWAP 分拆 + 超时撤单、风控压三条硬红线(单股不超 15%、组合回撤破 15% 砍半仓、单日亏 3% 当天停手),再加监控和迭代两层。
这六层里有两层最该划重点,因为它们直接接着前面的故事。一层是订单执行,它是 Bug 1 的延续——实盘滑点要被压到回测假设以下,否则前面那个”滑点敏感度告警”会立刻从纸面变成现实。另一层是信号生成里的”收盘后”——回测里 AI 已经修过一次的前视偏差,到实盘还会卷土重来:你能不能保证盘中根本不碰信号?
我对自己(也对读者)的提醒只有一条:模拟盘 3 个月 → 10% 资金 → 稳定后再加仓。这条不是套话,是用别人的真金白银验证过的台阶。
真正的收获:会挑刺的 AI,和那 4 份文档
效率是这次实验最不值钱的部分。对话 15 分钟、AI 自跑 22 分钟,加起来 37 分钟,干完传统流程 3 到 5 天的活——两位数倍的提速没什么神奇,代码这件事早就被 LLM 解构了。
真正反直觉的是质量。我原本以为 AI 跑出来的东西需要我”兜底”,结果反过来:它抓的 7 个 bug 里,有几个我自己花一周也未必识破(比如止损时间戳偷看 low 那种)。再加上自审计砍掉的那一大截 Sharpe——AI 自己当裁判,比我担心的”它会糊弄”靠谱得多。
但这件事有个开关:你得告诉它”挑刺”,不是”夸自己”。我试过反面——让它”找一个 Sharpe 大于 2 的策略”,它真就给你挖出一个过拟合的漂亮废物,回测惊艳、实盘大概率第一周原地爆炸。同一个 AI,指令一换,从内审变成了帮凶。
而这次实验最该带走的,不是那个 Sharpe 1.04,是那 4 份文档:CLAUDE.md(项目宪法)、plan.md(执行路线图)、progress.md(状态记录),再加一份 factors.md。换标的、换策略类型、换市场,这套骨架原封不动——下次想跑商品期货 CTA?把 CLAUDE.md 的标的池一改、plan.md 里 Phase 0 的数据源换一下、Phase 1 的因子定义重写,其余照搬。框架的价值大于单次结果。
写在最后
回到开头那句话:22 分钟,0 行代码,Sharpe 1.74。
我现在愿意更老实地把它说成另一个版本:22 分钟跑出来一份骨架,再花 10 分钟让它自己拆穿自己,最后拿到一个 Sharpe 1.04 的可信策略。
这中间的 0.7,不是 AI 的过错,是任何一个人写量化时都会犯的错。区别在于:人写完之后未必愿意再去找自己的错,AI 不在乎。
这才是 AI 量化最实在的价值——不是”它替你赚钱”,而是它把研究过程的诚实成本压到了你能负担的水平。
至于那句广为流传的话,我用这次实验给它打个具体的注脚:
你负责想清楚做什么,AI 负责做出来。
下一篇我想回头讲讲前面的 5 轮对话到底是怎么设计的——CLAUDE.md 怎么写、plan.md 怎么拆、7 个决策点怎么对齐——也就是这次 22 分钟自动执行能跑通的”前置条件”。
如果你看到这里还想继续看,那就是我下一篇该写的理由。
参考与延伸
- futu-api:公开的行情/交易 SDK(GitHub 可搜),本次实验中的数据源
- ATR(Average True Range):经典波动率指标,本次策略的核心信号之一
- 系列前作:《把交易直觉变成可计算的因子》《因子验证四件套》——讲清楚 ATR 这个因子是怎么从直觉变成可验证的事件信号的
- 系列下篇:5 轮对话设计 SOP——CLAUDE.md / plan.md / progress.md 三文件是如何把 AI 从”会写代码”升级成”会跑研究”的