瞿才应
← 回到主页的项目列表

课题组研究项目 · 选股与滚动验证

成本约束下的机器学习选股与滚动验证

模型能排对方向,但没有找到可靠的净超额。我在沪深全 A 上做滚动样本外回测,把交易成本、成交限制和统计检验一起放进研究流程。复杂方案没有显著跑赢简单方案,按看结果前写定的规则冻结简单方案,再留出保留期和每日模拟盘检验。

  • Python
  • pandas
  • LightGBM
  • BH-FDR
  • Clarabel
  • BaoStock
results沪深全 A · 简单方案
样本外日秩 IC
0.086
分数与未来收益的名次相关,开发期
年化净信息比率
0.41
扣完成本,相对合格池等权基准
复杂对简单
p = 0.84
块 bootstrap,未显著跑赢
2025 年保留期
−0.43
年化净信息比率,区间跨零
01

问题和做法

很多选股结果只看排序准不准,或一条不扣成本的收益曲线。我想检查,把手续费、滑点和 A 股成交限制加进去以后,机器学习的优势还剩多少。

秩 IC 比较模型给股票排的名次与之后 5 日收益的名次。它为正,只说明排序方向有用。组合每天的收益减去基准收益,才是主动收益;每天主动收益的平均值除以波动,再换成年化,就是信息比率。排序、净收益和可靠的超额是不同的问题。

基准统一用 0.95 × 前一日合格池等权,收盘到收盘、不计成本。合格池是当日可交易、非风险警示股(ST)、上市满 180 个自然日、20 日平均成交额不低于 1000 万元且基础特征齐全的股票,再按成交额取前 1800 只。这里的信息比率不是相对市场指数算的。

时点数据BaoStock 原始日线封成快照,保留区间内退市的 245 只,先查数据可用时点
滚动预测2020–2024 年切成 10 折,只用测试期之前的数据训练和验证
分数到持仓收盘决策、次日开盘成交,每 5 个交易日调仓,扣成本并限制换手
独立核账与检验从成交流水重算现金和净值,按预先写好的主要检验与冻结规则判定

只用当时看得到的东西

标签从次日开盘起,覆盖 5 个交易日。跨入验证或测试区间、还没成熟的训练标签剔除。每折训练 756 个交易日、验证 126 日、测试一般 126 日,最后一折到数据截止日结束。模型参数固定,训练到验证误差不再改善时停止。

可疑字段按原规则退出

30 个公司年里,3 个在年报公告前出现每股收益跳变,看起来更像供应商更新偏晚和瞬时错误,未证实是前视。但闸门不豁免这种情况,15 个估值因子整组不用,候选从 183 个降到 168 个。

最终冻结的是简单方案

LightGBM 是在表格特征上学习的树模型,用 10 个量价特征打分。线性规划按分数效用减费用来配仓,加每次 30% 双边换手上限,初次建仓除外。仓位不超过 95%、单股不超过 4%。不是因子库,也不是均值方差组合。

账本要能按成交还原

T+1 表示当天买入,下个交易日才能卖。整手、停牌、涨跌停、除权和退市逐笔记。佣金按成交额 3 个基点、最低 5 元,另记过户费、卖方印花税和 10 个基点滑点。每次运行后由独立脚本重算,不从记账代码导入费率规则。

复杂对照换成因子库信号,组合层用风险模型,在预期收益、成本和风险约束之间配仓,称为均值方差组合。因子只在每折训练窗里筛,BH-FDR 控制一批检验里错误发现的比例。信号层与组合层交叉搭配,共用股票池、快照、折和账本;主要检验只比事先定好的复杂与简单两个候选。

02

讲解片

explainer网页原片 · 8:43

在浏览器里按原分辨率播放,带字幕。也可以在 B 站看。

03

开发期结果,成本和复杂度都要算

简单方案,扣交易成本前后的累计主动收益

2020–2024 年;逐日主动收益的算术和,不是复利净值。灰线为零费用重跑,蓝线含税费与 10 个基点滑点。

扣完成本零费用重跑
看数据表
行情日期扣完成本累计主动收益零费用重跑累计主动收益

曲线与表格使用同一组抽样点,保留年末点;累计值先从完整逐日收益计算,再抽样。

零费用情景的信息比率是 0.64,加税费和滑点后是 0.41。两边复用相同预测,但扣费会改变现金,整手取整和之后成交也跟着分叉,所以两条曲线的差不能全归到直接扣费。冻结方案日均双边换手约 6%,年费用拖累约 3%,与年化主动收益 5.8% 是一个量级。

简单方案逐年净信息比率

同一基准、同一成本口径;零线左边跑输,右边跑赢。

