这两年做量化研究的朋友聚在一起,聊得最多的就是深度学习到底能不能在金融里落地。我自己的感觉是,这个问题不能简单用“能”或者“不能”来回答。深度学习方法在金融场景里确实能做出一些传统线性模型做不了的事,比如捕捉非线性关系、处理高维稀疏特征、在时序数据里挖掘长期依赖,但它也绝对不是拿来跑个 LSTM 就能躺赚的银弹。这篇文章我想结合自己从数据清洗到模型部署的一整套实操经验,聊聊深度学习在金融应用里真正值得关注的技术细节,以及那些文档里不会写、只有踩过坑才知道的注意事项。
我不打算讲花哨的数学推导,重心放在工程落地上:数据怎么处理才不算作弊,模型怎么选才匹配场景,回测怎么设计才可信,部署之后怎么监控才能活下来。对于想把深度学习方法引入量化或者风控流程的开发者、数据工程师和研究员,这篇文章应该能帮你省下几个月的试错时间。
1. 深度学习做金融:先把场景想清楚再动手
1.1 金融里的深度学习,到底解决的是哪几类问题
很多人一提“深度学习金融应用”,脑子里第一个蹦出来的就是股价预测。这没错,但预测只是其中一小块。我按自己的经验把金融里的深度学习任务分成了三类,这样讨论起来更清楚。
第一类是预测类任务,包括价格方向、收益率、波动率、流动性指标。这类任务的特点是信噪比极低,市场里大部分波动是噪音,模型很容易学到“看起来有用、实则随机”的模式。第二类是分类识别类任务,包括信用风险评估、违约预测、欺诈交易识别、异常账户检测。这类任务里标签相对明确,正负样本之间的模式差异也更大,深度学习的效果通常比传统方法明显更好,也是金融行业里落地最早、最成熟的场景。第三类是生成与模拟类任务,比如合成交易数据用于回测、情景生成用于压力测试、用强化学习做订单簿模拟等,这类应用相对前沿,但对工程能力要求很高,一般团队不建议一上来就碰。
把这三种场景分清楚非常重要。因为它们的评价标准完全不一样:预测类任务看的是预测准确性之外的东西,比如信息系数、换手率、稳定性;分类任务更看重召回率、精确率和误报率之间的平衡;生成任务则看重分布相似度和下游任务收益。如果一开始没想清楚自己在做哪一类问题,后面所有设计都会跑偏。
1.2 为什么是现在:数据、算力、模型三件事同时变了
深度学习在金融里并不是新概念,十年前就有人尝试,但当时做不出效果。我分析下来,不是算法不行,而是三个基础条件没到位。
数据方面,以前能拿到的行情数据基本就是日线或者分钟线,特征维度少得可怜。现在除了逐笔委托、订单簿快照这类高频数据,还有新闻、公告、社交情绪等另类数据,数据广度完全不一样了。算力方面,一张消费级显卡就能训练几百万参数的模型,这在十年前的量化团队里是不可想象的。模型方面,LSTM、Transformer 这些架构在处理长序列依赖上确实比传统 ARIMA、GARCH 这类统计模型更灵活,能自动从数据里学出交互关系。
但我要泼一盆冷水:基础条件变好,不代表深度学习在金融里变得容易。恰恰相反,数据变多了,假信号也变多了;模型变强了,过拟合的杀伤力也更大了。金融数据的本质特征——非平稳性、低信噪比、小样本——并没有因为深度学习的出现而改变。理解了这一点,再看后面所有技术细节,你就会有不一样的心态。
2. 数据与特征工程:金融数据的坑比模型多
2.1 行情数据的三道坎:幸存者偏差、前视偏差、复权问题
做深度学习金融应用,我最想强调的一句话是:数据质量决定模型上限,模型只是在逼近这个上限。金融数据里藏着三个很容易被忽略的坑,每一个都可能让你的模型在回测里光芒万丈、在实盘里一败涂地。
第一个是幸存者偏差。如果你用的是当前还在上市交易的股票集合做训练,那模型天然学习的是“活下来的公司”的特征,而实盘里你随时可能遇到退市、停牌、被 ST 的标的。规避方法只有一个笨办法:用历史某一天的成分股快照,而不是今天的全量列表。这个数据处理细节会直接影响训练样本的分布,处理不好,模型的所谓“超额收益”里有一部分其实是幸存者带来的虚假优势。
第二个是前视偏差,也叫 look-ahead bias。这是回测结果失真最常见的原因。比如你用某个时间点的财务数据预测未来收益,但这个财务数据实际发布日比截止日晚了好几个月,如果直接用“截止日”而不是“发布日”对齐,模型就等于提前看到了未来信息。金融数据里到处是这样的“时间陷阱”:财报发布滞后、指数调仓公告滞后、宏观经济数据修正滞后。我的处理原则很简单:所有特征必须用“当时真实可得”的数据,宁可损失一部分样本,也不要冒险用未来信息。
第三个是复权问题。很多人下载行情数据后直接拿收盘价做特征,这是错误的。因为分红送股会导致价格跳空,这些跳空不是真实的市场波动,却会被模型当成有效信号学习。正确做法是用后复权价格或者前复权价格计算收益率,建模时全部用复权后的对数收益率,而不是原始价格。
2.2 特征怎么造:从原始行情到可用因子
特征工程在金融深度学习里占据了至少一半的工作量。我见过很多团队把时间花在调网络上,最后发现特征设计和处理方式对结果的影响远大于模型结构。
先说标准化。金融序列的绝对价格水平没有意义,真正有意义的是收益、波动、相对强弱。所以我一般会这样处理:价格序列全部转成对数收益率,然后按滚动窗口做 z-score 标准化。滚动窗口的取值也有讲究,短了(比如5天)噪声大,长了(比如250天)反应慢,我通常在实践中取60到120个交易日作为标准窗口,具体要看标的的交易频率。
再说特征类型。我常用的特征可以分成四类。价量类特征包括收益率、换手率、振幅、成交量变化率,它们刻画的是市场微观结构的活跃程度;技术类特征包括 RSI、布林带位置、MACD 柱、均线偏离度,用来描述趋势和超买超卖状态;横截面特征包括个股在过去 N 日的收益在全市场所有股票中的百分位排名,这类特征在选股场景里特别重要,因为金融市场里的大部分收益差异来自相对强弱而非绝对方向;另类特征包括新闻情感得分、公告事件类型等,这些特征稀疏且噪声大,需要额外的降维处理。
这里补充一个横截面特征的例子。做多因子选股时,与其直接输入个股的 20 日涨幅(市场大涨时所有股票都在涨,这个特征的绝对数值带上很强的市场共性),不如输入该涨幅在全市场所有股票中的排名分位(消除市场整体趋势的影响,保留个股间相对强弱信息)。这样一个简单的变换,经常能让模型效果出现明显提升,因为深度学习模型虽然理论上能从数据里自行学到横截面比较,但在有限样本下你替它把这一步做了,它学起来会轻松得多。
2.3 标签怎么定:这决定了模型到底在学什么
很多初学者问我的第一个问题是“用什么模型”,我通常反问“你的标签怎么定的”。因为标签设计直接决定了模型学习的目标,而这个目标一旦定错,再好的模型也白搭。
预测任务里最常见的标签是“未来 N 日收益率”,然后训练模型做回归。这个做法直观,但有个问题:它假设未来收益服从某种连续分布,且模型所有预测误差的代价是对称的。实际交易中,做多和做空的不对称性、止损和对冲机制的存在,使得单纯的收益率回归可能与真实目标存在偏差。
我见过比较成熟的做法是三级障碍标注法(triple-barrier labeling)。具体来说,设定一个盈利目标(比如上涨 3%)、一个止损阈值(比如下跌 2%)和一个最大持有时间(比如 20 个交易日)。标签的取值规则是:如果先触及盈利目标,标签为 1;如果先触及止损阈值,标签为 -1;如果持有到期仍未触及任何一侧,则以到期时刻的收益方向作为标签。这样的标签模拟了真实交易中的止盈止损逻辑,模型学出来的东西更贴近实际可执行的策略,而不是纯粹的理论收益。
无论选哪种标注方法,还有一个关键参数必须谨慎处理:预测周期。预测周期太短(比如 1 分钟),信号噪声极大且交易成本会吃掉大部分收益;预测周期太长(比如 60 天以上),样本数减少,且市场结构可能已经发生了根本性变化。我在实践中通常先试 5 到 20 个交易日的预测窗口,对比不同窗口下的信息系数再决定。
3. 模型架构与训练策略:别一上来就堆 LSTM
3.1 常见时序模型怎么选:LSTM、GRU、TCN 还是 Transformer
模型选择是大家最感兴趣但最容易走偏的环节。我的建议是:先理解不同模型的适用场景,再根据自己的数据量决定,而不是谁论文效果好看就选谁。
LSTM 是金融时序建模最经典的入门选择。它的优势在于通过门控机制记住长时间跨度的信息,适合捕捉序列里的长期依赖,比如宏观经济周期对资产价格的影响。但 LSTM 参数量大、训练慢,在小样本金融数据上很容易过拟合。GRU 可以理解为 LSTM 的简化版,参数更少,在小数据集上通常比 LSTM 更稳,训练速度也更快。我做对比实验时,很多场景下 GRU 的效果与 LSTM 持平甚至略好,所以如果预算有限,可以先从 GRU 开始。
TCN(时序卷积网络)是经常被低估的一个选择。它用膨胀因果卷积来处理序列,感受野可以灵活调整,训练速度比循环网络快得多,而且没有梯度消失问题。在中等长度序列(几百步以内)的特征提取上,TCN 的表现往往不输 LSTM,还更稳定。Transformer 在金融场景里是双刃剑:它的自注意力机制能捕捉长距离依赖和特征间的复杂交互,但需要大量数据来训练,对学习率极度敏感,在小样本上容易出现训练不稳定和过拟合并存的问题。我在只有几千条样本的场景下不敢轻易上 Transformer,但如果数据量达到百万级且特征维度够丰富,它是值得尝试的。
还有一点必须提醒:不要把多种模型结构堆叠成一个巨大的混合体。金融数据里的信号本来就弱,模型容量越大,越容易把噪声当成信号学进去。我的经验是先跑一个简单的基线(比如 GRU 或者带正则项的线性模型),确认数据处理链路没问题了,再逐步升级模型复杂度。
3.2 训练集切分:时序数据不能随便打乱
普通机器学习里常见的随机打乱训练集做法,在金融场景里绝对不能直接用。因为金融数据是强时序相关的,相邻样本之间高度依赖,随机打乱会造成严重的数据泄漏——模型在训练时已经“见过”测试集对应的市场状态了,验证结果自然虚高。
正确的做法是用滚动前推验证(walk-forward validation)。核心逻辑是:训练集始终使用过去的数据,验证集严格使用时序上更晚的数据,然后不断向前滚动窗口。比如初始用 2019 到 2021 年的数据训练,验证 2022 年上半年,然后再把 2022 年上半年并入训练集,验证 2022 年下半年,如此反复。
这里还有一个进阶细节:清理验证集样本在时间上靠近训练集末尾的“泄漏边缘”。因为金融序列的自相关性,训练集最后几天的影响会扩散到验证集最初几天。解决办法是在训练集和验证集之间留出一段“禁区”(embargo),比如如果预测周期是 10 天,那就把训练集末尾 10 到 20 天的数据删掉不进训练,以此切断时间泄漏。这个细节很多教程不会提,但对结果可信度的提升非常明显。
3.3 损失函数与评估指标:金融场景不能只看准确率
金融场景里用得最多的是回归式的损失函数,比如 MSE,或者分类式的交叉熵。但评估模型效果时,我从不只看 MSE 或准确率,而是看几个金融领域特有的指标。
信息系数(IC)是最常用的一个,计算方式是模型预测值与未来实际收益之间的 Spearman 秩相关系数。它衡量的是模型的排序能力而不是绝对预测精度,而在选股和资产配置场景里,排序对了才能赚钱。Rank IC 是它的变种,更关注预测值在横截面上的排序与真实收益排序的一致性。信息比率(IR)则是把超额收益的均值除以超额收益的标准差,衡量策略的收益稳定性,比总收益指标更能反映风控水平。
我见过一个团队做的 LSTM 模型,MSE 压得很低,准确率看着也不错,但 IC 长期在 0.02 以下,这意味着模型排序能力基本等于随机。如果他们只看准确率,可能会被误导很久。所以我的建议是:训练阶段用 MSE 或交叉熵这类标准损失让模型收敛,但模型筛选和参数调优阶段,必须用 Rank IC、IR 这类金融导向的指标来做最终决策。
另外,预测的稳定性也很重要。一个模型的 IC 均值是 0.05,但每个月波动极大,另一个模型的 IC 均值稳定在 0.03,波动很小,长期看后者的实际表现往往更好,因为策略执行时不需要承受巨大的回撤和心理压力。
4. 回测与部署:能不能落地全看这一步
4.1 回测不是算个收益曲线就完事
很多研究死在回测这一步,是因为把回测想得太简单了。深度学习模型的预测只是一串数字,要变成策略收益,中间隔着交易执行、成本、冲击、风控等一整套环节。
回测里最容易低估的是交易成本。我见过不少团队在回测里假设零成本或者万分之一成本,结果模型换手率极高,实盘里光手续费和滑点就把收益吃光了。更合理的做法是给每一次交易都加上两部分成本:固定部分,比如佣金和印花税;可变部分,按成交金额的一定比例模拟滑点。如果做的是分钟级或更高频的策略,还要额外建模市场冲击——大单成交时对价格的影响,这部分在高换手策略里是利润的隐形杀手。
回测框架里另一个致命问题是未来函数。比如你在信号计算里用了当天的“收盘后才知道”的数据,但实际交易是在盘中执行的,这就是典型的未来函数。我排查未来函数的方法比较笨但有效:在回测引擎里加一个数据时间戳检查,任何特征数据和信号之间如果存在“同位取用”的嫌疑,就单独跑一天的逐笔复盘,人工核对信号产生时哪些数据窗口是真实可得的。
回测输出的指标也不能只看年化收益和最大回撤,我建议至少要记录:换手率、交易次数、单次平均持仓时间、每个月或每个季度的收益分布、不同市场状态下的表现(上涨段、下跌段、震荡段的分别回测)。这些信息在判定模型是否值得实盘时有决定性作用。一个只在特定市场状态有效的模型,和在全市场状态下都稳定的模型,实盘策略完全不同。
4.2 最小可用的部署闭环
从回测到实盘,是一个巨大的鸿沟。第一次上实盘时不需要做复杂的分布式系统,先搭一个最小可用的闭环就够了。
我建议的部署架构是:离线阶段,用历史数据训练模型,把权重和标准化参数固化导出;在线阶段,定时拉取最新行情和因子数据,按与训练时完全一致的流程计算特征,送入模型获得预测,再经过一层简单的风控过滤(比如最大仓位限制、单日最大亏损限制、流动性过滤)后,生成交易信号。
这个架构里有几个容易被忽略的细节。第一是模型输入和训练时的一致性,实盘里的特征计算顺序、标准化参数、缺失值填充方式必须和训练时一模一样,任何一步不一致都会导致预测偏移。第二是延迟控制,LSTM 或 Transformer 的推理如果走 GPU 通常没问题,但特征计算环节如果写得不好,行情数据到了之后迟迟算不完,信号就失效了。我的经验是把特征计算做成增量式,只对最新一个时间步计算,而不是每次都全量重算整个历史窗口。第三是监控,模型输出的分布、预测值的变化幅度、特征的分布漂移,这些都需要持续记录,一旦发现分布异常偏移,就要触发告警和重新训练流程。
再补充一点:千万不要在实盘里直接使用未经充分验证的在线学习方案。金融数据非平稳,理论上在线学习可以自适应,但实际中模型更新过快会带来严重的过拟合风险——最近一段时间的市场模式可能只是暂时的噪声结构。我在实践中更倾向于固定周期(比如每两周)用最新数据重新训练一次,而不是每个 bar 都增量更新,这样模型稳定性会好很多。
5. 实操中踩过的坑与排查清单
5.1 模型在测试集上表现好,实盘就崩,通常是这三个原因
这个问题我听过无数次,也亲身经历过,原因逃不出三点。
第一是特征数据泄漏。最典型的又是前视偏差:训练集里用了“未来才能知道”的数据,模型在测试集上当然表现好,一上实盘就失效。排查方法是重新审计每个特征的时间戳,尤其是手工构造的因子,必须确认每个时间点的取值只使用了该时间点之前可获得的信息。
第二是算力换来的过拟合。深度学习模型容量大,参数多,在有限的历史数据上极易记住噪声。当市场进入一个新的状态时,模型对噪声的记忆无法迁移,表现自然崩塌。排查方法是做严格的滚动前推验证,并且对比模型和简单基线(比如线性回归、动量策略)在真实交易样本上的表现差异——如果差异过大,就要警惕是不是过拟合了。
第三是忽略了市场状态切换。金融数据具有明显的非平稳性,牛熊切换、政策变化、流动性环境改变都会让模型学到的模式失效,这不是模型本身的错,是训练分布和上线后分布不一致导致的。应对方法是在部署后的监控里加入市场状态识别模块,比如用波动率集聚指标判断当前处于高波动还是低波动环境,当模型训练的分布属性与当前环境出现显著偏离时,回退到低风险模式或暂停信号输出。
5.2 训练不稳定、数据对齐错误:几个高频翻车现场
训练不收敛或者震荡,是深度学习中最好排查的问题,金融场景里也不例外。我先说最常见的梯度爆炸。金融收益率序列里偶尔会出现极端值(比如某天跌停、某只票一日暴涨),这种极端值如果进入特征计算,很容易让梯度瞬间爆炸。解决办法有两个:一是数据处理阶段对特征做 winsorize(把超出比如 99% 分位的极端值压缩到分位边界),二是在训练时启用梯度裁剪,设置一个合理的最大值比如 1.0。这两个措施合在一起,训练稳定性会有质的提升。
学习率过大也是训练震荡的常见原因。金融数据信号弱,模型容易对噪声产生剧烈响应,学习率稍大就会在最优解附近来回横跳,甚至发散。我通常用学习率扫描(learning rate finder)来确定初始学习率,从 1e-4 到 1e-2 之间对数均匀采样,画出损失下降曲线,选择下降最快的那个峰值区间往下调一个数量级作为初始值。
再说数据对齐错误。这个问题最具迷惑性,因为程序不会报错,但结果就是不对。具体场景是:模型预测 T 日的信号,对应的是 T+N 日的收益,但你在回测时把信号和收益做了同一时间的对齐,导致预测和标签之间错位了 N 天。排查方法很简单——写一个单元测试,用人工构造的序列验证数据对齐逻辑是否符合预期。我建议任何金融建模项目的第一行代码都先做这个对齐测试,看似简单,能省掉很多后期抓狂的时间。
5.3 常见问题速查表
我把实操中高频遇到的问题整理成一个速查表,方便各位对号入座:
| 现象 | 可能原因 | 排查方向与对策 |
|---|---|---|
| 训练损失不下降 | 学习率过大或过小 | 做学习率扫描,检查特征是否标准化 |
| 损失下降但验证 IC 一直很低 | 标签设计不合理或预测周期不当 | 尝试更换标签(如三级障碍法),调整预测周期 |
| 回测收益很高但换手率惊人 | 交易成本未被合理建模 | 加入成本和滑点,观察收益衰减幅度 |
| 训练集和验证集都很好,实盘不行 | 数据泄漏或特征时间戳错误 | 逐特征审计时间戳,留出 embargo 区间 |
| 模型对极少数股票预测极端值多 | 特征未做 winsorize 或标准化窗口不足 | 压缩极端值,增大标准化窗口 |
| 训练过程中损失突然 NaN | 梯度爆炸或特征含 NaN | 梯度裁剪、检查数据缺失值填充 |
| 部署后模型输出分布与训练时偏移 | 市场状态切换或特征分布漂移 | 监控分布指标,设置预警并考虑重新训练 |
每个问题背后对应的排查时间可能从半天到几天不等,但只要你把数据链路检查做扎实,大部分问题都能在建模早期发现,而不是拖到实盘阶段才暴露。
最后再分享一点个人经验。我每次看到一个漂亮得不像话的回测曲线,第一反应不是兴奋,而是怀疑——去找是否存在未来函数、标签泄漏、或者某个我没有注意到的对齐问题。这个习惯在实战中救了我很多次。深度学习在金融里的核心能力不是“预测未来”,而是“在大量数据中筛选出勉强可用的规律,并诚实地评估这些规律的稳定性”。理解了这句话,你就已经跑赢了大多数一上来就调参的人。