当数据说谎:为什么你的量化策略可能只是捕获了一厢情愿的相关性
相关性不等于因果——这是统计学第一课,但也是被违背次数最多的原则。
2012 年,NASA 火星探测器“好奇号”发射升空。同一年,意大利帕勒莫地区冰淇淋销量创历史新高。如果我告诉你这两件事高度相关,你会相信帕勒默人靠吃冰淇淋把钱送到了火星吗?
荒谬。但同样的逻辑每天都在量化交易中以更隐蔽的方式上演。
一、为什么冰淇淋和溺水共享同一个节奏
让我们解剖这个被引用了无数次的经典案例。冰淇淋销量和溺水死亡人数确实呈现正相关,而且相关性相当强——两者都在夏季达到高峰,在冬季跌至谷底。
这种相关性不是谎言。但它也不是你想的那种“联系”。
真正连接这两个变量的是第三个变量:季节。夏季同时驱动了两个结果:更多人买冰淇淋,更多人去游泳。冰淇淋不导致溺水,溺水也不导致冰淇淋。他们只是被同一个原因拖着往前走。
统计学家给这种现象起了名字:伪相关(Spurious Correlation)。这个词第一次系统性地进入学术视野是在 20 世纪初,西利曼·赖特(Sewall Wright)在路径分析中提出:如果两个变量共享一个未观测的共同原因,直接计算它们的相关系数会严重高估它们的“真实联系”。
赖特的核心洞见:一个被忽视的第三变量可以通过两种方式制造伪相关。第一,它同时影响两个变量,让它们看起来在“一起运动”;第二,它掩盖了真实因果关系的方向——你以为 A 导致 B,但其实是 C 同时导致了 A 和 B。
在量化交易的语境下,这比冰淇淋问题危险一百倍。因为冰淇淋-溺水只影响直觉,但伪相关可能让你在真实市场上亏掉真实的钱。
二、量化交易中最常见的伪相关陷阱
2.1 共同驱动因素:流动性与波动率的共舞
想象你发现了一个因子:某科技股的成交量与次日收益率呈现出 +0.35 的相关性。成交量放大,次日往往上涨。这是一个可交易的信号吗?
也许不是。
成交量放大的真正驱动力可能是波动率上升。高波动时期,流动性提供商扩大买卖价差,成交量自然放大;同时,高波动时期市场情绪更不稳定,次日方向更难判断。
如果你只看到了成交量-收益率的表面相关性,你实际上是在交易波动率——但你的因子名称叫"volume"。当你在低波动环境下使用同一个因子时,+0.35 的相关性会迅速蒸发。
诊断方法:控制波动率变量后,重新检验成交量-收益率的相关性。如果相关系数从 0.35 跌至 0.08,说明你捕获的是波动率的影子。
2.2 时间趋势掩盖的真实关系:VIX 与期权溢价
2008 年之后,一个广泛传播的观察是:VIX 指数与标准普尔 500 期权的隐含波动率溢价高度同步。
许多量化策略据此构建:做多 VIX 相关产品,同时买入指数看跌期权,对冲尾部风险。这个结构听起来合理,相关性在过去十年也验证得不错。
但问题在于:这两者可能在同一个趋势里上涨,但原因并不相同。VIX 更多反映的是市场情绪的即时反应,而隐含波动率溢价(实际波动率与隐含波动率的差值)反映的是期权定价效率。两者的时间序列高度相关,可能只是因为市场在压力时期同时推高了两个指标,而压力时期本身就是高危时段。
当相关性在低波动环境下失效时,这类策略的尾部风险往往比回测揭示的要大得多。
2.3 幸存者偏差:当你的基准已经在骗你
你构建了一个多因子模型,回测过去五年,年化收益 23%,夏普比率 1.8。漂亮。
但你有没有想过,你的股票池是什么?
如果在选股时你已经排除了市值低于 5 亿、上市不满三年、日均成交额低于 100 万的标的,你实际上在进行幸存者筛选——你只保留了活下来的公司,而那些死去的公司已经被你的过滤器过滤掉了。
这意味着你的基准本身已经包含了“成功者偏见”。在此基础上发现的相关性,可能是历史筛选机制的产物,而非真实的预测关系。
诊断方法:使用包含已退市股票的完整历史数据库,从过去时点的视角重新构建回测。在 TickDB 的美股历史数据体系中,10 年级别的清洗 K 线数据可以帮助你构建更真实的历史快照。
三、格兰杰因果检验:时间序列的因果侦探
好了,问题是明确的:相关性会撒谎。那么我们怎么判断一个变量是否能“预测”另一个,而不是仅仅“同步”?
统计学提供了一套工具,其中最经典的是格兰杰因果检验(Granger Causality Test)。
这个名字本身就容易误导:格兰杰因果并不是真正的因果——它检验的是预测性。如果你用变量 X 的历史信息可以显著提升对变量 Y 未来值的预测精度,格兰杰检验会说“X 对 Y 格兰杰因果”。但这仍然不等于 X 导致了 Y。
但这已经是统计工具能做到的极限了——在没有随机对照实验的情况下,我们无法证明真正的因果,只能验证预测能力。
3.1 核心思想
格兰杰因果的核心假设是:如果 X 导致 Y,那么 X 的历史信息应该包含关于 Y 未来状态的增量信息。
用回归的语言来说,假设我们要检验 X 是否对 Y 格兰杰因果:
限制模型:$Y_t = \alpha + \sum_{i=1}^{p} \phi_i Y_{t-i} + \epsilon_t$
无限制模型:$Y_t = \alpha + \sum_{i=1}^{p} \phi_i Y_{t-i} + \sum_{j=1}^{q} \beta_j X_{t-j} + \eta_t$
如果加入 X 的滞后项后,模型的解释力显著提升(通过 F 检验或似然比检验),我们拒绝“X 不格兰杰导致 Y”的零假设。
3.2 金融市场的经典检验场景
场景一:VIX 能预测标普 500 的波动率吗?
直觉上,波动率指数应该包含关于未来实际波动率的信息——但这需要实证验证。
import numpy as np
import pandas as pd
from statsmodels.tsa.api import VAR
from statsmodels.stats.stattools import durbin_watson
class GrangerCausalityAnalyzer:
"""格兰杰因果检验分析器"""
def __init__(self, significance_level=0.05):
self.alpha = significance_level
self.results = {}
def test_granger(self, data, x_col, y_col, max_lag=10):
"""
执行格兰杰因果检验
参数:
data: DataFrame,包含 x_col 和 y_col
x_col: 疑似原因的变量名
y_col: 疑似结果的变量名
max_lag: 最大滞后阶数(自动选择最优)
"""
# 构建 VAR 系统 [Y, X]
endog = data[[y_col, x_col]].dropna()
# 步骤1:确定最优滞后阶数(使用 AIC)
model = VAR(endog)
optimal_lag = model.select_order(maxlags=max_lag).aic
# 步骤2:估计无限制模型(包含 X 的滞后)
unrestricted = model.fit(optimal_lag)
# 步骤3:估计限制模型(不含 X 的滞后)
restricted = model.fit(optimal_lag, verbose=False)
# 步骤4:似然比检验
lr_stat = -2 * (restricted.llf - unrestricted.llf)
from scipy.stats import chi2
df = unrestricted.k_ar * unrestricted.neqs # 自由度
p_value = chi2.sf(lr_stat, df)
# ⚠️ 重要说明:格兰杰因果≠真正因果
# 格兰杰因果检验的是预测能力,不是因果机制
# 两个变量可能格兰杰因果相关,但都由第三个变量驱动
self.results[(x_col, y_col)] = {
'optimal_lag': optimal_lag,
'lr_statistic': lr_stat,
'p_value': p_value,
'significant': p_value < self.alpha,
'conclusion': f"{x_col} {'格兰杰导致' if p_value < self.alpha else '不格兰杰导致'} {y_col}"
}
return self.results[(x_col, y_col)]
def run_pairwise_analysis(self, data, columns, max_lag=10):
"""对多变量进行两两格兰杰因果检验"""
results = {}
for i, col1 in enumerate(columns):
for j, col2 in enumerate(columns):
if i != j:
key = (col1, col2)
try:
results[key] = self.test_granger(data, col1, col2, max_lag)
except Exception as e:
# ⚠️ 可能遇到平稳性问题,需要先做协整检验
results[key] = {'error': str(e)}
return pd.DataFrame(results).T
# 示例使用
def analyze_vix_predictability(vix_data, realized_vol_data):
"""
分析 VIX 对未来实际波动率的格兰杰因果关系
注意:实际应用中需要:
1. 对非平稳序列进行差分或使用 VECM
2. 检查残差的序列相关性
3. 考虑结构突变(市场极端时期)
"""
analyzer = GrangerCausalityAnalyzer(significance_level=0.05)
# 准备数据:日频收盘价
data = pd.DataFrame({
'VIX': vix_data,
'RealizedVol': realized_vol_data
})
# 执行检验
result = analyzer.test_granger(data, 'VIX', 'RealizedVol', max_lag=20)
if result['significant']:
print(f"✓ VIX 对实际波动率有显著预测能力(滞后 {result['optimal_lag']} 天)")
print(f" 似然比统计量: {result['lr_statistic']:.4f}, p-value: {result['p_value']:.4f}")
else:
print(f"✗ VIX 对实际波动率的预测能力不显著(p={result['p_value']:.4f})")
return result
3.3 格兰杰因果的局限性
但你必须清楚,格兰杰因果检验是有前提的:
平稳性要求:如果变量是非平稳的(如价格序列),需要先进行差分。错误的平稳性假设会导致伪回归。
滞后阶数的主观性:最优滞后阶数的选择影响结果。不同准则(AIC/BIC/HQIC)可能给出不同结论。
遗漏变量偏误:如果真正的因果变量不在模型中,格兰杰因果检验可能给出误导性结论。
样本选择性偏差:在不同时期,变量间的关系可能发生结构性变化。2008 年之前的格兰杰关系可能在 2008 之后失效。
四、从伪相关到真信号:验证流程
面对一个相关性信号,如何系统性地排除伪相关的干扰?
4.1 四步验证框架
第一步:物理直觉检验
在计算任何统计量之前,先问自己:这个变量真的有可能影响那个变量吗?传导机制是什么?
如果无法给出物理上合理的解释(比如“成交量上涨导致次日上涨”没有清晰的传导路径),需要更谨慎的证据。
第二步:控制变量后重新检验
引入可能的第三变量,看原始相关性是否消失。如果加入控制变量后相关性大幅下降,说明你捕获的是第三变量的影子。
第三步:格兰杰因果检验
验证预测能力是否真实存在。注意滞后阶数的选择和序列平稳性。
第四步:样本外验证
在非样本区间进行验证。任何在样本内有效的相关性,都必须在样本外重复验证至少两次,才能进入策略池。
4.2 一个具体案例:美元指数与黄金的相关性
过去十年,美元指数(DXY)与黄金价格(XAUUSD)呈现约 -0.7 的强负相关。许多交易者直接使用这个关系进行均值回归交易。
但这个相关性可靠吗?
物理直觉:美元走强通常意味着美国资产吸引力上升,资金流向美元资产,黄金作为无息资产吸引力下降。这个逻辑是成立的,传导机制清晰。
控制变量检验:加入实际利率(名义利率减去通胀)后,美元-黄金的相关性显著减弱——因为实际利率才是驱动黄金的更直接因素,美元只是中间变量。
格兰杰因果:DXY 的滞后项对 XAUUSD 有显著的预测能力,反之亦然(存在双向引导关系)。
结论:美元-黄金的相关性是真实存在的,但它的来源是实际利率,而不是美元本身的内在属性。这意味着当实际利率成为主要矛盾时,美元-黄金的相关性可能失效。
五、你的因子正在捕获什么?
回到最开始的问题:两个变量走势高度一致,就能用来预测吗?
答案取决于你能否回答以下三个问题:
你的信号在控制第三变量后还存在吗? 如果加入流动性、波动率、市场情绪等常见第三变量后,信号消失,说明你捕获的是伪相关。
你的信号有格兰杰因果的支持吗? 如果 X 的历史信息无法提升对 Y 未来值的预测精度,相关性可能只是巧合。
你的信号在非样本期重复验证了吗? 样本内的漂亮相关性是最危险的自欺欺人。
这三个问题不是选答,是必答。任何一题的答案如果是否定的,你的“信号”很可能只是冰淇淋和溺水之间那种看起来很美、但毫无交易价值的统计数据。
下一步行动
如果你想系统性地检验你的因子:
访问 tickdb.ai,在 API 控制台使用 /kline 接口获取 10 年级别的美股历史数据,配合 TickDB 提供的 depth 频道和 trades 数据,构建多维度的因子验证框架。历史数据的完整性是排除伪相关的第一步——你需要看到“死去”的股票,而不是只在“活着的”股票上做回测。
如果你习惯用 AI 辅助开发:
在 AI 助手中搜索安装 tickdb-market-data SKILL,可以更高效地完成数据获取、因子计算和验证流程。
如果你想了解更多因子有效性评估方法:
关注 TickDB 公众号,后续会推出系列文章,涵盖因子 IC 分析、夏普比率分解、样本外验证的系统性方法论。
回测局限性说明:本文涉及的验证方法基于历史数据,不构成未来收益保证。因子有效性会随市场结构变化而漂移,建议持续跟踪因子衰减情况并进行样本外验证。
风险提示:本文不构成任何投资建议。市场有风险,投资需谨慎。