halo 的技术博客

返回

先给一个会让很多人愣住的事实:同一对股票,你用日线数据算相关系数是 0.6,切到 1 分钟线变成 0.3,再切到 1 秒钟几乎归零。

数据没变,市场关系没变,采样频率变了而已。按常识,频率越高、样本越多,估计应该越准才对。可相关性偏偏反着来——越往高频看,两只资产的相关性越向 0 塌陷。

这个现象 1979 年被 Thomas Epps 发现,此后被反复验证,叫 Epps 效应(Epps Effect)。它不是一个学术玩具:任何做统计套利、配对交易、组合风险、高频对冲的人,只要用高频数据估协方差矩阵,就会一头撞进这个坑——你以为你算的是资产间的真实联动,其实你算的是一堆被采样噪声稀释后的幻觉。

结论先放这:Epps 效应的根源不是市场,是异步成交(asynchronous trading)。 两只股票的成交从不落在同一时刻,你为了把它们对齐到同一个时间网格,用了最自然的办法——前向填充旧价。就是这个填充,在每个细格点里塞进了大量人造的零收益,把相关性拖向 0。本文从零把这套机制和代码走一遍,最后给解药。

先看现象:采样越细,相关性越假#

我先造一个”上帝视角”下确定相关的世界:两条连续的 latent 对数价格,用相关系数 0.6 的布朗运动驱动。然后模拟真实市场里发生的事——成交是离散、稀疏、异步的,你只能在成交发生的时刻看到价格,其余时间靠上一笔成交的旧价撑着。

import numpy as np

rng = np.random.default_rng(2026)
T = 6.5 * 3600          # 一个交易日 6.5 小时(秒)
n = int(T)              # latent 过程以 1 秒推进
rho_true = 0.6
sigma1 = 0.20 / np.sqrt(n)   # 日波动约 20%
sigma2 = 0.25 / np.sqrt(n)

# 相关的连续 latent 对数收益
z = rng.standard_normal((n, 2))
z[:, 1] = rho_true * z[:, 0] + np.sqrt(1 - rho_true**2) * z[:, 1]
la = np.cumsum(sigma1 * z[:, 0])   # 股票 A 的 latent 对数价格
lb = np.cumsum(sigma2 * z[:, 1])   # 股票 B
python

注意:lalb连续的、每秒都存在的真实价格。它们之间的相关性铁定是 0.6,这是我造出来的。现在模拟观测:每秒以某个概率发生一笔成交,没成交的时刻用 last-tick 前向填充。

对不同采样间隔(1 秒到 30 分钟)各跑 30 次蒙特卡洛取平均,画出观测相关性随采样频率的变化:

Epps 效应主图:采样越细,观测相关性越向 0 塌陷

结果触目惊心:

  • 1 秒采样:ρ ≈ 0.03。 真实相关 0.6,观测到的几乎是 0。在最高频,你完全看不到两只资产的联动。
  • 1 分钟采样:ρ ≈ 0.5。 恢复了一大半。
  • 30 分钟采样:ρ ≈ 0.59。 基本回到真值 0.6。

同一份数据、同一对资产,仅仅因为采样间隔不同,相关系数从 0.03 走到 0.59。这不是估计误差,是系统性偏差——而且方向永远是把相关性往 0 压。

为什么会这样:异步 + 填充 = 人造零收益#

Epps 效应的机制其实很朴素,看懂这张图就懂了:

异步成交示意:细格点内常常只有一边有 tick

两只股票的成交(上蓝下红的竖线)落在完全不同的时刻。现在你要算 10 秒收益的相关性,就得把两条序列都对齐到 10 秒格点上。问题来了:某个 10 秒窗口里,可能只有 A 成交了、B 没成交。

B 没成交怎么办?最常用的做法是 last-tick 填充——用 B 上一笔成交的价格。于是 B 在这个窗口的”收益”是 0(价格没动,因为你根本没有新价格)。而 A 那边有真实成交,收益不是 0。

一边真实波动、一边人造零收益,这一对配下来对协方差的贡献就是 0。 采样越细,每个格点里”只有一边成交”的情况越多,人造零收益越多,相关性被稀释得越狠。这就是为什么高频端相关性塌向 0。

反过来,采样越粗(比如 30 分钟一格),窗口足够长,两只股票在窗口内几乎必然都成交过,收益都是真实的,相关性自然恢复。

一句话总结机制:Epps 效应 = 异步成交 × 强行同步对齐。 两个条件缺一不可。连续市场里不存在这个问题,是”离散成交”和”你想要同步数据”这对矛盾造出来的。

流动性是决定塌陷速度的关键#

既然根源是”细格点里一边没成交”,那成交越频繁(流动性越好),这种情况越少,Epps 衰减就越轻。反过来,冷门股、小盘股成交稀疏,Epps 效应会狠得多。

我把成交强度设成高(0.5 笔/秒)、中(0.1 笔/秒)、低(0.02 笔/秒)三档,看衰减曲线:

流动性越低,Epps 衰减越狠、恢复越晚

  • 高流动性:即使 1 秒采样,相关性也还能保住相当一部分,30 秒左右就基本恢复。
  • 低流动性:1 秒采样相关性趴在地上,得拉到 5~10 分钟才勉强恢复到真值附近。

实务含义很直接:你估一个组合的协方差矩阵,如果里面既有茅台这种流动性巨兽、又有某只日均成交额几千万的小盘股,用同一个采样频率去算,两者的 Epps 偏差程度完全不同。流动性差的资产相关性被低估得更厉害,你的协方差矩阵会系统性地低估它和别人的联动——风险模型据此会告诉你”这个组合很分散”,实际崩盘时它们一起跌,因为真实相关根本没那么低。