看数据表
年份日秩 IC年化净信息比率
20200.079−0.67
20210.069−0.11
20220.095+1.28
20230.082−0.38
20240.104+1.69

每年的平均 IC 都为正,净信息比率却有三年为负。开发期的绝对收益年化只有约 +2.5%,它和 5.8% 的年化主动收益不是同一个数。排序方向稳定,不代表扣成本后的组合年年有效。

复杂方案点估计更高,检验没分出来

唯一的主要比较,复杂对简单

LightGBM,10 个基点滑点,开盘价成交,初始资金 100 万元;比较年化净信息比率。

简单方案,最终冻结复杂方案,对照
看数据表
搭配年化净信息比率用途
10 个量价特征 + 成本约束0.41简单候选,冻结
因子库 + 均值方差0.54复杂候选,主要比较
因子库 + 成本约束1.18只报告,不参与冻结
10 个量价特征 + 均值方差−0.24只报告,不参与冻结
主要检验数值
复杂 − 简单+0.13
差值标准误0.62
双侧 p 值0.84
80% 功效的最小可检出差1.73

检验把连续 20 个交易日当作一块,两列主动收益按同一组块一起重抽 10,000 次,保留它们之间的相关和日收益的自相关。这是学生化循环块 bootstrap,差值标准误还考虑了收益的时间相关。

观测差只有 +0.13,标准误 0.62,p = 0.84。按这次的估计,真实差距约到 1.73,检出的把握才有八成。这不是低于就一定检不出的硬门槛,也不等于两种方案一样好。

decision四条条件须同时满足
条件看结果前写定的要求结果
主比较p < 0.05,且复杂对简单的差为正未满足
线性对照Ridge 的同一比较也为正,实际为 −0.56未满足
交叉对照复杂方案不低于另外两格,实际低于 1.18未满足
运行条件无解或放宽风险限额的调仓日不超过 5%,两侧跟踪误差(主动收益的年化波动)不低于 2%满足

四条只满足一条,照规则冻结简单方案。最高的 1.18 不是事先声明的候选,不能看完四格再挑它。均值方差组合在声明参数下日均换手约 20%、年费用拖累约 11%,但组合层还同时改变了目标函数、约束和候选集,不能把差别全算作均值方差本身的效果。

04

保留期和每日模拟盘

2025 年是事先留出的保留期。冻结后只开一次,用固定的一次训练、验证切分,整年不重训。开发期按折滚动重训,两段的训练频率不同。

2025 保留期与冻结后补做的历史样本

点为年化净信息比率,横线为 95% 块 bootstrap 区间。2026 是 183 个交易日的部分历史样本,非全年。

看数据表
样本年化净信息比率95% 区间定位
2025 年−0.43−2.02 至 +1.25事先留出,只开一次
2026 年部分样本0.24−2.20 至 +2.64冻结后补做,只描述

2025 年组合年化绝对收益 +13.4%,相对基准的年化主动收益却是 −7.7%。组合对合格池的 beta 为 0.32,意思是每天涨跌与池子联动的幅度较小,不能理解成全年只拿到池子收益的三成。同期合格池全年涨了 20.3%,所以绝对赚钱不等于跑赢基准。

2025 年的区间跨零。按这次估计,真实信息比率约到 2.85,检出的把握才有八成,一年数据还不足以判断策略好坏。后来补做的样本是看到保留期为负后才决定追加的,声明写在计算它的结果之前。它不是第二个保留期,也不是真正的前向证据,不改冻结配置。

模拟盘要检验冻结之后的运行

增量取数取当日行情,过数据闸门,封存快照
按冻结方案打分交易代码由哈希锁定,变动就拒绝运行
指令与账本次日开盘模拟成交,重放历史逐行核对,只追加新记录
日报和告警累计风格与行业贡献,取数失败、闸门失败或重放不一致时告警

每天收盘后自动跑,不下真实订单。模型、政策、参数、股票池和成本假设保持冻结。哈希是代码与配置的数字指纹,防止无意中换了一套交易规则;记录只追加不等于人不可能删文件。

已留存的模拟盘结果快照

非当前累计结果;含建仓费用。两个数都是百分比,不是信息比率,也不年化。

看数据表
指标留存记录口径
净值变化−1.06%含建仓费用
累计主动收益−1.28%从首个成交日起,逐日主动收益算术相加

这份记录小亏,也跑输了基准。周报按固定交易日长度折算后,仍在开发期的正常波动区间内,没有触发收益异常告警。日报的归因显示,追回来的那部分主要来自风格和行业,不能凭这段结果判断独立选股能力。

  • 建仓和费用有单独记录。24 笔全部模拟成交,费用 1,221.36 元,包含滑点。建仓费用不混进日常换手的比较。
  • 闸门确实拦过异常。退市整理期的特殊价带没被规则覆盖,行情核对无误后按协议人工确认,记成无信号,不改交易代码。那次不需要调仓,对交易没有影响。
  • 回测与模拟盘评估窗口分开。上面的 0.41、−0.43、0.24 沿用研究报告口径,包含全现金的首日。模拟盘主动收益从首个成交日起算,首个成交日的基准用开盘到收盘,之后用收盘到收盘,不混用两套信息比率。
