☰
从90%胜率到实盘亏损:量化交易回测陷阱与机器学习策略重构
2026/10/22 5:51:43 网站建设 项目流程

先交代一下背景。三个月前,我搭了一套用机器学习做股票方向预测的小系统,回测结果出来那一刻我差点以为自己要财富自由了:AI评估的历史胜率冲到90%以上。冷静下来之后,我又花了两周时间把这个"90%"拆了个底朝天,越拆越觉得自己当初太天真。这篇就聊聊这个"AI认为胜率90%"的投资策略到底是怎么设计出来的、问题出在哪、以及最后我改成了什么样子。内容偏实战,适合对量化交易和机器学习结合感兴趣,又不想被各种"稳赚不赔"话术忽悠的朋友。

先说结论:AI认为胜率高,和策略真正能赚钱,中间隔着一整条马里亚纳海沟。这个90%不是骗局,但它是被一堆隐蔽的假设和统计口径"喂"出来的。我会从策略的设计源头开始复盘,把每一步的坑都摊开讲。

1. 我为什么觉得"AI选股"这件事有戏

1.1 传统技术分析的痛点

入市一段时间的人大概都有这种感觉:均线金叉、MACD背离、KDJ超卖,这些指标单独拎出来都有道理,组合起来却经常打架。更麻烦的是,同样一个信号,在不同市场环境里表现完全不一样——牛市里"突破买入"怎么买怎么对,震荡市里"突破"就是"接盘"的同义词。

我一直想要一个能自动适应市场变化的系统,而不是靠人去猜当前该用哪套规则。机器学习的思路天然契合这个需求:让模型自己从历史数据里学规律,而不是我告诉它规律是什么。这是我做这个项目的第一个动机。

1.2 把"炒股"翻译成机器学习问题

要让AI介入,第一步是把"预测股价"这个模糊目标翻译成模型能吃的格式。我当时的做法是:

  • 预测对象:未来第T天(我最初用的是下一天)的收益方向是涨还是跌,转成二分类问题。
  • 输入特征:过去20个交易日的开高低收量价数据,加上一组技术指标。
  • 模型选型:结构化表格数据,优先试了梯度提升树(LightGBM系)和随机森林,后来也对比过LSTM,效果并没有质的提升,反而更难调。
  • 训练方式:滚动训练,用过去两年的数据训练,预测未来三个月的样本,然后再向前滚动。

为了直观,我列一下我最初用的特征清单:

特征类别具体特征用途
量价基础收盘价、成交量、成交额最原始的市场行为记录
均线体系MA5/10/20/60,价格相对均线的偏离度刻画趋势状态
摆动指标RSI、KDJ、BIAS乖离率捕捉超买超卖
波动特征历史波动率、ATR、振幅刻画风险水平
量能变化近5日量比、量能乖离判断资金活跃度

这套设计在思路上并没有太大问题,真正出问题的地方在后面——我怎么处理数据、怎么定义"胜率"、怎么评估结果。

2. 90%胜率究竟是怎么算出来的

2.1 数据泄漏:最隐蔽的"作弊"

我踩的第一个大坑,是数据预处理阶段的全区间归一化泄漏。听起来有点拗口,我用大白话解释一下。

机器学习模型普遍对输入特征的量纲敏感,所以训练前要归一化,比如把价格缩放到0到1之间。正常做法是:只用训练集的数据统计出最大值、最小值,然后用这个统计量去缩放训练集和测试集。我当时图省事,直接对整段历史数据一次性算好均值方差,然后再切训练集和测试集。

这就相当于考试前把答案夹在了参考书里。测试集的信息通过归一化参数混进了训练过程。模型在测试集上表现当然好,因为它"见过"未来数据的统计形态。这个坑极其隐蔽,回测程序不会报错,准确率还特别高,但一到实盘就原形毕露——因为实盘数据是实时流进来的,你不可能提前知道未来的极大极小值。

2.2 标签构造里面的"前视偏差"

第二个问题出在标签上。我最初的标签是"第二天收盘价相对于当天收盘价是涨是跌",这本身没问题。但我在拼接特征时,把当天收盘后的所有数据(包括全天成交量、收盘价)都算进了特征,然后用于预测"第二天全天"的涨跌。

问题在哪?第二天还没走完,它的信息当然不能用。更隐蔽的是,我回测成交价直接用了"第二天收盘价"成交——这在逻辑上等于你预知了第二天的结果再决定买不买。真实世界里,信号是当天收盘后产生的,最快只能以第二天开盘价成交,中间隔着一个晚上的不确定性(跳空、利空消息、隔夜外盘波动)。把"收盘价信号+收盘价成交"混在一起,就是典型的前视偏差。

2.3 "90%"里有多少水分:统计口径的小把戏

