第五部分 · 量化研究如何产生可信结论 · 第 29 章

数据、标签和样本切分: 量化模型从哪里学

如果你有机器学习的底子,很容易把量化当成一个普通监督学习问题:把特征和标签喂给模型,训练,验证,上线,收工。但金融数据最阴险的地方,恰恰在于它会不动声色地让你把未来塞进过去:财报的发布日期、指数成分的变动、复权价格、停牌、涨跌停、退市、交易成本——每一个细节都可能让你的模型在回测里像个天才,一到实盘立刻失忆。这一章专门拆解这些坑,它们是初学者和老手之间的那道分水岭。

主线五 本部分第 2 / 10 章

本部分的问题:一个金融判断怎样变成可证伪假设,再经过数据、回测、模型和实盘约束?

读完后,你能从问题出发完成研究闭环,而不是先找模型、再给结果编故事。

读完这一章,你会明白

  • 量化数据必须恢复历史当时的信息状态,点时数据是防止未来函数的核心。
  • 标签定义决定模型任务,预测绝对收益、相对收益、波动或回撤是不同问题。

金融现场 1. 用今天的名单回到 2007 年,雷曼已经不见了

假设你下载今天仍在交易的一批大公司,把它们的历史价格拉回 2007 年做选股。曲线大概率比真实经历漂亮,因为雷曼兄弟、贝尔斯登和许多后来消失的公司根本没有出现在你的起跑名单里。失败者被数据库安静地删掉,幸存者却带着完整历史回来参赛。

这就是幸存者偏差最狡猾的地方:代码没有报错,数据也没有缺失,结果甚至非常稳定。问题出在“谁有资格进入样本”这一步使用了未来信息。你不是在 2007 年选股,而是在今天知道结局后,让赢家回去重跑一次。

点时股票池、退市收益和成分变更记录因此不是数据洁癖,而是时间机器的门锁。量化数据的第一原则不是越多越好,而是每一个历史时点只能知道当时真的能知道的事。

2. 量化数据不是只有 K 线

新手想象中的量化数据,往往就是一张 K 线表。实际上,行情数据只是最基础的一层:开盘价、最高价、最低价、收盘价、成交量、成交额、盘口和逐笔成交。往上还有基本面数据:财报里的收入、利润、资产负债、现金流、ROE、毛利率、负债率。再往上还有公告、分析师预测、基金持仓、指数成分、融资融券、期货持仓、期权波动率、新闻文本和宏观数据。数据食材琳琅满目,问题是怎么配菜。

配菜的最大麻烦是:这些数据的频率和发布时间完全不在一个节拍上。行情数据每天甚至每秒更新,财报按季度才披露一次,宏观数据按月或按季发布,分析师报告和新闻则是不规则地突然到达。把它们拼进同一张训练表时,必须时刻盯住一件事——在交易发生的那个时刻,这条数据到底是不是已经可见?

所以量化数据工程的核心,不是把表拼起来那种体力活,而是考古式的还原:恢复历史当时的信息状态。模型在 2020 年 4 月 10 日做决定时,绝不能看到 2020 年 4 月 30 日才发布的年报修正,也不能看到后来才确定的指数成分回填。模型可以笨,但不能作弊——作弊考出的高分,一文不值。

3. 在那个时点你到底知道什么

点时数据是量化里极其重要的概念,用一句话说:每条数据都要携带“何时生效、何时可见、何时被修正”的完整时间档案。听起来理所当然?举个最常见的反例:财报的报告期末是 12 月 31 日,很多人就以为 12 月 31 日当天就能用全年利润建模——错。投资者真正知道这个数字,通常要等公告发布之后,中间可能隔着好几个月。

代入一个具体场景,感受这个坑有多深。某公司 2025 年年报的实际披露日是 2026 年 3 月 28 日。如果你在 2026 年 1 月的回测里使用了这份年报的最终净利润,那么你的模型等于提前两个多月偷看了答案——这就是教科书级的未来函数。它在回测里刷出的超额收益,到了实盘一秒蒸发。

