已实现协方差矩阵:用高频数据拼出盘中多资产联动全景
日线滚动协方差要 20 天才能看清资产联动的变化,而危机往往只给你 2 天。已实现协方差(Realized Covariance)把一天切成几百个高频区间,用日内收益的外积和直接『量出』当天的协方差矩阵——单日数据就能出一个完整估计。本文用纯 numpy 模拟 4 资产 60 天、每天 390 根分钟线的高频数据(内嵌相关性 regime 切换),完整走一遍 RC 的构建与三大实战陷阱:签名图显示 6bp 微观结构噪声把 1 分钟采样的估计误差推高 3 倍,最优采样退到 5 分钟;Epps 效应实验证明稀疏成交资产在 1 分钟粒度下相关被拉向 -0.04(真实 -0.10),采样越细越失真;响应速度对决中 RC 5 日均线只用 2 天就捕捉到相关性从 0.6 跳到 0.89 的 regime 切换,20 日日线滚动相关要 17 天。最小方差组合样本外对决:RC 组合次日实现波动 8.62% vs 日线协方差 8.75% vs 等权 16.95%。另拆穿维度灾难(资产数 > 日内区间数时 RC 必然奇异)与隔夜跳空缺口两类结构性坑(中高阶)。
先说结论:用 20 日滚动窗口估计协方差,等于用上个月的天气预报今天要不要带伞。相关性 regime 切换往往发生在两三天内——2020 年 3 月、2015 年 8 月,股债相关、板块联动一夜变脸——而日线滚动估计需要整个窗口被新数据填满才能跟上。已实现协方差(Realized Covariance, RC)换了一个思路:不跨天平均,而是把一天之内的高频收益加总成外积和,单日数据直接输出一个完整的协方差矩阵。本文的模拟实验里,regime 切换后 RC 只用 2 天就把股指-科技相关从 0.6 追到 0.89,日线滚动相关花了 17 天。但高频不是免费午餐:微观结构噪声把 1 分钟采样的估计误差推高 3 倍,稀疏成交的 Epps 效应把真实相关 -0.10 稀释到 -0.04——这两个坑不填,RC 比日线估计更糟。
一、为什么日线协方差天生迟钝#
组合优化、风险平价、对冲比率,全都要吃协方差矩阵。标准做法是拿最近 N 天的日收益算样本协方差:
问题出在 N 上。4 个资产的协方差矩阵有 10 个自由参数,N 至少要几十天才能压住估计噪声——业界常用 20~60 天。这意味着:
- 响应滞后:今天的相关性突变,要等它在窗口里占到足够权重才能反映出来。20 日窗口下,新 regime 要 10 天才占一半话语权;
- 幽灵效应:60 天前的一根异常大阴线滑出窗口的那天,协方差估计会突然跳变——跟今天的市场毫无关系;
- 样本量与时效性不可兼得:想降噪就得拉长窗口,拉长窗口就更迟钝。这是日频数据的结构性死结。
高频数据把这个死结解开了。理论基础来自二次变差(quadratic variation):如果价格是连续半鞅,把一天 切成 个区间,日内收益向量 的外积和
在 时依概率收敛到当天真实的积分协方差 。翻译成人话:采样够密,一天的数据就够你”量出”当天的协方差,不需要跨天平均。样本量的来源从”天数”变成了”日内区间数”——一天 390 根分钟线,样本量直接翻 390 倍。
二、纯 numpy 搭一个带 regime 切换的高频实验场#
真实高频数据难拿也难清洗,本文用模拟数据换取一个奢侈品:已知真值。设定 4 个资产(股指 ETF、银行、科技、黄金 ETF),60 个交易日,每天 390 根分钟线,前 30 天低相关(平静期),后 30 天切换到危机模式——股票间相关飙升、黄金避险负相关加深:
import numpy as np
rng = np.random.default_rng(42)
n_assets, n_days, fine_n = 4, 60, 390 # 4 资产, 60 天, 390 分钟/天
ann_vol = np.array([0.18, 0.22, 0.35, 0.12]) # 年化波动
day_vol = ann_vol / np.sqrt(252)
corr_calm = np.array([ # 平静期相关结构
[1.0, 0.5, 0.6, -0.1],
[0.5, 1.0, 0.3, -0.05],
[0.6, 0.3, 1.0, -0.1],
[-0.1, -0.05, -0.1, 1.0]])
corr_crisis = np.array([ # 危机期:股票抱团, 黄金避险
[1.0, 0.85, 0.9, -0.4],
[0.85, 1.0, 0.8, -0.35],
[0.9, 0.8, 1.0, -0.45],
[-0.4, -0.35, -0.45, 1.0]])
def intraday_u(n): # 日内 U 型波动: 开盘收盘活跃
t = np.linspace(0, 1, n)
u = 0.6 + 4.8 * (t - 0.5) ** 2
return u / np.sqrt((u ** 2).mean()) # 归一化, 保持日总方差不变
def simulate_day(corr, n):
L = np.linalg.cholesky(corr)
z = rng.standard_normal((n, n_assets)) @ L.T
return z * (day_vol / np.sqrt(n))[None, :] * intraday_u(n)[:, None]
all_days = np.array([simulate_day(corr_calm if d < 30 else corr_crisis, fine_n)
for d in range(n_days)]) # (60, 390, 4)pythonRC 的核心计算只有一行——日内收益矩阵的自乘:
def realized_cov(r): # r: (M, n_assets) 日内收益
return r.T @ r # 外积和 = 已实现协方差矩阵
def to_corr(c): # 协方差 → 相关矩阵
s = np.sqrt(np.diag(c))
return c / np.outer(s, s)python注意这里不减均值。日内收益的漂移项相对波动项是高阶小量(一天的期望收益 ~2bp,单根分钟线的标准差 ~6bp),减样本均值反而引入额外估计噪声——这是 RC 与日线样本协方差在公式上最容易被忽略的差别。
三、第一个坑:微观结构噪声与签名图#
理论说”采样越密越准”,前提是价格过程连续。真实的成交价带着买卖价跳动、最小报价单位、逐笔冲击——观测价 = 有效价 + 噪声。噪声在差分时不会消失,反而随采样次数线性累积进 RC 的对角线:采样 390 次就把噪声方差放大 390 倍。
给模拟价格叠加 6bp 的观测噪声,扫描 1~130 分钟共 8 档采样间隔,对比 RC 与真值的 Frobenius 距离:
noise_std = 0.0006 # 6bp 微观结构噪声
freqs = [1, 2, 5, 10, 15, 30, 65, 130]
for f in freqs:
for d in range(n_days):
p = np.vstack([np.zeros((1, 4)), np.cumsum(all_days[d], axis=0)])
pn = p + rng.standard_normal(p.shape) * noise_std # 加噪声
idx = np.arange(0, fine_n + 1, f)
rc = realized_cov(np.diff(pn[idx], axis=0))
err = np.linalg.norm(rc - true_cov[d]) # Frobenius 误差python
左图是教科书级的两难曲线:无噪声时 1 分钟采样误差最小(0.000053),加了 6bp 噪声后 1 分钟采样误差飙到 0.000577,是最优的 5 分钟采样(0.000192)的 3 倍。右图是所谓”签名图”(signature plot)——把已实现方差画成采样间隔的函数,高频端被噪声系统性推高,形成一个向左上翘起的尾巴。实务判断规则很直接:画签名图,选曲线开始走平的那个频率。对流动性好的股指期货是 15 分钟,对普通个股往往要退到 515 分钟。
四、第二个坑:Epps 效应——采样越细,相关越假#
噪声坑克扣的是对角线(方差),Epps 效应克扣的是非对角线(协方差)。两个资产的成交时刻不同步——股指 ETF 每秒都在跳,黄金 ETF 可能几分钟才有一笔成交。用”上一笔成交价”填充后,细粒度区间里稀疏资产的价格经常纹丝不动,收益为零,与任何资产的乘积都是零——协方差被系统性拉向零。
模拟:让黄金 ETF 平均每 7 分钟才更新一次价格,其余照旧:
mask = rng.random(fine_n + 1) < 1/7 # 黄金仅 1/7 的分钟有成交
last = p[0, 3]
for t in range(fine_n + 1): # 上一笔价格填充
if mask[t]: last = p[t, 3]
p_sparse[t, 3] = lastpython
真实相关是 -0.10。1 分钟采样下 RC 只量出 -0.04——六成的相关性被非同步性吃掉了;放粗到 30 分钟恢复至 -0.088,65 分钟基本回到 -0.105。这就是 Epps 效应的经典形态:相关系数随采样频率变细而单调走向零。它和噪声坑的处方方向相反——噪声让你想采粗一点,Epps 让协方差在粗采样下才靠谱,而粗采样又丢样本量。工程上的折中方案:对角线(方差)用细采样,非对角线(相关)用粗采样或同步化采样(refresh time),再把两者拼回一个矩阵;学术界的答案则是 Multivariate Realized Kernel 和 Hayashi–Yoshida 估计器这类免同步方法。
五、正餐:RC 到底比日线快多少#
填完坑,看 RC 真正的卖点。用 5 分钟采样构建每天的 RC,取股指-科技的相关系数,与 20 日日线滚动相关同台对比:

第 30 天 regime 切换(真实相关从 0.6 跳到 0.9):
- RC 5 日均线:2 天后突破 0.8。单日 RC 当天就跳上去了,只是单日估计噪声大,稍作平滑更稳;
- 20 日日线滚动相关:17 天后才突破 0.8。整个窗口被新 regime 数据填满之前,它一直在报一个新旧混合的假数字。
平静期与危机期的 RC 相关矩阵热图把结构变化看得更直白:

股指-科技从 0.60 到 0.89,股指-黄金从 -0.09 加深到 -0.39——危机期”分散化消失”(股票间抱团)与”避险资产更避险”两个特征同时被 RC 从盘中数据里量了出来,而且每个数字只用了当天 78 个 5 分钟区间。
六、实战检验:最小方差组合对决#
估计器好不好,最终要在组合里见真章。从第 20 天起,每天分别用三种权重构建组合,统计次日实现波动(含 regime 切换的 39 天样本外):
def min_var_w(cov): # 最小方差权重(允许做空)
inv = np.linalg.inv(cov)
w = inv @ np.ones(n_assets)
return w / w.sum()
w_rc = min_var_w(rc_5day_mean) # RC 5 日均
w_dl = min_var_w(np.cov(daily_ret[-20:].T)) # 20 日日线协方差
w_eq = np.ones(4) / 4 # 等权对照python
结果:等权 16.95%,日线协方差 8.75%,RC 8.62%(次日实现波动年化)。两点解读:
- 任何一个像样的协方差估计都碾压等权——把 35% 波动的科技股和 12% 波动的黄金等权混合本来就是错的,这一半功劳属于”对角线估对了”;
- RC 对日线的优势(8.62% vs 8.75%)看起来只有一点点,但集中兑现在切换后的两周——那正是日线协方差还在用平静期数字配权重、组合暴露被系统性低估的窗口。样本只有 60 天、4 个资产,这个差距的量级是保守的;资产数上去、切换更剧烈时差距会拉大。
七、两个结构性天花板#
诚实起见,RC 有两个再怎么调参也绕不开的限制:
维度灾难比日线来得更快。 RC 的秩不超过日内区间数 M。5 分钟采样一天只有 78 个区间,资产数一旦超过 78,RC 矩阵必然奇异,求逆直接爆炸。日线估计好歹能靠拉长窗口凑样本,RC 一天就这么多区间。大规模组合的标准处方:RC 只估一个低维因子协方差(行业/风格因子),个股残差回到压缩估计(shrinkage),或直接对 RC 做特征值清洗。
隔夜缺口不在盘中。 RC 只积分了交易时段的协方差,而 A 股和美股约有两到四成的日方差发生在隔夜跳空里——财报、政策、外盘全在闭市时间落地。直接拿 RC 当”日协方差”会系统性低估风险。常见修补:把隔夜收益作为一个额外区间加进外积和(简单但把跳空当成了一根普通 bar),或对盘中 RC 乘一个”全天方差/盘中方差”的校准系数。
八、结语#
已实现协方差的本质是一次样本量来源的置换:把”跨天数”换成”日内区间数”,让协方差估计的时效性从周级压缩到天级。本文的实验给出了完整的收益-成本清单——收益是 regime 切换的响应速度快 8 倍(2 天 vs 17 天)、最小方差组合在切换期少挨打;成本是必须直面微观结构噪声(签名图选频率)、Epps 效应(相关与方差分开采样)、维度上限(因子化)和隔夜缺口(校准系数)四道工序。跳过任何一道,高频数据带来的不是信息而是幻觉。对多资产风险管理来说,RC 不是日线协方差的替代品,而是它的快速通道:日线给长期结构,RC 给盘中脉搏——危机来的时候,你需要的是脉搏。
风险提示:本文全部实验基于合成数据,用于隔离和展示估计器的统计性质;真实市场的微观结构噪声非高斯且与波动相关,Epps 效应受具体品种流动性影响,文中数字不构成对任何真实资产的估计或投资建议。