跳到正文

量化中的特征工程

算法可以互换,特征才是策略。三类原始素材、判断一个特征好坏的四条标准、五个人人都会犯一遍的错,以及从裸动量到横截面 z 分数的完整改造路径。

第 3 篇 · 共 8 篇 约 15 分钟

量化的机器学习里,算法反而是最简单的部分。2026 年的 LightGBM 跟 2020 年的 LightGBM 大体上是同一个东西,真正变化的是特征。

每个机器学习模型都要交一笔”复杂度税”:模型越复杂,它在回测里过拟合的花样就越多。简单模型(线性回归、浅层树)税少,复杂模型(深度网络、成百上千棵树的梯度提升)税重。这笔税有两种交法——用更好的特征交,或者用更激进的正则化加一炷香交。多数人选后者,这篇文章讲前者。

一个反复出现的情形是:一整个组在同一组五个原始输入上把 XGBoost、LightGBM、CatBoost、Transformer 编码器、自研 GNN 翻来覆去地试,每换一个模型多挣的 Sharpe 都是零点几;然后有人加了三个精心挑选的特征,算法一个没换,Sharpe 直接翻倍。这不是段子,是特征工程和调参之间真实的杠杆比。

从原始成交到模型输入,中间有四层

从交易所到模型这条流水线有四个阶段,搞混它们是特征工作出错的一半原因。原始行情数据是逐笔成交和报价、日线 OHLCV、财报披露、另类数据源;衍生特征是从原始数据算出来的收益率、滚动统计量、比值、嵌入向量;因子得分是有明确方向性解读的特征——动量、价值、质量;机器学习输入才是真正喂给模型的东西,已经过了标准化、缩尾、缺失值处理这几关。

新手最容易犯的错是从第四层开始,反过来想怎么修模型。杠杆在第二层和第三层。如果你的特征在第三层就一点信号都没有,再花哨的模型也榨不出金子来。模型是张筛子,水里没金子,筛子自然筛不出金子。

下面三节按原始素材的来源分,这决定了特征的成本、更新频率和拥挤程度——三件在你写第一行代码之前就该想清楚的事。

价格与成交量:最老、最肥,也最拥挤

只用价格和成交量序列就能算,不用买基本面数据。这一类至今仍然是最肥的。

最基础的是收益率 rt=Pt−Pt−1Pt−1r_t = \frac{P_t - P_{t-1}}{P_{t-1}},一般要算多个时间窗——1 天、5 天、20 天、60 天。这里已经有一条经验规律:1 天收益率基本是噪声,20 天和 60 天的收益率承载了横截面信号的大头。往上是滚动统计量:滚动均值、标准差、偏度、峰度;多窗口下的波动率本身就是一个特征,因为高波动的票和低波动的票脾气不一样。

动量是回看窗口的累计收益,通常会把最近一个月抠掉,避开文献里反复出现的短期(一个月)反转效应——那一段时间里价格是反向的,包进来只会污染动量估计。均值回复 z 分数 Pt−μt,nσt,n\frac{P_t - \mu_{t,n}}{\sigma_{t,n}} 走的是相反的方向:均值和标准差在长度为 nn 的滚动窗口上计算,z 分数为正说明价格相对近期历史偏高,为负说明偏低,均值回复策略低买高卖。同一批价格数据,两个符号相反的信号,区别只在窗口长度上——这也是为什么窗口选择在这一类里几乎和公式一样重要。

成交量那一支包括相对成交量(今日成交量除以 20 日均量)、能量潮(OBV)、收益率与成交量的相关性(业内常叫”量价配合”)。如果你有逐笔数据,还能往下做微观结构特征:买卖价差、订单簿不平衡、成交方向(Lee-Ready 算法)、最近 nn 笔成交的已实现方差。

这一类之所以流行,是因为便宜又算得快。它们也因此是最拥挤的:一段 50 行代码就能写出来的动量信号,别的九百九十九个人早就写出来了。

基本面:慢,但价格里没有

从公司财报里算出来的特征。按季度更新,还有 45 天左右的报告时滞,慢得多,但携带着价格序列里根本不存在的信息。

