欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 180+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!
引言
在量化交易和投资组合管理中,了解不同资产之间的相关性至关重要。无论是构建分散化投资组合、设计配对交易策略,还是进行风险对冲,相关性分析都是不可或缺的工具。
本文将介绍如何使用 Python 中的 TA-Lib 库计算皮尔逊相关系数(Pearson's Correlation Coefficient),并通过实际案例展示如何分析两只股票之间的关系。这对于学习 Python 金融数据分析的朋友来说,是一个非常实用的技能。
什么是皮尔逊相关系数
皮尔逊相关系数(通常用 r 表示)是一个统计量,用于衡量两个连续变量之间线性关系的强度和方向。在金融领域,这两个变量通常是两种不同资产的价格序列。
相关系数的取值范围
相关系数的取值范围在 -1 到 +1 之间:
- +1(完全正相关):两个资产完全同步移动,一个上涨时另一个也按比例上涨
-
-1(完全负相关):两个资产完全反向移动,一个上涨时另一个按比例下跌
- 0(无线性相关):两个资产的价格变动在统计上是独立的
- 0 到 +1 之间:表示不同程度的正相关(如 +0.7 表示强正相关,+0.2 表示弱正相关)
- 0 到 -1 之间:表示不同程度的负相关(如 -0.7 表示强负相关,-0.2 表示弱负相关)
重要提示
需要注意的是,皮尔逊相关系数只能衡量线性关系。两个资产可能存在很强的非线性关系,但相关系数仍然接近于零。此外,相关性不等于因果关系。
相关性在金融中的应用
1. 投资组合分散化
分散化是现代投资组合理论的核心。通过组合相关性低或负相关的资产,可以在一个资产下跌时,用另一个资产的收益来抵消损失,从而降低整体投资组合的波动性。
2. 配对交易
配对交易策略利用历史上相关的资产之间的临时背离。如果两个资产通常一起移动但突然出现分歧,交易者可能会做多表现不佳的资产,同时做空表现较好的资产,预期它们会回归历史均值关系。
3. 风险评估
相关性有助于量化系统性风险。与大盘指数(如标普 500)高度相关的资产通常会与市场同步移动。这种关系是资本资产定价模型(CAPM)中 Beta 系数的基础。
4. 风险对冲
对冲策略通常依赖于相关性。如果你持有某个资产的多头头寸,可以通过做空正相关的资产或做多负相关的资产来对冲风险。
使用 TA-Lib 计算滚动相关性
TA-Lib 库提供了一个内置函数来计算滚动相关性:
talib.CORREL(prices1, prices2, timeperiod=N)
参数说明
- prices2:第二个价格序列(例如资产 B),长度必须与 prices1 相同
完整代码示例
下面的代码展示如何下载两只股票的价格数据、对齐数据、计算滚动相关性,并可视化结果:
import yfinance as yf
import talib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# --- 1. 数据获取和对齐 ---
asset1_symbol = "AAPL" # 示例:苹果公司
asset2_symbol = "MSFT" # 示例:微软公司(也可以使用 "SPY" 代表市场指数)
data_start_date = "2023-01-01"
data_end_date = "2024-05-01"
try:
# 下载两个资产的价格数据
data_asset1 = yf.download(asset1_symbol, start=data_start_date, end=data_end_date)
data_asset2 = yf.download(asset2_symbol, start=data_start_date, end=data_end_date)
if data_asset1.empty or data_asset2.empty:
raise ValueError("一个或两个资产的数据下载失败。")
# 如果存在多级列,删除额外的列级别
if isinstance(data_asset1.columns, pd.MultiIndex) and data_asset1.columns.nlevels > 1:
data_asset1.columns = data_asset1.columns.droplevel(level=1)
if isinstance(data_asset2.columns, pd.MultiIndex) and data_asset2.columns.nlevels > 1:
data_asset2.columns = data_asset2.columns.droplevel(level=1)
# 使用收盘价并按日期对齐
close_prices_asset1 = data_asset1[['Close']].rename(columns={'Close': f'Close_{asset1_symbol}'})
close_prices_asset2 = data_asset2[['Close']].rename(columns={'Close': f'Close_{asset2_symbol}'})
aligned_data = close_prices_asset1.join(close_prices_asset2, how='inner')
if aligned_data.empty or len(aligned_data) 2:
raise ValueError("对齐后没有足够的重叠数据。")
prices1 = aligned_data[f'Close_{asset1_symbol}']
prices2 = aligned_data[f'Close_{asset2_symbol}']
aligned_date_index = aligned_data.index
except Exception as e:
print(f"数据获取或对齐错误:{e}")
aligned_data = pd.DataFrame()
if not aligned_data.empty:
# --- 2. 滚动皮尔逊相关系数计算 ---
time_period_correl = 30 # 例如,30 天滚动相关性
if len(prices1) >= time_period_correl:
correl_values = talib.CORREL(prices1, prices2, timeperiod=time_period_correl)
indicator_name = f"CORREL({time_period_correl})"
print(f"\n--- {indicator_name} - 皮尔逊相关系数({asset1_symbol} vs {asset2_symbol})---")
valid_correl_values = correl_values[~np.isnan(correl_values)]
if len(valid_correl_values) >= 5:
print(f"{indicator_name} 输出(最后 5 个有效值):{valid_correl_values[-5:]}")
elif len(valid_correl_values) > 0:
print(f"{indicator_name} 输出(所有有效值):{valid_correl_values}")
else:
print(f"{indicator_name} 输出:未计算出有效值。")
# --- 3. 可视化 ---
fig, axes = plt.subplots(2, 1, figsize=(14, 10), sharex=True, gridspec_kw={'hspace': 0.1})
# 绘制资产 1 价格
axes[0].plot(aligned_date_index, prices1, label=f'{asset1_symbol} 价格', color='blue', linewidth=1.5)
axes[0].set_title(f'{asset1_symbol} 价格和滚动相关性(与 {asset2_symbol})', fontsize=14)
axes[0].set_ylabel(f'{asset1_symbol} 价格', fontsize=12)
axes[0].legend(loc='upper left')
axes[0].grid(True, linestyle=':', alpha=0.6)
# 绘制滚动相关性
axes[1].plot(aligned_date_index, correl_values, label=indicator_name, color='purple', linewidth=1.5)
axes[1].axhline(1.0, color='red', linestyle='--', linewidth=0.8, label='完全正相关 (+1)')
axes[1].axhline(0, color='gray', linestyle=':', linewidth=0.8, label='无相关 (0)')
axes[1].axhline(-1.0, color='green', linestyle='--', linewidth=0.8, label='完全负相关 (-1)')
axes[1].set_ylim(-1.1, 1.1)
axes[1].set_ylabel('相关系数', fontsize=12)
axes[1].set_xlabel('日期', fontsize=12)
axes[1].legend(loc='lower left')
axes[1].grid(True, linestyle=':', alpha=0.6)
plt.tight_layout()
plt.show()
else:
print(f"\n跳过 CORREL 绘图:对齐数据不足(需要 > {time_period_correl} 个数据点)。")
if not aligned_data.empty:
print(f"可用的对齐数据点:{len(prices1)}。")
else:
print(f"\n跳过 CORREL 绘图:数据准备失败。")
代码详解
1. 导入库
代码使用 yfinance 获取数据,TA-Lib 计算相关性,matplotlib 和 pandas 进行分析和可视化。
2. 数据获取和对齐
- 在共同的交易日期上对齐序列并删除缺失值,以确保有效的相关性计算
3. 滚动相关性计算
- 设置窗口长度(time_period_correl)
- 计算 talib.CORREL() 获得滚动相关性数组
4. 绘图
- 在 +1、0 和 -1 处添加水平参考线,便于解读
5. 错误处理
如果数据下载或对齐失败,或数据不足,代码会提供有用的提示信息。
结果解读和实际应用
这个分析帮助我们可视化两个资产之间的关系如何随时间演变。例如:
- 高正相关:表明市场暴露相似(如 AAPL 与 MSFT)
- 相关性波动:可能预示着市场制度转变或资产关系的结构性变化
滚动相关性分析支持分散化投资、配对交易和风险管理,是现代投资组合分析中的重要量化工具。
总结
本文介绍了皮尔逊相关系数的基本概念,以及如何使用 Python 的 TA-Lib 库计算两个资产之间的滚动相关性。通过完整的代码示例,我们展示了从数据获取、计算到可视化的完整流程。
掌握相关性分析技能,对于任何从事量化交易、投资组合管理或金融数据分析的 Python 学习者来说都非常重要。希望这篇文章能帮助你更好地理解和应用相关性分析工具。
参考文章
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。财经数据与量化投研知识社区
核心权益如下:
- 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
- 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
- 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
- 每日分享高质量量化投研文章(已更新 180+篇)、代码和相关资料
星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!