解药:Hayashi-Yoshida 估计量#

Epps 效应的病根是”强行把异步数据塞进同步网格”。那最直接的解药就是:别对齐了,直接在异步数据上算协方差。

2005 年 Hayashi 和 Yoshida 给出了一个漂亮的估计量(HY estimator)。思想一句话:A 的每一段收益,乘以所有和它时间上有重叠的 B 收益段,全部累加。 不需要同步,不需要填充,不丢任何一笔成交。

def hy_covariance(times_a, ret_a, times_b, ret_b):
    # times_a/b 是成交时刻,ret_a/b 是相邻成交间的对数收益
    ta0, ta1 = times_a[:-1], times_a[1:]   # 每段收益的起止时刻
    tb0, tb1 = times_b[:-1], times_b[1:]
    cov = 0.0
    for i in range(len(ret_a)):
        # 找出所有与 A 第 i 段时间重叠的 B 段
        overlap = (tb0 < ta1[i]) & (tb1 > ta0[i])
        cov += ret_a[i] * ret_b[overlap].sum()
    return cov

def hy_corr(ta, ra, tb, rb):
    cov = hy_covariance(ta, ra, tb, rb)
    va, vb = (ra**2).sum(), (rb**2).sum()   # HY 下方差就是收益平方和
    return cov / np.sqrt(va * vb)
python

关键在那行 overlap:它不要求 A、B 的成交时刻对齐,只要两段收益在时间轴上有交集就相乘累加。这样既不制造人造零收益,也不丢弃任何真实成交。理论上可以证明,HY 估计量在异步采样下对真实积分协方差是无偏、相合的。

对比一下 1 秒固定网格 last-tick 和 HY 在三种流动性下的表现:

解药:HY 估计量在异步稀疏数据下几乎无偏

固定网格(灰)在低流动性下被 Epps 咬得只剩一点点,HY(绿)三种流动性下都稳稳贴着真值 0.6。这就是为什么严肃的高频协方差估计基本都用 HY 或它的变体,而不是把 tick 数据重采样到固定网格再算 corrcoef。

四类真实陷阱(进阶)#

复现出漂亮曲线只是第一步。真拿这套东西去做研究,下面四个坑一个都躲不开。

陷阱一:把 Epps 偏差误读成”这对资产不相关”。 这是最致命的。你在高频看到相关性接近 0,很容易得出”这两只股票没关系、可以互相对冲/分散”的结论。错。它们的真实相关可能是 0.6,你只是用错了尺度。任何基于高频相关性的配对筛选、风险分散判断,都必须先排除 Epps 偏差——最简单的自检:把采样频率从细往粗扫一遍,如果相关性随尺度单调上升,那你看到的高频低相关十有八九是 Epps 幻觉而不是真实关系。

陷阱二:HY 估计量对时钟误差和异常 tick 极其敏感。 HY 靠”时间重叠”判定哪些收益段相乘,这意味着它高度依赖时间戳的准确性。交易所时钟不同步、数据源打时间戳的延迟、乱序 tick,都会让”重叠”判断出错。更糟的是错单/胖手指造成的价格跳变,会被 HY 原样吸进协方差里。上 HY 之前必须先做 tick 清洗:剔除明显离群的成交价、处理时间戳乱序、对齐不同数据源的时钟基准。脏数据喂进 HY,出来的是精确的垃圾。

陷阱三:微观结构噪声会把方差(对角线)顶上天。 Epps 效应压的是协方差(非对角线),但同一批高频数据里还藏着另一个反向的偏差:买卖价差跳动(bid-ask bounce)会让已实现方差在超高频端被严重高估——价格在买价卖价之间来回弹,制造出大量根本不存在的”波动”。所以你在估协方差矩阵时是两面受敌:对角线被微观结构噪声顶高、非对角线被 Epps 压低,整个矩阵的病态程度(condition number)被双向恶化,做组合优化时会放大成灾难性的权重。实务上常用的折中是”最优采样频率”(比如 5 分钟)或带噪声修正的估计量(TSRV、pre-averaging),而不是无脑上最高频。

陷阱四:多资产下 HY 不保证协方差矩阵半正定。 单对资产用 HY 很干净,但你把 N 个资产两两算 HY 拼成一个 N×N 矩阵时,这个矩阵可能不是半正定的——因为每一对用的重叠区间不一样,缺乏整体一致性。而组合优化(求最小方差权重、算风险平价)严格要求协方差矩阵半正定,否则会解出荒谬的权重甚至无解。拼完 HY 矩阵必须做一步半正定修复(最近邻 PSD 投影、特征值截断),或者改用天生保证半正定的多元估计量。这一步在教科书里常被略过,实盘里却是硬约束。

一句话总结#

Epps 效应告诉你一件反直觉的事:在高频世界里,“更多数据”不等于”更准估计”。 采样越细,异步成交和强行对齐制造的人造零收益越多,相关性被稀释得越狠,直到看起来两个明明联动的资产毫无关系。

破解它靠两件事:理解偏差的方向(永远把相关性往 0 压,且流动性越差越狠),和用对的工具(Hayashi-Yoshida 直接在异步数据上算,不对齐、不填充、不丢数据)。但 HY 也不是银弹——它换来无偏的代价是对数据质量、时钟精度、矩阵半正定性的一整套新要求。

高频相关性从来不是”把数据切细一点算 corrcoef”这么简单。你面对的不是一个数字,是一个被采样机制、流动性、微观结构噪声共同扭曲的观测量。看懂扭曲的方向,你才知道手里的相关系数到底是信号还是幻觉。

Epps 效应与高频相关性:为什么采样越细相关性越假
https://blog.halo26812.eu.org/blog/epps-effect-correlation
Author halo
Published at 2026年7月25日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