数据库里还埋着更隐蔽的雷:字段里只有报告期、没有发布日期;或者数据供应商把历史数据悄悄修正成最终版本,却没保留当时的初版。这种数据看起来干干净净,回测出来的结果却天然过于乐观——因为模型看到的是“事后改过的历史”。专业的数据服务会尽量提供公告日期、更新时间和历史版本沿革,买数据、选数据时,这条是硬指标。

4. 你让模型预测什么

训练模型之前,有个问题必须先想清楚:你到底让它预测什么?这个“什么”,就是标签。股票量化里常见的标签有:未来 1 日、5 日、20 日或 60 日的收益率;也可以是未来相对行业或指数的超额收益;还可以是未来是否跑赢市场中位数、未来的波动率、未来的最大回撤,甚至未来能否顺利成交。标签不同,你训练的根本就是不同的模型。

别小看标签定义,换一个标签,等于换了一道题。预测明天收益和预测下个月收益,是两份完全不同的考卷:明天收益噪声更大、交易频率更高、对成本更敏感;下个月收益信号或许更慢更稳,但持有期间的风险更长。同理,预测绝对收益,你会被整个市场的涨跌裹挟;预测相对收益,才是真正的选股题——那一部分才可能是你模型做出的成绩。

拿一个常见的入门标签来说:从今天收盘,到未来 20 个交易日之后的复权收盘收益。它适合月频选股研究,但它绝不等于真实可成交的收益。为什么?因为你今天收盘之后才能算出完整收盘价,实际执行买入最早也要等到明天开盘或盘中,这中间隔着一个夜晚的跳空;而且还没扣成本,没处理停牌和涨跌停能不能成交的问题。标签是题面,成交是答题,先分清这两件事。

5. 特征和标签的时间对齐

监督学习有条铁律:特征 X 必须在标签 y 之前可见。在任何领域都成立,但在量化里,它值得用加粗加大号字体刻在你的工位上。特征日期、数据发布日期、交易决策时间、下单时间、成交时间、标签收益区间——六个时间点,必须像火车时刻表一样排得整整齐齐,一处都不能越位。

来感受一个每天都会犯的经典错误。你用今天的收盘价计算特征,又在回测里假设自己按今天的收盘价买入——可收盘价格是收盘那一瞬间才确定的,你等于先看了答案再做题。正确姿势是:收盘后生成信号,下一次可执行成交在之后的某个交易时点。差一步,就是从研究滑向自欺的一步。

这类错误的可恶之处,在于它在代码里根本不显眼。一个 shift 写错了一格,一个 merge_asof 的连接方向反了,一个财报公告日期没做处理——模型表现立刻“优异”得不像话。所以请把下面这句话变成条件反射:看到过于漂亮的结果,第一反应不是庆祝自己挖到圣杯,而是去检查时间对齐。在金融数据里,异常好往往意味着异常错。

时间对齐错位= 之所谓'自带未来酒'——回测被顺手偷看了未来 交易日 时间 决策日(今天必须下单的瞬间) 特征 X 数据 必须是决策日之前就可见 特征 Y 数据 如果要等到决策日后才见到,这就是非法数据 合法要做的检查:每个特征在它该被使用的那一刻都必须是真实当时披露的版本——不能被未来修正过的值污染

判断回测能不能信,先问数据是不是时点上可见——没有中间态:可见日必须早于使用日,差一分钟都不算对齐。

6. 复权价格和真实成交价格要分开

前面章节讲过,复权是为了让历史价格口径可比。到了建模这一步,你会撞上一个看似矛盾的规则:算收益标签,该用复权价格;模拟真实成交,却绝不能用复权价格。两套价格,各管一段,弄混了全盘皆错。

用一个例子把这两条路分开。某股票分红除权,未复权价格从 10 元变成 9.5 元。如果你拿未复权价格算收益,会硬生生把分到手里的分红算成亏损——冤枉了它;可反过来,如果你拿复权价格去模拟下单成交,又是在用一个历史上根本不存在的交易价格——骗了你自己。标准做法是:收益计算和因子计算,走合适的复权口径;撮合成交、判断涨跌停、计算成本,一律走当时真实可交易的价格口径。

很多回测框架会在内部默默帮你做这些转换,这很方便,但也埋着信任风险——你不能完全盲信框架。至少要把几个字段抠清楚:close 到底是未复权还是前复权?return 含不含分红?limit_up 和 limit_down 用的是哪个价格口径?口径不清楚,后面的一切计算都建在流沙上。做量化,先把字段当法律文书读。