估值比率是经典的”价值”一支:市盈率、市净率、企业价值倍数(EV/EBITDA)、自由现金流收益率。Fama-French 的 HML 因子粗略地说就是一个按账面市值比排序的多空组合。成长是同比增长率——营收、利润、账面权益——但成长是个特征,不是策略:多数学术研究发现原始成长对未来收益的预测力很弱甚至为负,真正有信号的是相对预期的成长,也就是”成长意外”那一类。

盈利能力这一支值得单独说。除了 ROE 和 ROA,还有毛利能力(毛利润/资产)。Novy-Marx (2013) 给出的证据是,光是毛利能力一项就差不多有和价值因子相当的 Sharpe,而且两者基本正交——把它们组合起来几乎相当于白送,这在因子世界里是罕见的。杠杆(资产负债率、债务/EBITDA、利息保障倍数)方向更稳定但也更依赖环境:大多数市场环境下高杠杆公司跑不过低杠杆公司,金融危机前后那一段是明显的例外,那时候”能去杠杆的能力”反而成了稀缺品。盈余质量看的是应计项目,也就是会计利润和现金流之间的差距;Sloan (1996) 提出的应计异象——应计高的公司表现差——是文献里最稳健的异象之一。

这一类真正的坑不在公式上,在数据上,名字叫 point-in-time integrity(时点完整性)。你今天看到的 2020Q1 的 PE,不是 2020Q1 那个投资者当年看到的 PE:公司后来重新声明过、补报过、再重新声明过好几次。把现在的值当作历史上的值用,你就已经把前视偏差请回家了。你需要的是一份能保留”每个历史日期上当时报出来的那个数”的基本面数据库,而不是一份最新快照。

另类:听起来独家,多数不是

兜底的一类,只要不是价格/成交量或基本面就算另类,新研究大多集中在这里。

情绪从新闻标题、业绩电话会议记录、社交媒体、分析师报告里挖,噪声大,但和基本面不相关,所以组合起来能多解释一些方差。内部人交易用 SEC 的 Form 4 文件,其中集群买入——多个内部人在短时间内一起买——是数据里最持久的一类信号。融券余额(被融券的流通股本占比)预测未来的负回报,但这种关系是非线性的:极端高融券反而可能轧空,变成正收益,所以直接线性用它是错的。期权流量包括异常期权活动、看跌/看涨比、隐含波动率偏斜,可以每天按分钟级粒度算。

再往外是真正的另类数据:卫星图像(零售停车场里的车数、油罐的影子、农作物的长势)从当年的小众玩法变成了几十亿美元的生意;网站流量和 App 使用情况给出上市公司层面的用户总数、会话时长、转化率,已经有一批供应商在专门卖;地缘和事件特征(国家风险评分、贸易政策变化、选举结果)最难量化,往往是离散更新的。

另类特征讨人喜欢,是因为听起来像独家。多数其实不是——你一周能搭出来的情绪特征,别的团队一周也能搭出来。这一类的护城河通常不在数据本身,而在于多快能把它落到策略里(低延迟新闻源),或者它和传统特征怎么组合。

好特征要过的四关

素材有了,接下来的问题是怎么判断一个特征值不值得留。特征和特征之间是不平等的,下面四条能把活下来的那些,跟回测漂亮、上线就死的那些分开。

第一关是持久的 IC。 IC(Information Coefficient,信息系数)是特征与未来收益之间的秩相关,衡量的是这个特征区分”会涨的票”和”会跌的票”的能力。持久指的是它跨时间稳定:一个 2015 年 IC 是 0.04、2020 年 IC 也是 0.04 的特征,比一个 2018 年 IC 是 0.10、2022 年 IC 是 0.00 的特征值钱得多,虽然后者的峰值好看两倍多。所以规矩是把 IC 放到多个市场环境下算,别只算回测窗口。过去十年每一年 IC 都为正的特征是有点东西的;只在 2019-2023 为正、其他年份跑出负值的,基本就是噪声。

