量化投研中的缓慢变化维:从因子定义到回测可复现的底层逻辑


引言:回测里最隐蔽的"未来函数"陷阱

量化研究中,最让研究员头疼的问题之一不是策略亏钱,而是回测赚钱、实盘亏钱------而且找不出原因。

很多时候,根子不在模型,而在数据。

设想这样一个场景:

你用"申万一级行业分类"作为特征因子训练了一个选股模型。2023年6月,某股票从"房地产"调入"建筑装饰"行业。你用2024年的快照数据跑2023年的回测------这只股票全程被标记为"建筑装饰"。模型在2023年学到的"建筑装饰行业溢价",实际上偷看了未来的行业归属

这就是典型的"未来函数"问题。而它的本质,正是维度属性随时间缓慢变化,但数据仓库没有正确建模

在量化投研体系中,特征因子(factor)本身就是一种维度数据------它们描述股票、期货、基金等标的在某一个时间点的状态。这些状态会变,而且变化频率远低于逐笔行情,但一旦变了,就会直接影响回测的准确性

缓慢变化维(SCD),就是解决这个问题的系统性框架。


量化场景中的 SCD 类型映射


Type 0:不可变属性------因子的"出生证"

典型场景:股票首次上市日期、原始证券代码、IPO 时的发行方式

Type 0 写入后永不更新。在量化中,这类属性是时间锚点,用于计算上市年限、新股因子、事件研究等。

复制代码
股票维度表(节选):
证券代码  | 上市日期   | 交易所 | 证券类型
000001.SZ | 1991-04-03 | 深交所 | A股

即使后来该股票被借壳、更名、迁址,上市日期永远不变。研究员计算"上市满3年因子"或做事件研究时,依赖的就是这个不可变锚点。


Type 1:直接覆盖------修正而非变更

典型场景:股票简称更正、Wind/聚源数据源的字段纠错

Type 1 用新值直接覆盖旧值,不保留历史。

复制代码
股票维度表(修正前):
证券代码    | 证券简称 | 总市值(亿)
000001.SZ  | 平安银   | 2,100    ← 简称录入漏字

股票维度表(修正后,Type 1 覆盖):
证券代码    | 证券简称 | 总市值(亿)
000001.SZ  | 平安银行 | 2,100

这种"修正"对量化研究没有影响------你不会用证券简称做因子。但如果覆盖的是因子计算错误(比如某日市值字段因数据源 bug 填错),就需要配合操作日志追溯,确保回测中不会混入脏数据。


Type 2:版本行------量化 SCD 的绝对主力

*典型场景:行业分类变更、指数成分股调整、ST/ST 状态变化、板块归属调整

Type 2 是量化投研中使用最广泛的 SCD 类型 。它通过版本行 + 生效/失效时间,确保回测时每个交易日都能关联到当时正确的因子状态

案例:行业分类变更(最经典的未来函数来源)
复制代码
行业维度表(SCD Type 2):

证券代码    | 行业分类标准 | 行业代码 | 生效日期   | 失效日期   | 当前标志
000002.SZ  | 申万一级    | 房地产   | 2014-01-01 | 2023-06-14 | N
000002.SZ  | 申万一级    | 建筑装饰 | 2023-06-15 | 9999-12-31 | Y

配合日频特征因子表:

复制代码
日频因子事实表:

交易日     | 证券代码    | 收盘价 | 换手率 | 行业维度关联键
2023-06-10 | 000002.SZ  | 12.50  | 1.2%   | DIM_202301
2023-06-16 | 000002.SZ  | 11.80  | 2.1%   | DIM_202302

当回测引擎在 2023-06-10 计算"建筑装饰行业均值"时,关联逻辑是:

复制代码
WHERE 生效日期 <= '2023-06-10' AND 失效日期 > '2023-06-10'
→ 命中"房地产"那行 → 该股票被归入房地产行业

而在 2023-06-16 计算时:

复制代码
→ 命中"建筑装饰"那行 → 该股票被正确归入建筑装饰行业

回测完全消除了行业分类上的未来函数。

案例:ST 状态变化

ST 状态对量化策略影响极大(很多策略直接剔除 ST 股),而且变更频率不低:

复制代码
股票状态维度表(SCD Type 2):

证券代码    | 特别处理状态 | 生效日期   | 失效日期   | 当前标志
600240.SH  | 正常        | 2022-01-01 | 2023-04-30 | N
600240.SH  | *ST         | 2023-05-01 | 2024-06-30 | N
600240.SH  | 正常        | 2024-07-01 | 9999-12-31 | Y

回测中,2023年5月之前该股票参与选股,5月之后被自动过滤------与实盘行为完全一致。

案例:指数成分股调整
复制代码
指数成分维度表(SCD Type 2):

指数代码   | 证券代码    | 权重(%) | 生效日期   | 失效日期   | 当前标志
000300.SH | 601012.SH  | 1.25    | 2023-06-12 | 2023-12-10 | N
000300.SH | 601012.SH  | 1.42    | 2023-12-11 | 9999-12-31 | Y

这对指数增强策略的回测至关重要------成分股调整日前后,权重和约束条件完全不同。如果只用最新快照,回测中的"跟踪误差"会被严重低估。


Type 3:有限历史------上一次就够了

典型场景:因子值的环比变化、行业迁徙分析

Type 3 在原记录上新增一列存储上一次的值,适合只需要知道"上一次是什么"的场景。

复制代码
行业维度表(SCD Type 3):

证券代码    | 当前行业   | 上一行业   | 变更日期
000002.SZ  | 建筑装饰   | 房地产     | 2023-06-15

用途举例:

"从房地产调入建筑装饰的股票,调入后60个交易日的平均超额收益是多少?"

只需要当前行业和上一行业就能回答,不需要完整变更链。在因子研究中,这种**"迁徙效应因子"**是机构量化中常见的另类特征。


Type 4:历史表分离------因子库的工程优化

典型场景:基本面因子(财务数据)的版本管理

财务数据有一个特殊性质:会追溯调整。一家公司4月发布年报,9月发布更正版------两个版本都是"对的",只是后者更准。量化研究员既需要分析"市场当时看到了什么"(用当时版本),也需要用"最终修正版"做长期因子研究。

复制代码
财务因子主表(当前最新版本):
证券代码    | 报告期     | 净利润(亿) | ROE   | 数据状态
600519.SH  | 2023-12-31 | 747.34     | 32.5% | 已审计终版

财务因子历史版本表:
证券代码    | 报告期     | 净利润(亿) | ROE   | 数据提取日期 | 版本说明
600519.SH  | 2023-12-31 | 735.20     | 31.8% | 2024-04-03  | 初步披露版
600519.SH  | 2023-12-31 | 747.34     | 32.5% | 2024-09-15  | 审计更正版
  • 事件研究(如"年报首次披露后的市场反应")→ 用历史版本表,还原市场当时看到的数据
  • 横截面因子回测(如"用最新 ROE 排序选股")→ 用主表,保证因子质量

这是 Type 4 在量化工程中最典型的应用模式。


Type 6:混合模式------因子平台的终极形态

典型场景:大型量化机构因子库同时服务回测、实盘信号、合规审计

Type 6 组合 Type 2(版本链)+ Type 3(上一值)+ 当前值冗余列:

复制代码
股票维度表(SCD Type 6):

证券代码    | 行业分类   | 生效日期   | 失效日期   | 当前标志 | 当前行业(冗余)
000002.SZ  | 房地产     | 2014-01-01 | 2023-06-14 | N        | 建筑装饰
000002.SZ  | 建筑装饰   | 2023-06-15 | 9999-12-31 | Y        | 建筑装饰
  • 回测引擎:按生效/失效日期精确关联 → 消除未来函数 ✅
  • 实盘信号生成:直接读"当前行业"冗余列 → 低延迟 ✅
  • 合规审计:逐行扫描版本链 → 证明"回测没有数据穿越" ✅