7. 你允许模型在哪些资产上下注

模型不是想选谁就选谁——动手之前,你要先给它发一张“准入名单”,也就是股票池。你可以选全 A 股,也可以选沪深 300、中证 500、中证 1000 的成分股,或者锁定某个行业;也常常顺手剔除 ST 股、停牌股、上市未满一定天数的新股和流动性太差的股票。别以为股票池是随便画的圈,它直接决定策略的收益、风险和可执行性。

股票池里最阴的一个坑,是拿今天的名单回测过去。比如只拿现在还活着、还上市的股票回测十年——那些中途黯然退市的公司,被你的数据集悄悄抹掉了,样本里清一色“活到了决赛圈”的幸存者。这就是幸存者偏差。正确做法是:每个历史日期,都只使用当时可投资的股票池,让过去只看到过去的名单。

股票池还顺手决定了你的基准,这两件事必须配套。你在沪深 300 成分里选股,就应该主要和沪深 300 比;在中证 1000 里选,就和中证 1000 比。股票池和基准不匹配,就像拿游泳运动员的配速去考核自行车手——市场暴露和选股能力搅在一起,结论必然失真。

股票池不是中性设置,是你策略的一部分 假设你只回测沪深 300 的成分股——你是在大盘股里找规律, 允许全市场选股的小微盘股池,结果完全不同——你看见了另一个世界。 股票池一旦固定,就算是在不同日期上,结论也不能跨池互换。

股票池是策略真正踏上的土地——涨跌停规则、流动性、因子效果,全都在这个池里决定。换池即换规则。

8. 缺失值不是小麻烦

金融数据从来就不是完整的方格子。新上市的公司历史短,停牌的日子没成交,财务字段可能还没到披露时间,某些行业指标在别的行业根本不适用,新闻数据覆盖更是厚此薄彼——缺失无处不在。最危险的一个动作是:看见缺失就填 0。要知道,0 可能是一个真实数值(比如本期计提为零),也可能只是“没有数据”,两者的含义天差地别。

常见处理方式有这么几样:删除缺失样本、用行业中位数填充、拿上一期可见值延续、加一个“是否缺失”的标记位,或者干脆让模型自己学会处理缺失。选哪种没有标准答案,取决于字段的真实含义。比如 PB 缺失,可能是公司净资产为负、算出来没意义,也可能只是数据未覆盖——一个是信号,一个是事故,绝不能一视同仁。

再深一层:缺失本身可能携带信息。财报迟迟不发、没有分析师覆盖、数据质量差,往往和风险挂在一起。如果你图省事,把带缺失的样本一刀切全删掉,你的股票池会悄悄偏向信息披露好、流动性好、规模大的公司——一个看不见的偏差,就被你亲手埋进了训练集。你以为在做清洗,其实是在做采样偏见。

缺失值的两个错误填法 填 0:在这一刻假装既没有行情,也没有波动——给动量、波动率因子喂了假数据 填历史均值:这个均值在当时你不可能知道;你等于用未来的均值校正了今天 正确做法:记为“缺失”,不填不猜,让模型在特征工程阶段自己知道——这叫中信持久性

缺失值不是需要补的坑,是该被标记的状态。你填了一个漂亮的值,模型信以为真——这比“这一天没有数据”伤害大多了。

9. 训练集、验证集和测试集不能随机打乱

机器学习课本能教你随机划分训练集和测试集,但金融序列不吃这一套。为什么不能随便随机打乱?因为金融市场在时间上是连续的、上下游有依赖的:未来样本和过去样本可能共享同一个市场状态。一随机,未来市场环境的“气味”就顺着共享的状态渗进了训练集,模型等于提前闻过了考卷的味道。

更合理的做法是按时间顺序切分:比如 2015-2019 年用作训练,2020-2021 年做验证调参,2022-2024 年守住测试。这样测试集才是真正的“未来”。还可以做滚动训练和 walk-forward 验证:用过去一段时间训练,向前预测一段,再整体往前滚动窗口,像推着时间向前走。让模型永远只学昨天、预测明天。

