4. 偏相关与条件独立性:从全相关到精准关联
各位同学,咱们今天聊点硬核的。前面我们讲了皮尔逊相关、秩相关,这些方法说白了就是看「两个变量之间有没有线性关系」。但实际金融市场里,变量之间往往是「你中有我,我中有你」——A和B看起来相关,很可能是因为它们都受C影响。
举个例子。沪深300和上证50的收益率,相关系数经常在0.9以上。但你想想看,这能说明它们之间「直接」关联这么强吗?其实是因为它们都受宏观经济、市场情绪这些共同因子驱动。偏相关要解决的,正是这个问题——剔除其他变量的干扰后,看两个变量之间「干净」的关系。
4.1 偏相关的概念与计算
偏相关的核心思想很简单:控制住其他变量,再算相关性。我习惯把它叫做「条件相关」——给定其他变量不变,X和Y的相关性是多少。
数学上,偏相关系数可以通过三种方式计算:
- 递归法:通过低阶偏相关递推计算高阶偏相关
- 矩阵求逆法:利用协方差矩阵的逆矩阵(精度矩阵)直接得到
- 回归法:做两次回归,取残差再算相关系数
我个人最常用的是矩阵求逆法,因为计算效率高,而且和高斯图模型天然契合。具体来说:
# Python示例:偏相关系数计算
import numpy as np
from sklearn.covariance import GraphicalLasso
# 假设我们有5只股票的收益率数据,T×5矩阵
returns = np.random.randn(1000, 5) # 模拟数据
# 计算协方差矩阵
cov = np.cov(returns, rowvar=False)
# 求精度矩阵(协方差矩阵的逆)
precision = np.linalg.inv(cov)
# 偏相关系数 = -precision_ij / sqrt(precision_ii * precision_jj)
pcorr = np.zeros_like(precision)
for i in range(precision.shape[0]):
for j in range(precision.shape[1]):
if i != j:
pcorr[i, j] = -precision[i, j] / np.sqrt(precision[i, i] * precision[j, j])
print("偏相关系数矩阵:\n", pcorr[:3, :3])
4.2 条件独立性检验
偏相关和条件独立性是一枚硬币的两面。如果两个变量在给定其他变量后偏相关系数为0,我们就说它们在条件上独立。这在金融网络里意义重大——条件独立意味着没有直接的边连接。
检验条件独立性的常用方法是Fisher Z变换:
import scipy.stats as stats
def conditional_independence_test(pcorr, n, p):
"""
pcorr: 偏相关系数
n: 样本量
p: 条件变量个数
"""
z = np.arctanh(pcorr) # Fisher Z变换
se = 1.0 / np.sqrt(n - p - 3) # 标准误
z_stat = z / se
p_value = 2 * (1 - stats.norm.cdf(np.abs(z_stat)))
return p_value
# 示例:检验偏相关是否显著
pcorr_val = 0.15 # 假设偏相关系数
n_samples = 500
n_condition = 3
p_val = conditional_independence_test(pcorr_val, n_samples, n_condition)
print(f"条件独立性检验p值: {p_val:.4f}")
4.3 高斯图模型(GGM)简介
高斯图模型,说白了就是用偏相关来画网络图。它假设数据服从多元高斯分布,那么偏相关系数为0就等价于条件独立。GGM的核心输出是精度矩阵(precision matrix),它的非零元素就对应网络中的边。
我画了一张图来展示GGM的核心逻辑:
GGM在实际应用中有几个关键点:
- 稀疏性假设:金融网络中,大部分资产之间没有直接关联。GGM通过L1正则化(Graphical Lasso)来强制稀疏性。
- 稳定性问题:当p > T时,直接用协方差矩阵求逆会崩溃。我建议用
sklearn.covariance.GraphicalLasso,它自带交叉验证选择正则化参数。 - 非高斯数据:如果收益率有厚尾特征,GGM的假设可能不成立。这时可以考虑非参数方法或者Copula模型。
4.4 偏相关网络 vs 全相关网络
这两种网络的区别,我直接用一张表来说明:
| 对比维度 | 全相关网络 | 偏相关网络 |
|---|---|---|
| 定义 | 直接计算两两变量的皮尔逊相关系数 | 剔除其他变量影响后的条件相关性 |
| 边的含义 | 「看起来」有关系,可能包含间接关联 | 「直接」的条件依赖关系 |
| 网络密度 | 通常很稠密,很多虚假边 | 相对稀疏,更接近真实结构 |
| 计算复杂度 | O(p²),简单快速 | O(p³),需要矩阵求逆 |
| 对噪声的鲁棒性 | 较差,容易受共同因子干扰 | 较好,能过滤共同因子 |
| 金融应用 | 快速筛查、初步探索 | 风险传导、系统性风险分析 |
我在实际项目中做过一个对比实验:用A股300只股票构建网络,全相关网络几乎全连接(密度>90%),而偏相关网络只有约15%的边是显著的。你想想看,哪个更可信?
核心结论: 全相关网络适合做「快速筛查」,偏相关网络适合做「精准建模」。如果你要做风险传导分析、系统性风险度量,我强烈建议用偏相关网络。否则你可能会把「共同因子驱动」误判为「直接关联」。
4.5 实战中的注意事项
嗯,这里我要多说几句。GGM虽然强大,但有几个坑你得避开:
- 时间序列的平稳性:GGM假设数据是独立同分布的。金融收益率虽然近似平稳,但波动率聚集效应会导致条件异方差。我建议先用GARCH过滤掉波动率聚类,再建GGM。
- 正则化参数的选择:Graphical Lasso的alpha参数控制稀疏度。我习惯用BIC或交叉验证来选择,而不是拍脑袋定一个值。
- 网络稳定性:滚动窗口建网时,你会发现网络结构随时间变化。这时候可以计算网络相似度指标(如Jaccard系数),看看哪些边是「稳定存在」的。
# 实战代码:滚动窗口GGM
from sklearn.covariance import GraphicalLasso
def rolling_ggm(returns, window=252, alpha=0.01):
"""
滚动窗口构建偏相关网络
returns: T×p DataFrame
window: 滚动窗口大小
alpha: 正则化参数
"""
n_periods = len(returns) - window + 1
networks = []
for i in range(n_periods):
window_data = returns.iloc[i:i+window]
model = GraphicalLasso(alpha=alpha, max_iter=100)
model.fit(window_data)
# 提取偏相关矩阵
precision = model.precision_
pcorr = np.zeros_like(precision)
for j in range(precision.shape[0]):
for k in range(precision.shape[1]):
if j != k:
pcorr[j, k] = -precision[j, k] / np.sqrt(precision[j, j] * precision[k, k])
networks.append(pcorr)
return networks
# 使用示例
# networks = rolling_ggm(stock_returns, window=252, alpha=0.05)
最后说一句:偏相关网络不是万能的。它假设线性关系,如果市场存在明显的非线性关联(比如极端风险下的尾部依赖),你可能需要结合Copula或者DCC-GARCH来补充。但作为入门,GGM已经能帮你看到很多全相关网络看不到的结构了。
公众号:蓝海资料掘金营,微信deep3321