对于需要向监管或 LP(有限合伙人)证明"策略回测严谨性"的量化基金,Type 6 是因子数据平台的理想架构。


量化 SCD 设计的三个关键实践

1. 因子字段的 SCD 类型混搭

同一个股票维度表中,不同因子字段用不同的 SCD 类型:

因子字段 SCD 类型 理由
证券代码 Type 0 不可变标识
证券简称 Type 1 修正性变更
行业分类 Type 2 核心因子,需完整版本链
指数成分权重 Type 2 调仓日精确对齐
ST 状态 Type 2 策略过滤条件,不能穿越
上一行业 Type 3 迁徙效应因子
上市日期 Type 0 新股因子锚点

2. 生效/失效时间的精确约定

量化回测对时间精度要求极高,建议约定:

  • 行业分类、ST 状态等定期调整类因子:以公告生效日为准(A 股通常为交易日)

  • 财务数据类因子:以实际披露日为生效日期(不是报告期!),否则会引入未来函数

  • 失效日期统一用 9999-12-31 表示当前有效版本

    -- 回测中查询某交易日的行业归属
    SELECT 行业代码
    FROM 行业维度表
    WHERE 证券代码 = '000002.SZ'
    AND 生效日期 <= '2023-06-10' -- 注意:用实际披露日,不是报告期
    AND 失效日期 > '2023-06-10'

3. 变更检测的工程实现

量化因子库的 SCD 变更检测通常由以下方式触发:

  • 公告日历驱动:跟踪交易所/指数公司的定期公告(如中证指数成分股调整公告)
  • 数据源 diff:每日对比 Wind、聚源、Tushare 等数据源的快照,检测字段级变更
  • 财务数据版本管理:在每次财报季,按"数据提取日期"建立新的版本行

结语:SCD 是量化回测可信性的底线

量化投研的核心信条是**"回测可复现"。但可复现的前提,不是代码写对了,而是数据在时间维度上的语义是正确的**。

一个没有正确建模 SCD 的因子库,就像一栋地基不稳的楼------策略再漂亮,实盘也会塌。

SCD 在量化中的本质:确保每一个因子值,在回测的每一个时间点上,都等于市场当时实际看到的那一个。

这句话,值得贴在每一个量化研究员和因子工程师的显示器上。

相关推荐
roman_日积跬步-终至千里43 分钟前
常驻 Spark 引擎的稳定性风险:从一次 Linkis 任务失败说起
大数据·分布式·spark
星辰徐哥1 小时前
鸿蒙金融理财全栈项目——生态合作、用户运营、数据变现
金融·harmonyos·用户运营
liukuang1101 小时前
商汤2026上半年盈利6.2亿元,生成式AI业务占比近80%
大数据·人工智能
百胜软件@百胜软件1 小时前
AI是“放大器”也是“风险源”:零售企业如何驾驭这把双刃剑?
大数据·人工智能·零售
数字融合1 小时前
透明化数字孪生:未来医疗的核心平台
大数据·人工智能·virtualenv
一路向北finish2 小时前
《Hadoop 高可用集群与 OpenStack Mitaka 控制节点部署全流程实操排坑指南》
大数据·linux·运维·服务器·hadoop·openstack
段一凡-华北理工大学2 小时前
高炉炉况智能诊断与预警实战~系列文章14:机器学习炉况分类:样本构建、类别不平衡与模型选型
大数据·人工智能·机器学习·分类·高炉智能化·炉况诊断·炉况分类
代码里的AI星2 小时前
B2B企业AI搜索可见度诊断与GEO技术优化实践:从0%到67%的架构重构之路
大数据·人工智能
insertYam2 小时前
[hadoop高可用架构]
大数据·hadoop·架构