但时间切分也不是金钟罩。如果训练期和测试期的市场环境碰巧太像,结果仍可能乐观;如果测试期刚好撞上极端环境,结果又会过于悲观。所以更稳的做法是覆盖多个市场阶段,看策略在牛市、熊市、震荡市、流动性冲击里分别什么德行。一次切分一盏灯,多种环境才是全景灯。

10. 样本外不是一句口号

“我做了样本外测试”——研究报告里这行字人人会写,真正做到的却没有那么多。样本外的含义,是模型没有用这段数据参与训练、调参和策略选择。现实里最常见的违规是:反复盯着测试集结果看,根据测试结果回头改特征、调参数。一次两次看不出问题,搞多了,测试集就被悄悄“用脏”了——名为样本外,实为训练集。

量化里还有个更隐蔽的污染源,藏在研究员自己的脑子里。假设你试了 200 个因子,只留下表现最好的 5 个写进报告——即使每个因子都规规矩矩在测试集上跑过,最终的报告依然带着数据挖掘偏差。因为“留下这 5 个”这个动作本身,就已经看过了测试集的成绩。你筛过的不是因子,是运气。

对抗这种自欺,靠的是一整套研究纪律:留一份真正没碰过的最终样本、记录所有做过的实验(包括失败的)、控制试错次数、做跨市场交叉验证、上模拟盘和小规模实盘再验证一轮。样本外不是一个技术名词,而是一种对自己的诚实——能不骗自己的研究员,才配得上信任曲线。

11. 从数据表到训练样本

铺垫了这么多防线,最后一步该真的搭样本了。一个股票日频训练样本,可以想象成三维结构:日期、股票、特征。每个交易日,操场上站着一批股票,每只身上挂着几十个特征值,标签是未来一段收益。喂给模型时,把这个立体结构拍平成一张大表:每一行是“某天某只股票”,列是特征和标签。

但拍平这张表之前,要过一串安检门:当天是否可交易?是否停牌?是否涨跌停到无法买卖?上市天数够不够?财务数据是否已披露?是否在股票池内?最关键的是:这套过滤规则,必须在训练、回测和实盘三处完全一致——三套规则各说各话,训练出来的就是“三次元模型在二次元考试”。

过滤不一致的结局是什么?如果训练样本里混着大量实盘根本买不到的股票,模型会津津有味地学习一堆不可执行的机会——纸上高手,实盘废物;如果回测过滤得严、训练过滤得松,训练目标和交易目标从一开始就南辕北辙。量化的细节不会浮现在 PPT 里,它们藏在每一行过滤规则里,最后统统反映在收益曲线上。

小结

这一章的正文不是让你记住几个孤立名词,而是要把它们放回同一条因果链里。读完后,先用自己的话复述下面几条判断,再顺着“小节回看”检查是否能解释每一步。

  • 量化数据必须恢复历史当时的信息状态,点时数据是防止未来函数的核心。
  • 标签定义决定模型任务,预测绝对收益、相对收益、波动或回撤是不同问题。

小节回看

  • 1. 用今天的名单回到 2007 年,雷曼已经不见了
  • 2. 量化数据不是只有 K 线
  • 3. 在那个时点你到底知道什么
  • 4. 你让模型预测什么
  • 5. 特征和标签的时间对齐
  • 6. 复权价格和真实成交价格要分开
  • 7. 你允许模型在哪些资产上下注
  • 8. 缺失值不是小麻烦
  • 9. 训练集、验证集和测试集不能随机打乱
  • 10. 样本外不是一句口号
  • 11. 从数据表到训练样本

自测

为什么财报报告期不等于可用时间?

报告期只是财务数据覆盖的时间区间,投资者通常要等公告发布之后才能看到这些数字;在披露日之前使用,就是未来函数。

未来 20 日收益标签有什么执行问题?

用今天收盘价生成信号又按今天收盘成交,等于先看到收盘结果再下单,偷看了当天信息;此外还要扣成本、处理停牌涨跌停。

下一章为什么接在这里

回测: 在历史里排练,但不要把历史当答案

讲清事件驱动、调仓、成交假设、交易成本、滑点、容量和回测陷阱。