4、相关系数与距离法:如何筛选配对

做统计套利,第一步就是找配对。

说白了,你得找到两只股票,它们之间有种「说不清道不明」的亲密关系。涨一起涨,跌一起跌。哪怕短期分开了,最终也会回到一起。

那怎么量化这种关系呢?

我这些年用过不少方法,最常用的就是相关系数和距离法。今天我把压箱底的经验都掏出来,跟你聊聊。

4.1 皮尔逊相关系数

这是最经典的方法。我刚开始做量化时,第一个用的就是它。

皮尔逊相关系数衡量的是线性相关。值在 -1 到 1 之间。1 表示完全正相关,-1 表示完全负相关,0 就是没关系。

核心公式:

ρ = Cov(X, Y) / (σX * σY)

其中 Cov 是协方差,σ 是标准差。

实际应用中,我一般取绝对值大于 0.7 的。但这里有个坑——

我曾经踩过的坑:

皮尔逊相关系数对异常值极其敏感。有一次我筛选出两只股票,相关系数高达 0.95,结果发现是因为某天一只股票数据异常,拉高了整个相关性。后来我学乖了,每次算之前先做数据清洗。

代码实现很简单:

import numpy as np
import pandas as pd

# 假设 df 包含两只股票的价格数据
def pearson_corr(df, stock1, stock2):
    return df[stock1].corr(df[stock2])

# 批量计算所有配对
corr_matrix = df.corr(method='pearson')

4.2 Spearman秩相关系数

皮尔逊有个硬伤——它要求数据服从正态分布,且关系是线性的。

但现实中的股票数据,哪有那么乖?

这时候就该 Spearman 出场了。

Spearman 不关心具体数值,它只关心排名。你把两只股票的价格分别排序,然后看排名之间的相关性。

我的个人习惯:

当数据有明显非线性特征时,我优先用 Spearman。比如某些小盘股,波动大、分布怪异,Spearman 比皮尔逊靠谱得多。

def spearman_corr(df, stock1, stock2):
    return df[stock1].corr(df[stock2], method='spearman')

# 对比一下两种方法
pearson = pearson_corr(df, 'AAPL', 'MSFT')
spearman = spearman_corr(df, 'AAPL', 'MSFT')
print(f'皮尔逊: {pearson:.3f}, Spearman: {spearman:.3f}')

你想想看,如果两者差距很大,说明关系不是线性的。这时候就要小心了。

4.3 距离法

相关系数看的是「方向一致性」,距离法看的是「数值接近度」。

我个人的理解是:相关系数告诉你两只股票是不是同涨同跌,距离法告诉你它们涨跌的幅度是不是差不多。

4.3.1 最小平方距离

也叫欧氏距离。计算两只股票标准化价格之间的平方差之和。

def euclidean_distance(series1, series2):
    # 先标准化
    s1 = (series1 - series1.mean()) / series1.std()
    s2 = (series2 - series2.mean()) / series2.std()
    return np.sqrt(np.sum((s1 - s2) ** 2))

距离越小,说明两只股票的价格走势越「贴合」。

4.3.2 曼哈顿距离

这个我用的少一些,但在某些场景下很管用。

曼哈顿距离计算的是绝对差之和,对异常值没那么敏感。

def manhattan_distance(series1, series2):
    s1 = (series1 - series1.mean()) / series1.std()
    s2 = (series2 - series2.mean()) / series2.std()
    return np.sum(np.abs(s1 - s2))

什么时候用曼哈顿?

我记得有一次处理高频数据,数据里有很多毛刺。欧氏距离被这些毛刺搞得一塌糊涂,换成曼哈顿就好多了。

4.4 如何用相关系数筛选配对

理论说完了,来点实战的。

我一般按这个流程走:

  1. 数据准备:取过去 1-2 年的日线数据,用对数收益率或标准化价格
  2. 计算相关系数矩阵:所有股票两两计算
  3. 初步筛选:保留相关系数绝对值大于 0.7 的配对
  4. 距离验证:对筛选出的配对计算距离,剔除距离过大的
  5. 稳定性检查:滚动窗口计算相关系数,看是否稳定

避坑指南:

我曾经只看了整体相关系数就冲进去,结果发现最近三个月两只股票的相关性已经变了。所以我现在一定会做滚动窗口检查。

# 滚动窗口相关系数
def rolling_corr(df, stock1, stock2, window=60):
    return df[stock1].rolling(window).corr(df[stock2])

# 检查稳定性
rolling_corr = rolling_corr(df, 'AAPL', 'MSFT')
if rolling_corr.std() < 0.1:
    print('相关性稳定,可以进一步分析')
else:
    print('相关性波动大,小心!')

4.5 本章知识体系

下面这张图,是我自己总结的筛选流程。你照着做,基本不会出大错。

配对筛选知识体系 数据准备 相关系数法 距离法 皮尔逊 Spearman 欧氏距离 曼哈顿距离 综合筛选:相关性 + 距离 + 稳定性 候选配对列表

嗯,这套流程我用了好几年,虽然简单,但很有效。你刚开始做的时候,先别想着搞太复杂的模型,把基础打牢了再说。

最后说一句:

相关系数和距离法只是筛选工具,不是交易信号。找到配对后,还要做协整检验、确定交易阈值。这些后面的章节会详细讲。


公众号:蓝海资料掘金营,微信deep3321