/ / /
第23讲:斯皮尔曼等级相关 (Spearman Rank Correlation)
🔴
入学要求
💯
能力测试
🛣️
课程安排
🕹️
研究资源

第23讲:斯皮尔曼等级相关 (Spearman Rank Correlation)

💡

查看全集:💎Quantopia量化分析56讲

斯皮尔曼等级相关系数(Spearman Rank Correlation)是一种非参数统计方法,用于衡量两个变量之间的单调关系。与皮尔逊相关系数不同,斯皮尔曼相关不要求数据呈线性关系,也不要求数据服从正态分布,因此适用范围更广。

一、基本概念与原理

1.1 什么是单调关系?

单调关系指两个变量变化方向的一致性。举例说明:

1.2 为什么需要等级相关?

当数据存在以下情况时适用:

与皮尔逊相关系数的对比:

指标皮尔逊斯皮尔曼
数据要求线性关系、正态分布单调关系
异常值敏感度
测量尺度要求相同可不同

二、核心公式与计算

2.1 等级转换方法

处理重复值的平均等级法:

import scipy.stats as stats
data = [85, 90, 78, 90, 92]
print(stats.rankdata(data, method='average'))  # [2. 3.5 1. 3.5 5.]

2.2 斯皮尔曼公式

ρ=16di2n(n21)\rho = 1 - \frac{6\sum d_i^2}{n(n^2-1)}

参数说明:

手动计算示例:

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

三、实战应用

3.1 使用scipy快速计算

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}")

3.2 金融数据案例(使用yfinance)

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()

3.3 因子选股验证

# 获取股票数据
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}")

四、进阶话题

4.1 时间延迟相关性检测

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))

4.2 显著性检验

p值的解读指南:


五、常见问题解答

Q1:如何处理等值数据?

当出现相同值时:

Q2:样本量要求?

Q3:与肯德尔tau的区别?

两者比较:

指标计算方式灵敏度
斯皮尔曼等级差平方对趋势敏感
肯德尔tau一致对比例更稳健

练习:

  1. 下载苹果公司过去一年的股价数据,计算其日收益率与交易量的斯皮尔曼相关性
  1. 生成两个具有二次关系的变量(y = x² + noise),比较皮尔逊和斯皮尔曼相关系数
  1. 尝试修改时间延迟检测函数,实现双向延迟检测(正负延迟)
# 练习参考答案
# 练习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}")

通过本教程,您应该掌握了斯皮尔曼相关系数的核心原理、实现方法及在金融分析中的典型应用。在实际研究中,建议结合可视化分析和统计检验综合判断变量间的关系。

附:练习合集