05

为什么排序有用,可靠超额却没留下

先看模型选了什么,再看组合挣的是什么。自建风险模型显示,冻结配置偏向低特质波动、低流动性。特质波动是扣掉市场涨跌影响后的残差波动;这里的流动性用平均换手率衡量,不是成交额。

原始分数和剔除行业、风格后的日秩 IC

中性化只处理分数,标签不动;补充分析,不改变主要检验和冻结结果。

原始分数中性化分数
看数据表
样本原始 IC中性化 IC分数对暴露的截面 R²
2020–2024 开发期0.0860.0210.68
2025 保留期0.0980.0350.76
2026 部分历史样本0.0700.0190.76

每天把分数截尾,对行业和六个风格做回归,只留它们解释不了的残差,再算秩 IC。开发期从 0.086 降到 0.021,只剩约四分之一;不能把“四分之一”套到另外两段。R² 0.68 到 0.76 则表示分数的截面差异大多能被这些暴露解释,是另一个问题。

中性化口径在保留期打开后,随冻结后补做的样本外声明写定。开发期和 2025 年按同一口径补算,只作描述,不是事先的主要检验。

组合超额大头是风格

开发期低特质波动、低流动性两项的年化贡献约 +12.5%、+9.2%。风格加行业合计约 +12.2%,净主动收益只有 5.8%,加回约 3% 成本也只有约 8.8%。粗算个股层面的剩余约 −3.5%/年,没有留下正的独立超额。

比较的基准本身偏弱

2020–2024 年合格池等权几何年化 −4.7%,不截成交额前 1800 只的宽口径等权为 +8.9%。避开成交额最大的那批,本身就能产生相对优势,所以不能把相对合格池的收益全叫作选股能力。

风格归因和基准拆分是开发结果出来后补的描述。归因与主动收益覆盖的交易日略有差别,个股剩余是近似,不是严格相减得到的检验结论。

06

能说什么,不能说什么

能说

  • 在这份数据、成本与成交假设下,没有检出复杂方案对简单方案可靠的优势,按预先规则冻结了简单方案。
  • 原始分数有排序能力,开发期大部分可见超额由低特质波动、低流动性风格解释。
  • 时点、交易限制、费用、账本和冻结过程留有审计记录;模拟盘能检查每日取数与运行是否按协议执行。

不能说

  • 不显著不是两者等效,也不是简单方案更好。1.18 只报告,不能按它事后换方案。
  • IC 为正、绝对收益为正,都不能直接证明有稳定的独立超额;风格中性化的 IC 仍为正也不等于能变成组合收益。
  • 免费数据没有独立时点认证,少数除权按参考价近似;固定滑点和开盘成交没有真实成交回报校准。
  • 模拟盘不下真单,短期收益说明不了策略好坏;冻结方案没有测容量,不能据复杂对照的容量网格替它报数字。

下一轮会把风格当风险在组合层控制,另写规则,用冻结之后的数据检验。看过的保留期和补做样本不能再拿来挑参数。回测和模拟盘不代表未来收益,不构成投资建议。

07

术语速查

日秩 IC
每天在股票之间,比较模型分数名次与未来收益名次的相关,再对交易日取平均。只看排序,不直接衡量收益。
主动收益
组合收益减去指定基准收益。本页累计主动收益是逐日差值的算术和,不是复利净值。
年化信息比率
每天主动收益的平均值除以标准差,乘年化系数。既看超额的方向,也看它的波动。
滚动样本外
训练、验证、测试按先后滚动,测试期预测只由此前的数据得到。跨段未成熟标签要剔除。
换手与滑点
双边换手把买入和卖出金额都算上,再除以净值。滑点是实际或假设成交相对参考价多付的成本。
块 bootstrap
成块重抽连续交易日,两条策略一起抽,保留时间相关与策略之间的相关,再估计差值的不确定性。
保留期
不用于选模型和调参数的留出历史区间,冻结后才开。它仍是历史数据,和真正向前的模拟盘不同。
风格中性化
把分数对行业和已定义风格回归,取残差再看排序能力。这里没有改标签,也没有重新训练一个中性模型。
哈希冻结
给源码、配置、依赖和历史数据记数字指纹,开保留期或运行模拟盘时核对。开启凭据不能覆盖,失败也留痕。
→

其他项目