查看全集:💎Quantopia量化分析56讲
斯皮尔曼等级相关系数(Spearman Rank Correlation)是一种非参数统计方法,用于衡量两个变量之间的单调关系。与皮尔逊相关系数不同,斯皮尔曼相关不要求数据呈线性关系,也不要求数据服从正态分布,因此适用范围更广。
单调关系指两个变量变化方向的一致性。举例说明:
当数据存在以下情况时适用:
与皮尔逊相关系数的对比:
指标 | 皮尔逊 | 斯皮尔曼 |
数据要求 | 线性关系、正态分布 | 单调关系 |
异常值敏感度 | 高 | 低 |
测量尺度 | 要求相同 | 可不同 |
处理重复值的平均等级法:
import scipy.stats as stats
data = [85, 90, 78, 90, 92]
print(stats.rankdata(data, method='average')) # [2. 3.5 1. 3.5 5.]
参数说明:
手动计算示例:
X = [10, 9, 5, 7, 5]
Y = [20, 17, 11, 15, 13]
# 转换等级
X_rank = [5,4,1.5,3,1.5]
Y_rank = [5,4,1,3,2]
# 计算差值平方和
d_sq = sum([(x-y)**2 for x,y in zip(X_rank,Y_rank)]) # 0.5
rho = 1 - 6*0.5/(5*(25-1)) # 0.975
import numpy as np
from scipy import stats
x = np.random.normal(size=100)
y = np.exp(x) + np.random.normal(scale=0.5, size=100)
corr, p_value = stats.spearmanr(x, y)
print(f"相关系数: {corr:.3f}, p值: {p_value:.4f}")
import yfinance as yf
import pandas as pd
# 获取标普500和道琼斯指数数据
data = yf.download(['^GSPC', '^DJI'], start='2020-01-01', end='2023-01-01')['Close']
returns = data.pct_change().dropna()
# 计算滚动三个月相关性
rolling_corr = returns.rolling(60).corr(pairwise=True).iloc[:,0,1]
# 可视化
import matplotlib.pyplot as plt
plt.figure(figsize=(10,6))
rolling_corr.plot(title='3个月滚动斯皮尔曼相关性')
plt.ylabel('相关系数')
plt.show()
# 获取股票数据
symbols = ['AAPL', 'MSFT', 'GOOG', 'AMZN', 'META']
data = yf.download(symbols, period='1y')['Close']
# 计算月度收益
monthly_returns = data.resample('M').last().pct_change()
# 生成因子(过去三个月动量)
factor = monthly_returns.rolling(3).mean().shift(1)
# 计算等级相关性
correlations = []
for i in range(3, len(monthly_returns)):
current_factor = factor.iloc[i].rank()
next_return = monthly_returns.iloc[i].rank()
corr = stats.spearmanr(current_factor, next_return).correlation
correlations.append(corr)
print(f"平均前瞻相关性: {np.mean(correlations):.3f}")
def detect_lag_correlation(x, y, max_lag=5):
correlations = []
for lag in range(max_lag+1):
shifted_y = y.shift(-lag).dropna()
common_index = x.index.intersection(shifted_y.index)
corr = stats.spearmanr(x.loc[common_index], shifted_y.loc[common_index]).correlation
correlations.append((lag, corr))
return pd.DataFrame(correlations, columns=['Lag', 'Correlation'])
# 使用示例
np.random.seed(42)
x = pd.Series(np.random.rand(100))
y = x.shift(2).iloc[2:].reset_index(drop=True) + np.random.normal(scale=0.1, size=98)
results = detect_lag_correlation(x, y)
print(results.sort_values('Correlation', ascending=False))
p值的解读指南:
当出现相同值时:
两者比较:
指标 | 计算方式 | 灵敏度 |
斯皮尔曼 | 等级差平方 | 对趋势敏感 |
肯德尔tau | 一致对比例 | 更稳健 |
练习:
# 练习参考答案
# 练习1:
aapl = yf.download('AAPL', period='1y')
aapl['Return'] = aapl['Close'].pct_change()
aapl['Volume'] = aapl['Volume']
corr = stats.spearmanr(aapl['Return'].dropna(), aapl['Volume'].dropna())
print(f"收益率与交易量相关性:{corr.correlation:.3f}")
通过本教程,您应该掌握了斯皮尔曼相关系数的核心原理、实现方法及在金融分析中的典型应用。在实际研究中,建议结合可视化分析和统计检验综合判断变量间的关系。