第二关是低换手。 预测力再强,换手太高,交易成本也会把它吃干净。如果你的特征是”过去 20 天涨幅最大的那些票”,你天天都在调仓——信号强,执行贵。这里有个可以直接用的经验:横截面特征(一个票相对同行的位置)通常比时间序列特征(一个票相对自己历史的水平)换手低,因为横截面排名变化得慢。

第三关是跨行情扛得住。 一个牛市能用、熊市就崩的动量特征,你没法不挂一个市场择时模型就去交易它。用特征的整个目的就是挖出可移植的信号;如果信号只在某一种行情下有用,那不如直接做一个行情识别器加一个单因子策略,至少你知道自己在赌什么。测试要拿多年的样本:2000 年代和 2020 年代的结构完全不同,一个年代价值股吃香,另一个年代成长股吃香,一个只在 2000 年代有效的”价值”特征下的是行情的注,不是价值的注。

第四关是至少没有明显的伪相关。 这一关的门槛比想象的低。你不需要一个完整的因果故事,多数机器学习 alpha 都没有;你只需要能排除一个明显的伪相关故事。如果你的特征是”股票代码的第三位数字”而它居然预测收益,那你就有麻烦了:样本内的相关是真的,但它几乎肯定是噪声,而你没有任何办法把这两种情况分开。反过来,有因果故事的特征——动量来自反应不足、价值来自过度外推、应计来自盈余管理——在风险委员会那里更好过关,在策略开始抽风的时候也更好推理。

一个具体的例子:把动量改造四遍

四条标准放在一起,最好的展示方式是拿一个特征改一遍。最简单的动量特征就是 12 个月收益:

mom12=PtPt−12−1mom_{12} = \frac{P_t}{P_{t-12}} - 1

这玩意儿能用,自从 Jegadeesh & Titman (1993) 之后它是资产定价里被研究得最透的一个特征。它也有几个出名的死法:短期反转(最近一个月是强烈的反向信号,包进来就污染了动量估计)、2009 年的动量崩盘(那一小段时间策略亏了 50%+)、以及越来越拥挤。

第一处改动只是把最后一个月扔掉:

mom12,skip=Pt−1Pt−12−1mom_{12,\text{skip}} = \frac{P_{t-1}}{P_{t-12}} - 1

信号更稳,2009 年的回撤也明显小一些。这一步针对的是上面那个反转问题。

第二处改动除以 60 日波动率:

mom12,risk-adj=Pt−1/Pt−12−1σt−1,60mom_{12,\text{risk-adj}} = \frac{P_{t-1}/P_{t-12} - 1}{\sigma_{t-1, 60}}

这下信号衡量的是风险调整后的动量,而不是裸收益。一只票涨了 20%、年化波动率 40%,跟另一只涨了 20%、年化波动率 15%,两者的”动量味道”不一样,除以波动率把这个区别抓住了。

第三处改动把它挪到横截面上:

mom12,xs-z=mom12,risk-adj−μuniverseσuniversemom_{12,\text{xs-z}} = \frac{mom_{12,\text{risk-adj}} - \mu_{\text{universe}}}{\sigma_{\text{universe}}}

这是风险调整动量在整个票池横截面上的 z 分数。模型听到的不再是”这只票过去一年涨了 20%“,而是”这只票今天在所有票里风险调整动量排到了 90 分位”。横截面的框架把市场整体行情的干扰拿掉了——这正好是第三关要的东西,牛熊都管用——也让这个特征可以直接拿来排序,顺带把换手降下来,第二关也过了。

每一步都是小改动,每一步都是实质性的提升。大部分人在自己的第一个动量实验里就停在第一步,拿到一个正向但不稳定的信号,然后就往下走了。从第一步走到第四步这段路,才是护城河所在。

五个人人都会犯一遍的错

希望你只犯一遍。

前视偏差是最经典的:用今天的收盘价算今天的收益,然后拿这个收益当目标训练模型。“今天的收益”既是特征又是标签,模型在样本内当然完美拟合,样本外完全是垃圾。修法一点也不性感——用昨天的价算今天的收益,明天的价算明天的收益;每一个特征必须在它要去预测的那个标签严格可用之前就到位,每一个,没有例外。(López de Prado, Advances in Financial Machine Learning,第 3 章 Labeling 和第 7 章 §7.3 Why K-Fold Fails in Finance,ISBN 978-1119482086。)

