资讯动态

从相关性到因果:基于CTP数据的期货量化实战指南

发布时间:2026/10/16 0:39:29 来源:尧图企业网站定制
做期货量化这些年我最大的一个体会是数据越多越要回答清楚一个问题——到底是谁在带动谁。这听起来像哲学题但落到CTP实盘里它就是盈利和亏损的分界线。很多CTA策略前期回测漂亮一到实盘就崩根源往往不是模型不够快而是把“相关性”误当成了“因果性”。我今天想把这些年把因果关系算法用到CTP期货量化上的思路、代码、坑一次性讲透内容偏向实操适合正在做因子挖掘、跨品种套利或者高频择时的朋友。先用一句话把因果关系算法讲明白它不是找“两个序列一起涨跌”而是回答“A的变化是不是B变化的原因”或者“如果强行改变AB会不会跟着变”。在期货市场里螺纹钢和铁矿石的相关性可能常年都在0.8以上但到底是铁矿石涨价推高了螺纹钢成本还是螺纹钢需求拉动了铁矿石价格这个方向性问题普通相关分析完全答不了。因果关系算法就是为解决这类问题来的。1. 为什么量化交易必须引入因果关系算法1.1 从“相关性陷阱”说起伪相关的代价我做过的第一个CTA策略就是用相关矩阵选配对品种的回测里筛选出相关性超过0.7的品种组合做配对交易结果实盘半年就把回撤拉到了历史极值。复盘时发现那组高度相关的品种真正驱动它们的是同一个宏观因子当宏观因子走势一变两者就分道扬镳了。这就是典型的伪相关“相关”不等于“谁影响谁”更不等于“一个变了另一个会跟着变”。在量化研究里这种伪相关带来的问题是实打实的因子与收益率的相关系数高但换样本期就失效资产定价模型一加控制变量原来“显著”的解释力就消失跨品种统计套利的协整关系被突发行情打破且方向和你预期相反。因果关系算法提供的是另一种视角它要求你检验“X对Y的过去信息是否有助于预测Y的未来”或者“在控制其他因素之后X的变化是否仍伴随Y的变化”。这直接过滤掉了一大类“看相关但无因果”的假信号。我自己的习惯是任何因子在进入策略库之前先跑一轮格兰杰因果检验加一轮条件独立检验宁可漏掉“暂未发现因果”的因子也不想放一个“看着相关但实际无因”的因子进来。实践证明这一道闸门能过滤掉大约两成到三成的回测漂亮因子。1.2 因果关系在期货市场的三种典型应用场景期货市场的结构非常适合因果分析因为它的品种之间存在天然产业链联系和资金面传导。我归纳下来因果关系算法在期货量化里最常用的场景有三个第一个是跨品种产业链传导判断。比如铁矿石、焦炭对螺纹钢的影响豆粕对豆油的影响原油对PTA和聚酯链的影响。这些品种之间有理论上清楚的上中下游关系但在实际行情里价格反馈机制非常复杂下游需求反过来也会影响上游价格。用因果检验可以判断在某个时间尺度上到底是上游领先下游还是下游反过来引领上游。第二个是资金与持仓维度的因素分析。持仓量、成交量、资金净流入这些数据和价格之间到底谁是因谁是果业内争议很大。有人说“资金流入导致价格上涨”但更可能是“价格上涨吸引资金流入”。这两者对应的策略完全相反做错方向等于给市场送钱。因果分析可以揭示主导方向。第三个是高频订单流对短期价格冲击的判断。在CTP的tick级数据里主动买盘和主动卖盘是否显著持续影响未来几十笔的成交价格这种微观因果关系是高频做市和冲击成本优化算法的理论基石。1.3 CTP平台的特点对因果分析的影响既然标题里有CTP我得把平台特性讲清楚。CTPComprehensive Transaction Platform是国内期货公司最主流的主机接入方式几乎覆盖全市场期货合约交易。它给我的感觉是行情推送实时性强交易链路稳定但使用上需要注意几个和因果分析密切相关的地方。数据维度CTP行情接口推送的是逐笔tick快照或逐笔委托/成交包含最新价、买卖盘口、持仓量、成交量等。相比日线数据tick级数据能让因果分析在更细粒度上展开但计算量和噪声也大幅增加。连续性与拼接问题不同合约有不同到期日做跨品种或时序分析时通常需要把主力连续合约拼出来。拼接方式不同如按成交量切换、按持仓量切换会直接影响序列的平稳性从而影响因果检验结果。交易时段国内期货有日盘和夜盘不同品种开盘收盘时间还不一样这个“日历效应”如果不在因果模型里处理很容易冒出奇怪的“日内领先滞后”。所以在用CTP数据做因果分析之前先把数据清洗、合约拼接、时间对齐这几件事做扎实否则后续所有因果推断都是建立在沙子上。2. 因果关系算法方法族谱与选型思路因果推断不是单一算法而是一个方法论家族。我按自己实践中的使用频率把常用的方法排一个序从最简单最稳定的开始。2.1 格兰杰因果检验最常用也最容易被误用的方法格兰杰因果检验Granger Causality Test是最容易上手的因果判断工具。它的核心思想很朴素如果过去的X对预测未来的Y有统计上显著的帮助在控制Y自身历史之后仍然如此那就认为“X是Y的格兰杰因”。数学模型是这样Y_t α Σβ_i * Y_{t-i} Σγ_i * X_{t-i} ε_t如果所有这些γ_i都不显著就接受原假设“X不是Y的格兰杰因”。用Python的statsmodels做这个检验非常直接几行代码就能跑完。不过我要泼一盆冷水很多文章把格兰杰因果检验当成万能钥匙其实它有三个前提必须满足序列必须是平稳的否则会出现伪回归。做检验前一定先跑ADF检验不平稳就取差分或取对数收益率它检验的是“统计意义上的预测能力”不是“结构性因果”所以它无法排除“X和Y同时受第三个变量Z驱动”的情况它是线性模型对非线性因果关系的检测能力有限。我在实盘应用中的习惯是把格兰杰因果检验当作第一步筛选器而不是最终结论。它告诉我“方向上存在可预测关系”但具体能不能在策略里用还得靠后边的条件检验和样本外验证。2.2 收敛交叉映射对付非线性系统的利器格兰杰因果检验之所以在真实市场中经常失灵是因为价格传导机制往往是非线性的。比如“铁矿石上涨5%时对螺纹钢的影响跟上涨20%时的影响完全不是一个量级”这种非线性在期货产业链里太常见了。这时我更喜欢用收敛交叉映射Convergent Cross Mapping, CCM这是Sugihara等人在2012年提出的方法。它的思想来自动力系统理论如果X对Y存在因果影响那么Y的时间序列中应该已经“烙印”了X的信息。所以可以从Y的历史状态空间中重建对X的估计随着时间序列长度L增加这个估计精度ρ会收敛上升反过来如果X对Y没有影响用Y去估计X不会随L增加而改善。CCM的优势是能捕获非线性因果而且能判断方向。它的缺点是数据需求量比格兰杰大得多通常需要几百个连续观测点起步。日线数据虽然样本少但用在5分钟或tick级数据上就非常合适。有一年我专门用CCM分析沥青和原油在夜盘时段的因果结构发现晚间原油库存数据公布后原油对沥青的因果影响显著加强而沥青对原油几乎没有反向影响。这种“单向门”关系用格兰杰检验看并不稳定但CCM的收敛曲线给出了非常清晰的证据。2.3 结构因果模型与干预思想从观察走向推演如果你需要的不只是判断“A是否影响B”而是想回答“如果我现在改变A会发生什么”那就要上升到结构因果模型Structural Causal Model, SCM。SCM的核心是表示“机制”而不是“相关”它用有向无环图描述变量间的因果关系用结构方程量化因果强度。SCM中有一个重要概念叫做“干预”记作do(Xx)表示“强制将X设置为x”这和在自然状态下看到X等于x是两回事。举一个期货里的场景假设你发现库存数据X和价格Y相关想分析“如果库存意外上升10万吨价格会怎么走”简单回归是不能直接回答这个问题的因为现实中库存上升可能伴随需求变化、基差变化等一篮子因素。SCM能通过后门准则、前门准则这些工具告诉你需要控制哪些混杂变量才能干净地估计这个干预效果。说实话SCM在实盘策略里的直接应用比前两个方法少因为真实市场的因果结构太复杂且随时间变化。但它给了一个非常宝贵的分析习惯画因果图、找混杂变量、说清楚假设。即使不用完整SCM跑数在因子筛选时把“潜在混杂变量”列出来做条件独立性检验也能让因果结论稳健很多。2.4 DAG学习与PC算法让数据告诉你因果结构当你不确定变量之间的因果顺序同时又有很多候选变量时可以考虑用因果结构学习算法。最出名的是基于约束的PC算法它通过一系列条件独立性检验来逐步删掉不可能的边最后得到一个有向无环图。市面上有现成的工具库比如causal-learn项目CMU开源的因果学习工具包。和金融场景结合时我一般不会直接把原始收益率丢进去学图因为金融序列的非平稳性和波动集聚性会破坏独立性检验的前提。更稳妥的做法是先对序列做平稳化处理或者把问题限定在“同一时点横截面上多个品种的收益率相互影响”这一具体机制上。这个方法在品种选择上很实用。比如做多品种组合时与其硬套经济直觉不如用PC算法结合专家约束快速锁定“有向边”很清晰的品种组合剔除那些看似相关实则相互独立的冗余品种。3. 基于CTP行情数据的因果分析实战理论讲再多不如直接跑一次完整流程。下面这节是整篇的核心我会用我实际做过的一个案例讲清楚从CTP拿数据到预处理到跑格兰杰因果检验和CCM再到解读结果。3.1 环境和数据准备CTP行情落地与预处理做因果分析的第一步是把高含金量的CTP数据准备好。我实际用的方案是通过CTP行情API订阅行情落地成csv或直接入SQLite。行情字段我会至少保留合约代码、时间戳精确到毫秒、最新价、成交量、持仓量、买一卖一价格和量。如果条件允许逐笔委托和成交通数据价值更大但存储成本高要量力而行。数据落地的几个关键点我得重点提醒合约拼接、时间对齐和复权处理。合约拼接上我通常按持仓量和成交量综合判断切换主力合约切换时刻前后各留一段交叉区用于校验。实盘研究里最忌讳直接拿两个不同合约段拼在一起当连续序列用这种“结构断点”会直接摧毁因果检验的平稳性假设。时间对齐上CTP的tick时间戳是交易所时间不同品种的日盘夜盘时段不一致比如螺纹钢有夜盘到23点而豆粕夜盘也有类似时段但细节不同。做跨品种分析时我会先把每个品种的序列按统一时间轴重采样到5分钟K线或1分钟K线缺失的时段不填充直接做inner join宁缺毋滥。3.2 实战一螺纹钢与铁矿石的跨品种因果传导先说背景螺纹钢是下游成材铁矿石是上游原料。经济直觉是铁矿石涨价通过成本传导推高螺纹钢。但市场实际情况更加复杂因为螺纹钢需求旺盛时钢厂增产反过来会拉动铁矿石需求。我选取的是近两年的5分钟收盘价数据先取对数再差分得到对数收益率这样可以确保序列平稳。然后用statsmodels跑格兰杰因果检验核心代码如下import pandas as pd import numpy as np from statsmodels.tsa.stattools import adfuller, grangercausalitytests # 读取已对齐的5分钟数据 df pd.read_csv(rb_i_5min.csv, index_coldatetime, parse_datesTrue) df df[[rb_close, i_close]].dropna() # 转成对数收益率 ret np.log(df).diff().dropna() ret.columns [rb_ret, i_ret] # ADF平稳性检验 for col in ret.columns: stat, pval, _, _, _, _ adfuller(ret[col], autolagAIC) print(f{col}: ADF p-value {pval:.4f}) # 格兰杰因果检验 # 注意grangercausalitytests 的 data 参数第1列是y第2列是x print(检验: 铁矿石收益(第2列) 是否格兰杰因 螺纹钢收益(第1列)) result grangercausalitytests(ret[[rb_ret, i_ret]], maxlag5, verboseTrue)输出的表格里有两组F统计量和p值第一组是“i_ret不是rb_ret的格兰杰因”的检验第二组是“rb_ret不是i_ret的格兰杰因”。我当时跑出来的结果是铁矿石对螺纹钢的单向因果在滞后1到3阶时显著而螺纹钢对铁矿石的因果在大部分滞后阶上不显著。这和经济直觉比较吻合——成本端传导是主要方向。需要说明的是这套结果只代表一个特定样本区间。每次换数据窗口我都建议重新跑一遍因为产业逻辑和资金结构会变。3.3 实战二持仓量变化对价格收益的因果作用持仓量是被很多人忽视但非常有价值的数据。CTP的tick行情里带持仓量字段国内期货市场又普遍实行“日盘收盘后结算持仓量连续公布”的制度这使得持仓量序列天然适合做增量分析。我经常用二元格兰杰因果检验分析持仓量变化率OI change和绝对收益之间的关系。具体做法是把持仓量取一阶差分除以持仓量均值得到变化率收益取对数绝对值或平方作为波动代理。这里我想强调的是必须把量纲统一否则检验结果会被尺度主导。下面是我常用的一个操作思路对持仓量变化率序列和收益序列分别做平稳性检验用AIC/BIC选择最优滞后阶数而不是随便定为5跑格兰杰因果检验并同时记录双向结果关键一步在做回归时加入成交量作为控制变量因为持仓和价格经常同时受成交活跃度影响不控制的话容易出现伪因果。我真实跑下来的一个普遍规律是在多数品种上“持仓量变化是成交量变化的结果”而“持仓量变化对价格收益的预测能力在中低频上并不稳定”。这意味着如果有人直接用“持仓量增加看多”这个简单规则做入场信号本质上是在赌一个并不稳健的因果方向。3.4 实战三tick级订单流与短期价格冲击如果做高频或日内超短线因果分析需要下探到tick级。CTP逐笔数据里有主动买方向成交和主动卖方向成交经典的市场微观结构指标是订单流不平衡Order Flow Imbalance, OFI定义为单位时间窗口内主动买量减去主动卖量再除以总成交量。OFI和未来短期价格变化的关系在学术文献里有很坚实的结论OFI是价格冲击的核心驱动。但如果直接看二者的相关系数会发现问题OFI和价格几乎是同时刻联动的导致相关极高却说不清方向。我用格兰杰因果检验处理的原则是把OFI按价格变化的“前一期”做滞后对齐检验OFI的历史值是否能预测未来1到5个tick的价格变化。实测发现在流动性好的品种上OFI的因果预测能力在中高频上非常显著但在流动性差的冷门合约上这一因果几乎消失。这意味着因果结构在不同合约上差异巨大策略参数不能直接跨品种复制。4. 因果信号如何落成可交易的策略讲完检验方法接下来是大家最关心的因果检验跑出结果之后怎么变成赚钱的策略。我的经验是因果分析给出的不是“买卖点”而是“可信的方向性前提”。它应该和交易系统里的其他模块配合使用而不是单独输出信号。4.1 从因果关系到交易信号的映射如果检验发现“铁矿石收益率是螺纹钢收益率的格兰杰因且方向为正”我能得到一个非常实际的用法当铁矿石在某个时间窗口出现异动比如收益率超过某个阈值可以基于这个因果关系在螺纹钢上做跟随交易。但这里必须做两个额外处理因果系数的大小是有时效的。一个常见的误区是检验显著就放心用事实上因果强度本身也会漂移。我会把样本切成滚动窗口比如每90天重估一次只保留那些在过去多个窗口中都稳定显著的因果方向滞后的长度要落到交易逻辑上。格兰杰检验的“滞后K期显著”要转化成交易系统的“K期后入场”这个K不是靠肉眼看的而是参考信息准则同时兼顾交易成本。我习惯把因果信号做成一个独立的“方向过滤器”只有因果方向和市场当前的相对强弱方向一致时才允许开仓。这相当于给原有CTA策略加了一道因果“安全检查门”实测能明显减少逆大势交易和假突破交易。4.2 与现有因子模型结合因果权重再分配当你手头已经有一套多因子打分模型时因果检验还有一个漂亮的用法因子权重动态再分配。具体操作是对所有候选因子分别与目标收益跑条件格兰杰因果检验得到p值将p值转化为因果强度分比如 -log(p) 并做归一化在多因子组合时用因果强度分去调整原始因子权重而不是用传统IC/IR加权。这样做的好处是避免一个因子虽然在历史回测中IC很高但实际只是“跟随大盘变化的影子因子”实盘中一旦市场结构变化就失效。我实盘测试后感觉使用因果加权后的组合回撤明显变小原因就在于它剔除了一部分“高相关、弱因果”的因子。当然因果强度分要做衰减和平滑处理避免权重频繁抖动导致换手过高。我一般用30日滚动窗口计算因果p值再用指数平滑处理权重变化。4.3 回测与样本外验证因果也会失效任何因果结论在回测中表现良好都必须过样本外这一关。我的标准流程是这样第一步把历史数据严格分成“样本内”和“样本外”两部分。样本内用于估计因果方向和参数样本外用于验证这段因果关系是否仍然成立。这里最容易犯的错误是整个数据集去跑因果检验然后又用同一份数据回测策略等于把应变量当自变量用结果一定极其乐观。第二步在样本外验证中我不只看收益还看因果方向本身的稳定性。方法是滚动重估格兰杰因果检验的p值如果p值在样本外持续显著说明因果结构还在一旦p值快速上升说明驱动因素已经消失策略应该自动降纬或者停止交易。第三步引入“置换检验”作为归零基准。把因变量的时间顺序随机打乱数千次看真实因果强度统计量处于置换分布的什么位置。如果真实值落在分布的边缘说明所谓因果可能只是数据挖掘出来的噪声。5. 常见问题与排查技巧实录我把自己在实战中踩过的一些“看起来没问题但实际坑人”的细节整理成了速查表供大家排查时对照。5.1 非平稳序列导致的“假显著”最大的坑就是直接拿价格序列跑格兰杰检验。价格序列几乎是单位根过程直接跑检验很容易得到“万物互为因果”的荒谬结论。解决方式是有标准流程的先ADF检验不平稳就做差分直到检验通过为止。对于价格这种有经济含义的序列我通常直接用对数收益率而不用简单收益率因为对数收益率在处理复合收益时更平滑。5.2 滞后阶数选择不当格兰杰检验对滞后阶数非常敏感。选少了遗漏了长期因果选多了自由度下降而且容易引入噪声。我的做法是先跑VAR模型用AIC和BIC同时评估最优滞后阶再在最优滞后阶附近做稳健性测试。如果因果结论只在某一个滞后阶上显著而相邻滞后都不显著我会把它当作偶然现象不敢用来上实盘。5.3 因果方向判断出错很多人跑完双向格兰杰检验发现“X是因、Y是果”但到实盘就反了。常见原因是滞后阶数和采样频率不匹配比如日线数据里铁矿石影响螺纹钢要滞后2天而5分钟数据里影响滞后2根K线两者结论可能完全相反。另一个原因是数据区间包含重大宏观事件事件同时冲击两个品种使因果方向显得存在。处理思路是加入控制变量做条件格兰杰检验比如把原油收益率或国债收益率作为控制变量加入回归。5.4 实盘中因果关系失效的根源因果检验在实盘中失效我复盘下来通常归结为两个原因。一是市场状态变化由趋势市转向震荡市领先滞后结构会改变。有些品种在趋势市里产业链传导逻辑清晰震荡市里则变成资金博弈主导原来的因果链不再成立。二是参与者结构变化当一个因果关系被足够多的量化资金发现和使用后它本身会被交易行为削弱甚至反向。这类反身性在期货市场非常明显。所以我给每个因果策略都设置了“因果健康度”监控每个交易日收盘后滚动计算最近30天的因果检验p值一旦p值连续多日超过阈值系统自动把该策略权重降为零。这条纪律能救命。最后再分享一个体会因果分析不是“算一次管一年”的事而是需要持续迭代的基础设施性工作。CTP数据的价值很大但真正的门槛在于你能不能在噪声里识别出那个稳定的驱动方向。我个人的建议是先从最朴素的格兰杰因果检验开始把样本外验证和置换检验做扎实再逐步引入CCM处理非线性关系最后才考虑结构性因果模型。这样一路走下来策略的“根”会稳很多实盘的时候心里也有底。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