4、相关性分析:皮尔逊、斯皮尔曼相关系数在资产筛选中的应用
做跨资产套利,第一步不是找策略,而是找「对的人」。
什么意思?你得先搞清楚哪些资产之间真的存在联动关系。如果两个品种八竿子打不着,你硬要做配对套利,那纯粹是给自己找麻烦。我早年就干过这种蠢事——把螺纹钢和豆粕放在一起算相关性,结果回测曲线漂亮得不行,实盘一跑直接崩了。后来才明白,那纯粹是数据挖掘出来的伪相关。
4.1 为什么相关性是套利的基石?
套利的本质,是赚「价差回归」的钱。但前提是——价差必须会回归。
如果两个资产根本不相关,价差就是随机游走,你进去就是赌大小。相关性分析,说白了就是帮你筛选出那些「天生就该在一起」的品种。
核心逻辑: 只有高相关性的资产,价差才具备均值回归特性。相关性越低,套利策略的胜率越接近抛硬币。
我个人习惯把相关性分成三个档次:
- 0.8 以上: 强相关,适合做套利。比如沪深300和上证50,同涨同跌是常态。
- 0.5 - 0.8: 中等相关,可以做,但需要额外筛选。比如黄金和白银,有时候会背离。
- 0.5 以下: 弱相关,别碰。你想想看,两个走势都没关系的品种,价差怎么回归?
4.2 皮尔逊相关系数:最常用的线性关系度量
皮尔逊相关系数,大家应该都见过。公式我就不写了,你肯定知道。它的核心是衡量两个变量之间的线性关系。
但这里有个坑——皮尔逊对异常值极其敏感。我在项目中遇到过一件事:有一次分析比特币和以太坊的相关性,正常情况都在0.9以上。结果某天比特币闪崩,数据里多了一个极端值,相关系数直接掉到0.3。我当时差点把这个配对删掉,还好多看了一眼散点图。
注意: 皮尔逊相关系数假设数据是正态分布且线性相关。如果你的数据有厚尾、有异常值,结果会严重失真。
代码实现很简单,用 numpy 或者 pandas 都行:
import numpy as np
import pandas as pd
# 假设你有两个资产的价格序列
asset_a = np.array([100, 102, 101, 105, 107])
asset_b = np.array([50, 51, 50.5, 52.5, 53.5])
# 计算皮尔逊相关系数
pearson_corr = np.corrcoef(asset_a, asset_b)[0, 1]
print(f"皮尔逊相关系数: {pearson_corr:.4f}")
# 用pandas也行
df = pd.DataFrame({'A': asset_a, 'B': asset_b})
print(f"pandas 结果: {df.corr().iloc[0, 1]:.4f}")
嗯,这里要注意:计算之前最好先做差分或者对数收益率,直接用价格算相关性会有伪回归的问题。我早期吃过这个亏,后来就养成了习惯——永远用收益率算相关性。
4.3 斯皮尔曼相关系数:非线性关系的救星
皮尔逊搞不定的情况,斯皮尔曼来补。它不关心具体数值,只关心排名。说白了,就是看两个资产的涨跌顺序是否一致。
举个例子:假设资产A涨了5%,资产B涨了3%。皮尔逊看的是「5%和3%」这两个数字的关系,斯皮尔曼看的是「A涨得比B多」这个排名关系。
为什么需要斯皮尔曼?因为金融市场很多时候不是线性的。比如极端行情下,所有资产一起暴跌,但跌幅比例可能完全不同。这时候皮尔逊会告诉你相关性下降,但斯皮尔曼会告诉你——其实它们还是同涨同跌的。
我的经验: 做跨品种套利时,我一般两个系数都算。如果皮尔逊和斯皮尔曼差距很大(比如超过0.2),说明可能存在非线性关系或者异常值干扰,这时候我会进一步检查数据。
代码实现:
from scipy.stats import spearmanr
# 继续用上面的数据
spearman_corr, p_value = spearmanr(asset_a, asset_b)
print(f"斯皮尔曼相关系数: {spearman_corr:.4f}")
print(f"p值: {p_value:.4f}")
p值很重要。如果p值大于0.05,说明相关性不显著,就算系数算出来是0.9也别信。我见过有人拿着p值0.1的相关性去做套利,结果亏得底裤都不剩。
4.4 实战:如何用相关性筛选套利对?
光讲理论没意思,咱们来点实际的。假设你有10个资产,想找出最适合做套利的配对,怎么做?
我的流程是这样的:
- 数据准备: 取日线数据,计算对数收益率。记住,用价格算相关性是新手才会犯的错。
- 计算相关性矩阵: 同时算皮尔逊和斯皮尔曼,得到两个矩阵。
- 筛选候选对: 两个系数都大于0.8的,进入候选池。
- 检查差异: 如果皮尔逊和斯皮尔曼差距大于0.15,标记为「需人工复核」。
- 可视化验证: 画散点图,肉眼确认一下。这一步不能省,我吃过亏。
避坑指南: 我曾经用全自动筛选跑出来一组「完美」的套利对——黄金和某只小盘股,相关性0.95。结果一查,那只股票是黄金矿企,本身就是跟黄金走的。这种相关性是假的,因为存在共同因子。所以筛选完一定要做逻辑验证。
下面是一个完整的筛选代码框架:
import pandas as pd
import numpy as np
from scipy.stats import spearmanr
import itertools
def filter_pairs(price_df, threshold=0.8):
"""
筛选套利候选对
price_df: DataFrame, 每列是一个资产的价格
threshold: 相关性阈值
"""
# 计算对数收益率
returns = np.log(price_df / price_df.shift(1)).dropna()
# 计算皮尔逊矩阵
pearson_matrix = returns.corr()
# 准备结果
results = []
assets = returns.columns
for a, b in itertools.combinations(assets, 2):
# 皮尔逊
p_corr = pearson_matrix.loc[a, b]
# 斯皮尔曼
s_corr, p_val = spearmanr(returns[a], returns[b])
# 筛选条件
if p_corr > threshold and s_corr > threshold:
diff = abs(p_corr - s_corr)
results.append({
'pair': f"{a}-{b}",
'pearson': round(p_corr, 4),
'spearman': round(s_corr, 4),
'diff': round(diff, 4),
'p_value': round(p_val, 4)
})
result_df = pd.DataFrame(results)
result_df = result_df.sort_values('pearson', ascending=False)
return result_df
# 使用示例
# result = filter_pairs(price_data)
# print(result.head(10))
4.5 知识体系总览
说了这么多,我画了一张图帮你理清思路。相关性分析在整个套利流程中的位置,以及两种系数的适用场景,一目了然。
4.6 总结一下
相关性分析不是万能的,但没有相关性分析是万万不能的。我见过太多人一上来就搞协整、搞机器学习,结果连最基本的皮尔逊和斯皮尔曼都没搞清楚。
记住三点:
- 用收益率算相关性,别用价格
- 皮尔逊和斯皮尔曼一起看,互相验证
- 算完一定要做逻辑验证,别信数据挖掘
做到这三点,你的套利对筛选至少不会犯低级错误。至于更高级的协整分析、半衰期计算,那是后面章节的事。先把基础打牢,后面才能走远。
一个小技巧: 如果你发现两个资产的皮尔逊系数很高但斯皮尔曼很低,大概率是存在异常值。这时候别急着删数据,先看看那段时间发生了什么。有时候异常值本身就是交易机会。
公众号:蓝海资料掘金营,微信deep3321