存活偏差藏在票池里。你手头有一份”现在还在交易”的美国股票池,拉下数据、算特征、训模型,问题是今天的池子不是 2015 年的池子:被退市、被收购、破产的票已经不在里面了,它们那些往往相当负面的特征(当时正在困境里)也一并失踪,模型压根学不到怎么预测它们。修法是用 point-in-time 的池子,把历史上存在过的票都算进去。标普 500 的历史成分股是有据可查的,CRSP 数据库有完整的含退市回报的历史行情。

数据窥探是你试了 100 个特征变体,然后挑那个有效的来报。文献里管这叫”研究者自由度”,说难听点就是多重检验偏差:哪怕这 100 个特征全是纯噪声,至少有一个看起来以 p<0.05p < 0.05 显著地预测收益的概率大约是 99%。修法是流程纪律而不是统计戏法——在看数据之前就把要测的特征定下来(预注册),或者认真用 deflated Sharpe 比率和样本外验证。

错误的缩放是个纯工程问题:你把原始 PE(取值范围 0–100)和一堆二元指示变量(0–1)一起喂进模型,PE 因为量级大在损失函数里一统天下,二元特征基本没贡献。修法是对每个特征做 z 分数(减均值、除以标准差),或者干脆用对量级不敏感的树模型(XGBoost、LightGBM、Random Forest)。树模型天生能处理混合量级,线性模型和神经网络不行。

非平稳特征是最难防的一个。2010–2019 好用的特征到 2020–2025 未必好用,因为宏观环境在变——利率周期、行业领涨、散户和机构的钱谁说了算。在单一十年里校准出来的特征,到下一个十年可能一点用都没有。修法是滚动验证:每年重算一遍特征的 IC,把跌破历史 25 分位的标记出来,淘汰掉。这一条其实就是第一关的运维版本——IC 持久性不是一次性的检验,是要一直做的事。

缩尾与离群值:进模型之前的卫生工作

原始金融数据里到处都是离群点。单只票的日内收益在财报日或公司行为当天能超过 ±50%,一些比率可能是负的、无穷大,甚至没定义(一家零利润公司的 PE),成交量在指数调仓日能飙到平时的 100 倍。原值直接喂进模型,离群点会在损失函数里一手遮天,而这跟上一节”错误的缩放”是同一类病的两个症状。

缩尾(winsorization)是标准修法:在百分位阈值上把极端值截掉,通常是 1 分位和 99 分位,或者 0.5 和 99.5。注意这些值不被删除,而是被拉到阈值处——数据点还在贡献,只是不再一手遮天。当离群点是真的但没有代表性时这最对路,一天的财报跳空不该主导整个模型的损失。

MAD(中位数绝对偏差)标准化比均值/标准差更稳健:减中位数、除以 MAD,而不是减均值、除以标准差。这样标准化本身就不会被离群点带偏,在特征分布重尾的时候特别好用。对数变换则适合有乘性动态的特征——价格、成交量、市值——它把乘性增长变成加性增长,让分布更对称,也削弱极端值的影响。

规矩是把缩尾和标准化当成特征流水线的一部分,别事后才补。用原始未处理特征训出来的模型会被离群点支配,泛化不了。

特征重要性:看清模型到底在看什么

特征搭好、模型训完,下一个自然的问题是模型到底在用哪些特征。注意这个问题不是”哪些特征可能有用”,而是”哪些特征真的承载着模型正在利用的预测信号”——它们经常不是同一批。

三种标准方法,各有各的坑。

Gain-based 重要性是 XGBoost 和 LightGBM 的默认:对每个特征,把所有用到它的分裂点上损失函数的减少量求和。被很多分裂用到、被早期分裂用到、在大幅降低损失的分裂里用到的特征分数就高。方法快,天然为树模型设计。坑在于高基数特征——取值很多的连续变量——会因为候选分裂点多而被系统性高估:一个连续型动量特征会比一个二元行情指示器显得更重要,哪怕后者实际承载更多经济信号。

