第三节:协方差矩阵与相关性——风险联动的核心工具

说实话,协方差矩阵这东西,我刚开始做量化的时候觉得它就是个数学符号。直到有一次,我管理的组合在2020年3月市场暴跌时,明明分散了仓位,却所有资产一起跳水。嗯,那才真正意识到——你看到的分散,可能只是假象

这一节,我们就来拆解协方差矩阵和相关性。它们是你理解资产之间「怎么联动」的基础。说白了,没有它们,风险预算就是瞎算。

3.1 协方差矩阵的计算

先问个问题:为什么我们不用方差,而要用协方差?

因为单看一个资产的波动,你永远不知道它和别的资产是不是「同涨同跌」。协方差就是衡量两个资产一起变动的方向和幅度。

公式长这样:

Cov(Ri, Rj) = E[(Ri - μi)(Rj - μj)]

翻译成人话:把两个资产的收益率,各自减去自己的均值,然后乘起来,再求平均。

我习惯用Python里的numpy.cov直接算。但你要理解它背后的逻辑——正数表示同向变动,负数表示反向变动,零表示没关系

举个例子,假设我们有三个资产:沪深300、中证500、国债。5天的收益率数据如下:

日期沪深300中证500国债
Day10.020.03-0.01
Day2-0.01-0.020.005
Day30.0150.01-0.002
Day4-0.0050.0050.003
Day50.010.015-0.004

用Python算一下:

import numpy as np

returns = np.array([
    [0.02, 0.03, -0.01],
    [-0.01, -0.02, 0.005],
    [0.015, 0.01, -0.002],
    [-0.005, 0.005, 0.003],
    [0.01, 0.015, -0.004]
])

cov_matrix = np.cov(returns, rowvar=False)
print(cov_matrix)

输出结果是一个3x3的矩阵。对角线是每个资产自己的方差,非对角线就是协方差。你会发现沪深300和中证500的协方差是正的,而它们和国债的协方差是负的。这符合直觉——股票和债券通常跷跷板。

核心要点:协方差矩阵是对称矩阵,对角线是方差,非对角线是协方差。它完整描述了资产组合的波动结构。

3.2 相关性分析

协方差有个问题:它受量纲影响。比如一个资产收益率是0.01级别,另一个是0.1级别,协方差会被大的那个带偏。这时候就需要相关性——说白了,就是标准化后的协方差。

相关系数公式:

ρij = Cov(Ri, Rj) / (σi * σj)

取值范围在-1到1之间。1代表完全正相关,-1代表完全负相关,0代表不相关。

我个人习惯,在构建组合前,先看相关性矩阵。如果两个资产相关性超过0.8,我会怀疑它们是不是同一个东西。我曾经见过一个组合,里面同时持有沪深300ETF和上证50ETF,相关性高达0.95——那还分散个啥?

用上面的数据算相关性:

corr_matrix = np.corrcoef(returns, rowvar=False)
print(corr_matrix)

结果大概是这样:

沪深300中证500国债
沪深3001.000.87-0.62
中证5000.871.00-0.55
国债-0.62-0.551.00

你看,两个股票指数相关性0.87,很高。而国债和它们都是负相关。这就是经典的「股债跷跷板」效应。

小技巧:我一般用热力图可视化相关性矩阵。一眼就能看出哪些资产「抱团」,哪些是真正的分散工具。颜色越红,相关性越高。

3.3 协方差矩阵的估计方法

这里有个坑:你算出来的协方差矩阵,真的准吗?

我踩过这个坑。有一次我用过去3年的日数据算协方差矩阵,结果模型回测很漂亮,实盘却一塌糊涂。为什么?因为市场结构变了,过去的协方差不能代表未来。

所以,我们需要不同的估计方法。常用的有三种:

3.3.1 历史估计法

最简单粗暴。直接用过去N天的收益率数据算协方差。优点是简单,缺点是对极端值敏感,而且假设过去会重复。

# 历史估计:直接用最近252个交易日
hist_cov = np.cov(returns[-252:], rowvar=False)

我建议你至少用1年以上的数据。太短了噪声大,太长了市场结构可能已经变了。

3.3.2 指数加权估计法

这个方法更聪明。它给近期的数据更高的权重,远期的数据权重逐渐衰减。说白了,就是「最近发生的事更重要」。

公式:

Cov_t = λ * Cov_{t-1} + (1-λ) * (R_t * R_t^T)

其中λ是衰减因子,通常取0.94(RiskMetrics的标准做法)。

def ewma_cov(returns, lam=0.94):
    cov = np.cov(returns[:2], rowvar=False)
    for i in range(2, len(returns)):
        r = returns[i].reshape(-1, 1)
        cov = lam * cov + (1-lam) * (r @ r.T)
    return cov

我个人习惯用指数加权。它在市场波动突变时反应更快。比如2020年3月,历史估计法还在用过去的数据平滑,指数加权已经捕捉到了波动率的飙升。

注意:λ的选择很关键。λ=0.94相当于半衰期约11天。如果你做长线,可以调高到0.97。别照搬参数,要根据你的交易频率调整。

3.3.3 收缩估计法

这个方法解决了一个实际问题:当资产数量多、数据量少时,样本协方差矩阵会「病态」。比如你有100个资产,但只有50天的数据,算出来的矩阵可能不可逆。

收缩估计法的思路是:把样本协方差矩阵向一个「目标矩阵」收缩。目标矩阵通常是对角矩阵(假设资产不相关)或者常数相关矩阵。

公式:

Σ_shrink = δ * F + (1-δ) * S

其中S是样本协方差矩阵,F是目标矩阵,δ是收缩强度(0到1之间)。

from sklearn.covariance import LedoitWolf

lw = LedoitWolf()
shrink_cov = lw.fit(returns).covariance_

Ledoit-Wolf方法会自动计算最优的收缩强度。我遇到高维数据时,几乎必用这个方法。它虽然有点「作弊」——把矩阵往理想方向拉——但实际效果往往比纯样本估计好得多。

我的经验:三种方法没有绝对的好坏。历史估计适合数据充足、市场稳定的情况。指数加权适合高频或波动剧烈的市场。收缩估计适合资产多、数据少的情况。我一般会同时算三种,然后看哪个在回测中表现最稳健。

知识体系总览

下面这张图,帮你理清这一节的核心逻辑:

协方差矩阵与相关性 协方差矩阵计算 相关性分析 估计方法 对称矩阵,对角线为方差 标准化协方差,范围[-1,1] 三种方法各有适用场景 numpy.cov / pandas.cov 热力图可视化,识别抱团 历史 / 指数加权 / 收缩 核心:理解资产联动关系,为风险预算打基础

嗯,这一节的内容就到这里。协方差矩阵和相关性,是量化交易里最基础也最容易被忽视的工具。你想想看,如果连资产之间怎么联动都没搞清楚,风险预算就是空中楼阁。

我建议你拿到真实数据后,先画个相关性热力图,再试试三种估计方法。你会发现,不同的方法算出来的组合风险可能差好几个百分点。选对方法,比选对参数更重要。

避坑指南:我曾经用历史估计法算了一个50只股票的组合,结果矩阵条件数高达10^6,根本没法求逆。后来换成收缩估计,条件数降到100以内,优化器才正常工作。记住:矩阵的「健康度」比精确度更重要。

专注资料整理