拆完数据问题,我再看那个90%到底怎么来的。结果又发现一个尴尬的事实:我计算胜率时,分母只统计了"模型发出明确看涨信号并实际开仓"的交易,而模型没信号或者信号置信度低于阈值的日子,全部被丢进了"无操作"分类,不计入胜率分母。

这意味着什么?打个比方:一个学生在100道选择题里只挑了最有把握的20道做,全对了,然后宣称"正确率100%"——他不提剩下那80道题他根本没敢做。我的模型也一样,它只在极少数趋势非常明确的样本上开仓,这些样本训练集里本来就容易学,胜率高是理所当然的。它掩盖了两个致命问题:大部分时间模型根本不知道该干什么,以及一旦开仓失败,单笔亏损可能吞掉很多次小盈利。

2.4 过拟合:把噪音当成规律

最后还有过拟合。我的特征里塞了20多个技术指标,模型在训练集上几乎可以背下每段K线的特定组合。训练集精度一度高到98%,验证集也有90%左右,但再往后的独立时间段一测,立刻掉到55%——跟抛硬币差不多。

过拟合的本质是模型把历史数据里的偶然噪音当成了必然规律。特征越多、训练时间越长、模型越复杂,噪音被"记住"得就越牢。我在复盘时用一个简单方式自查:把训练数据的时间顺序随机打乱,再跑一遍同样的流程,如果模型精度依然很高,说明它学到的不是时间序列里的因果关系,而是某种跟顺序无关的假模式——这不是好信号。

3. 回测漂亮,模拟盘翻车:落差从哪来

3.1 模拟盘第一周的实况记录

带着那个虚高的回测结果,我上了模拟盘。前三天风平浪静,小幅盈利,我心里还挺美。第四天开始不对劲:市场稍微一震荡,模型的开仓信号变得极其频繁,跟之前回测里"精准狙击"的风格判若两人。到第二周结束时,模拟账户把前几天的利润全部回吐,还倒亏了几个点。

这个落差几乎可以精确拆解。回测时我用的成交价是理想化的,没有计入真实交易中的冲击成本和滑点。实际成交时,买一卖一的价差、挂单深度不足导致的滑移,每一笔都在侵蚀收益。单看胜率,模型还是能有70%以上,但盈亏比崩了——因为每一笔亏损都比回测模拟中更大。

3.2 市场风格切换:模型没见过的新场景

另一个很现实的问题是市场环境变了。我的训练数据主要覆盖了一段相对平稳的行情,模型学到的是"低波动环境下动量延续"这类规律。模拟盘期间市场波动率突然放大,日内反复涨跌,这种模式在训练集里占比极低,模型彻底蒙圈。

机器学习模型本质上是个"模式匹配器":它只会对见过的模式给出可靠判断。历史数据里没有的极端情形,它处理不了。这也是为什么任何量化策略都必须强调"样本外测试"——用模型从未见过的时间段做验证,而不是只在同一个历史区间上反复调参自我感动。

3.3 我把几个主要失败模式整理成了表格

失败模式回测里的表现模拟盘里的真实结果核心原因
数据泄漏型胜率90%+,几乎不回撤快速失效,方向频繁判断错误归一化、标签构造混入未来信息
过拟合型训练集98%,验证集90%独立时段掉到55%,信号混乱特征太多、模型记住了噪音
成本忽略型胜率好看、净值稳步上升实际扣掉滑点和手续费后利润归零没建成本模型
环境突变型在单一风格行情里表现好风格切换时连续止损训练分布覆盖不全

看这个表就明白了:回测是"戴着滤镜看历史",模拟盘是"素颜面对未来"。滤镜越厚,落差越大。

4. 胜率之外,量化策略真正要盯的指标

4.1 一个反直觉的算术题:90%胜率为什么照样亏钱

先说个简单的数学例子。假设你的策略做10笔交易,9笔盈利每笔赚1%,1笔亏损亏掉20%,结果是什么?

总收益 = 9 × 1% - 1 × 20% = -11%

胜率90%,照样亏钱。这个例子极端,但很直观地说明了一个道理:胜率只是表象,真正决定账户净值的是期望值(期望收益)。期望值的公式很简单:

期望收益 = 胜率 × 平均单笔盈利 - (1 - 胜率) × 平均单笔亏损

如果平均盈利贡献只有1%,而平均亏损要吃掉5%,那就算胜率90%,长期也是亏的。反过来,很多趋势跟踪策略胜率只有40%上下,但靠"截断亏损、让利润奔跑",依然能稳定盈利。我最初只盯着胜率这个单指标,是典型的认知偏差。

4.2 我重构评估体系后真正盯住的指标

吃了一次亏之后,我做了一套新的评估清单,逐项检查策略成色:

指标含义我当时为什么必须盯它
期望收益每笔交易平均贡献的净收益看策略长期是否正期望
盈亏比平均盈利 / 平均亏损判断赚钱交易能否覆盖亏损交易
最大回撤净值从高点回落的最大幅度心理承受和风控的核心约束
夏普比率单位风险的超额回报衡量收益的"质量"而非"数量"
盈利交易占比真正赚钱的开仓比例结合盈亏比一起看,避免被单一胜率误导
交易频率单位时间开仓次数频率太低样本少,频率太高成本吃掉利润

这里面最容易被新手忽略的是最大回撤。一个策略哪怕年化50%,如果过程中要经历40%的回撤,绝大多数人根本拿不住——要么中途割肉,要么加杠杆爆仓。回撤不仅是数学问题,更是行为学问题。

4.3 为什么要做"交易成本敏感性分析"

我后来还做了一件之前没做过的事:成本敏感性分析。把交易成本(手续费+滑点)分别设为0、万二、万五、千一四档,跑同一个策略,看净值曲线变化。结果让人冒冷汗:

  • 成本为0:年化收益28%,近90%胜率
  • 成本万二:年化收益掉到15%
  • 成本万五:年化只剩6%
  • 成本千一:策略直接亏损

这说明我的策略本质上赚的是"微薄的方向性收益",对成本极度敏感。实盘里滑点往往比想象中更大,一进一出,利润全被磨平。没有做过成本敏感性分析的策略,都是纸面富贵。

5. 重构策略后的心得与可复用的改进思路

5.1 用前向验证(Walk-Forward)代替一次性回测

我最核心的改动,是把"一次性回测"换成了前向验证。做法是:把历史数据切成很多段,每段用前面的数据训练、紧跟着的下一段做验证,然后逐步向前滚动。这更贴近真实交易的节奏:你在每个时间点只能用到当时已经发生的数据。

具体流程我简化成三步:

  1. 用过去500个交易日的特征训练模型;
  2. 在之后的60个交易日做样本外预测并模拟交易;
  3. 每60天重新训练一次,滚动覆盖全部历史数据。

这样得到的收益曲线,每一段都是"当时真实可做到的",而不是事后诸葛。我改完之后,那个虚高的90%立刻现出原形——样本外胜率在55%到65%之间徘徊,但也正因为这个数字真实了,后续的优化才真正有意义。

5.2 给特征"减肥":少即是多

我把最初20多个特征砍到只剩下几个核心项:收益率、波动率、成交量变化率、价格相对中长期均线的偏离度。砍掉那些高度相关的指标(比如RSI和KDJ本来就是近亲,都源于价格位置),模型过拟合程度明显下降。

这里有个朴素的经验:特征越多,越容易拟合噪音;特征越少,模型被迫去学真正有用的结构。我当时用一个简单办法验证特征有效性——逐个特征做置换重要性排序,把置换后模型精度掉得最多的特征留下,其他删掉。删完以后,验证集表现反而更稳了。

5.3 把成本模型嵌进验证流程

现在我的所有回测都强制计入成本。不是简单加一个固定手续费,而是更细一点:按流动性水平和成交量分层估计滑点,成交额小的标的滑点系数拉高。这样回测曲线不会再有"理想国"的感觉。

嵌入成本之后的策略才是真正可讨论的策略,这一步和指标一样重要。在成本完全吞掉策略收益之前,根本谈不上讨论策略优劣。

5.4 组合层面模拟:单票开仓改为分散持仓

另一个重要改动,是从"单票重仓"改成"组合分散"。单票预测的难度和不确定性都太高,一次黑天鹅就能让账户重伤;但如果你同时持有十几只标的,并且每只的仓位上限控制在5%以内,即使某只标的预测方向错了,对整体净值的影响也可控。

组合层面的模拟不只是把单票结果简单相加,还要考虑标的相关性。我当时选了不同行业的标的,避免扎堆在某一个板块。这个改动直接降低了净值曲线的波动,最大回撤从原来的20%以上压到了10%以内——虽然收益也被摊薄了一些,但拿得住才是关键。

5.5 我最后留下的一条铁律

整个项目跑下来,我给自己立了一条规矩:任何策略,首先在样本外拿到稳定的正期望,其次在计入真实成本后依然不亏,最后再谈胜率高低。顺序不能反。90%的胜率可以当作一个有趣的结果来展示,但如果它经不起样本外验证、经不起成本检验、经不起风格切换的考验,那它就是一个数字幻觉。

这只是我个人在这个模拟项目里的一次完整试错记录,不构成投资建议,也谈不上什么高深理论。我更想传达的是:AI工具确实能帮人做大量数据分析和模式挖掘,但它不会改变市场的基本规律——不确定性永远存在,所谓的"高胜率"往往只是某种统计口径下的产物。认清这一点,比找到一个"完美策略"重要得多。

如果你也在做类似的尝试,我的建议是多花时间在验证机制上,而不是模型调参上。数据怎么切、标签怎么定义、成交假设是否符合实际、成本有没有计入——这四个问题想清楚了,哪怕模型简单一点,出来的结论也踏实得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询