Permutation 重要性换了个思路:把某一列在数据上随机打乱,打断这个特征和目标之间的关系,看模型性能掉多少,每个特征都来一遍。它与模型无关,测的是特征真实的边际贡献。坑在于特征相关时,打乱一个特征会让信息从别的特征那里漏过来,模型还能找回一部分信号,于是重要性被低估。修法是条件 permutation 重要性,在相似特征取值的子组里打乱。

SHAP(SHapley Additive exPlanations)基于博弈论,把模型对单个样本的预测精确分解成每个特征的贡献,加起来正好等于预测值。它有理论依据——在一系列公理下它是唯一的归因方案——并且跨模型一致。坑是计算开销(最坏情况下随特征数指数增长,虽然有近似),以及全局重要性摘要在特征相关时容易误导。

三种方法的坑各不相同,正好可以互相校验:先用 gain 快速筛一遍,再用 permutation 或 SHAP 验证。三者一致,重要性排序就是真的;三者打架,你面对的就是特征交互或相关性问题,得老老实实做更细致的分析。

不过特征重要性最有用的问法不是”哪个特征最重要”,而是”重要性是均匀摊在多个特征上,还是集中在某一两个”。依赖 5 个特征的模型比依赖 1 个特征的模型稳。集中是脆弱的:那一个特征一衰减,整个模型就塌了。

特征交互:什么时候值得管

线性模型默认每个特征对预测独立贡献。树模型天然能捕捉交互——在 A 上分裂一次再在 B 上分裂一次就是 A×B 的交互——神经网络则靠隐藏层隐式地捕捉。所以”要不要管交互”这个问题,很大程度上就是”该用线性模型还是树模型”。

有两类交互是真的值得管的。一类是跨特征交互,比如动量 × 波动率:低波动下的动量和高波动下的动量脾气不一样,树模型自动能抓,线性模型不显式构造交互项就抓不到。另一类是行情条件交互,比如价值 × 利率水平:价值因子在低利率和高利率环境下表现不同,要表达它你得有一个行情指示特征,或者用一个能学到行情条件行为的模型。

剩下的绝大部分交互不值得显式构造。50 个特征两两交互有 1,225 个,在线性模型里全加进去几乎全是垃圾。真正值得做的,是那些有经济故事支撑的。

判断的办法很直接:先用线性模型跑裸特征。如果线性模型的交叉验证表现和树模型差不多,那交互不重要,线性模型更可取——更简单、过拟合风险更小。如果树模型明显好一截,那交互就重要,你要么留着树模型,要么把那几个有经济动机的交互项显式构造出来。这个对比顺带还给了你一个信息:树模型领先的幅度,大致就是你的特征集里”没被表达出来的结构”的量。

最后

一个常见的时间分配错误是:几个月花在调 XGBoost 的超参上——learning rate、max depth、min child weight、column sampling——最后比默认参数好那么零点几个百分点;同样的时间花在特征工程上,量级上要大得多。模型基本不是瓶颈。

特征才是策略,模型只是实现。大部分量化机器学习的失败,是把实现优化在了一个不存在的策略之上。


参考文献

  • López de Prado, M. (2018). Advances in Financial Machine Learning. Wiley. 第 3 章(Labeling)、第 7 章 §7.3(Why K-Fold Fails in Finance)。ISBN 978-1119482086。
  • Gu, S., Kelly, B., & Xiu, D. (2020). “Empirical Asset Pricing via Machine Learning.” Review of Financial Studies, 33(5), 2223-2273。
  • Jegadeesh, N. & Titman, S. (1993). 动量的原始论文。
  • Novy-Marx, R. (2013). 毛利能力因子。
  • Sloan, R. (1996). 应计异象。
  • Molnar, C. Interpretable Machine Learning, 第 2 版。特征重要性、permutation 与 SHAP 的章节。
  • McKinney, W. Python for Data Analysis, 第 3 版. ISBN 978-1098104030。滚动统计和分组运算的实现细节。