数据准备与工具:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import yfinance as yf
from sklearn.covariance import LedoitWolf
import seaborn as sns
import statsmodels.api as sm
# 数据获取函数
def get_stock_data(tickers, start, end):
data = yf.download(tickers, start=start, end=end)
return data['Close'] # 仅使用收盘价一、系统性风险与对冲的必要性#
在构建交易策略时,系统性风险是需要重点管理的对象。这类风险无法通过分散投资消除,需要通过构建对冲来降低影响。本文将通过三个逐步优化的案例,展示如何通过Beta对冲和行业对冲来降低资产间的相关性,提升策略的有效性。
关键概念:
-
Beta系数:衡量资产对市场波动的敏感度
-
残差收益:资产收益中无法被市场或行业因素解释的部分 计算公式: 市场对冲残差 = 资产收益 - Beta * 市场收益 行业对冲残差 = 市场残差 - 行业Beta * 行业收益
二、对冲策略案例#
2.1 案例1:无对冲策略#
-
获取股票历史数据
-
计算收益率
-
分析相关性
tickers = ['WFC', 'JPM', 'USB', 'XOM', 'BHI', 'SLB']
start = '2015-01-01'
end = '2017-02-22'
# 获取数据
prices = get_stock_data(tickers, start, end)
returns = prices.pct_change().dropna()
# 计算协方差矩阵
lw = LedoitWolf().fit(returns)
cov_matrix = lw.covariance_
# 转换为相关系数
def cov_to_corr(cov):
d = np.sqrt(np.diag(cov))
return cov / np.outer(d, d)
corr_matrix = cov_to_corr(cov_matrix)
# 可视化
plt.figure(figsize=(12,6))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm',
xticklabels=tickers, yticklabels=tickers)
plt.title('无对冲策略相关系数矩阵(平均相关系数:0.56)')现象观察:金融股(WFC、JPM、USB)与能源股(XOM、BHI、SLB)形成明显聚类,组内相关性高达0.7-0.8
2.2 案例2:Beta对冲策略#
-
加入市场基准(SPY)
-
对每只股票进行市场回归
-
提取残差收益
tickers += ['SPY']
prices = get_stock_data(tickers, start, end)
returns = prices.pct_change().dropna()
# 分离市场收益
market_returns = returns['SPY']
stock_returns = returns.drop('SPY', axis=1)
# 计算市场Beta残差
residuals = pd.DataFrame()
for stock in stock_returns:
model = sm.OLS(stock_returns[stock], sm.add_constant(market_returns))
results = model.fit()
residuals[stock] = results.resid
# 计算对冲后相关系数
lw = LedoitWolf().fit(residuals)
corr_matrix_beta = cov_to_corr(lw.covariance_)
# 可视化对比
fig, axes = plt.subplots(1,2, figsize=(16,6))
sns.heatmap(corr_matrix, ax=axes[0], cmap='coolwarm',
annot=True, vmin=-1, vmax=1)
sns.heatmap(corr_matrix_beta, ax=axes[1], cmap='coolwarm',
annot=True, vmin=-1, vmax=1)关键改进:
-
平均相关系数从0.56降至0.22
-
跨行业相关性显著降低(如金融与能源股相关性降至0.1-0.3)
2.3 案例3:行业对冲策略#
-
加入行业ETF(XLF金融/XLE能源)
-
分行业进行二次对冲
sector_etf = {'金融': 'XLF', '能源': 'XLE'}
tickers = ['WFC', 'JPM', 'USB', 'XOM', 'BHI', 'SLB', 'SPY', 'XLF', 'XLE']
prices = get_stock_data(tickers, start, end)
returns = prices.pct_change().dropna()
# 市场对冲
market_ret = returns['SPY']
sector_rets = {
'金融': returns['XLF'] - market_ret * sm.OLS(returns['XLF'], sm.add_constant(market_ret)).fit().params[1],
'能源': returns['XLE'] - market_ret * sm.OLS(returns['XLE'], sm.add_constant(market_ret)).fit().params[1]
}
# 分行业二次对冲
final_residuals = pd.DataFrame()
for sector in ['金融', '能源']:
sector_stocks = ['WFC','JPM','USB'] if sector == '金融' else ['XOM','BHI','SLB']
sector_ret = sector_rets[sector]
for stock in sector_stocks:
# 市场对冲
model_mkt = sm.OLS(returns[stock], sm.add_constant(market_ret))
res_mkt = model_mkt.fit().resid
# 行业对冲
model_sector = sm.OLS(res_mkt, sm.add_constant(sector_ret))
final_residuals[stock] = model_sector.fit().resid
# 计算最终相关系数
lw = LedoitWolf().fit(final_residuals)
corr_matrix_full_hedge = cov_to_corr(lw.covariance_)效果呈现:
-
金融组内部相关性降至0.05以下
-
跨行业相关性接近零
-
平均相关系数降至0.028
三、有效广度计算#
Buckle公式
其中N为资产数量,ρ为平均相关系数
def effective_breadth(N, rho):
return N / (1 + rho*(N-1))
cases = [
('无对冲', 0.56),
('Beta对冲', 0.22),
('行业对冲', 0.028)
]
plt.figure(figsize=(10,6))
x = np.linspace(0, 1, 100)
for label, rho in cases:
plt.plot(x, effective_breadth(6, x),
label=f'{label} (实际ρ={rho})' if label else None)
plt.legend()
plt.title('不同对冲策略的有效广度对比')
plt.xlabel('平均相关系数ρ')
plt.ylabel('有效广度BR');结论:
-
无对冲:BR ≈ 2
-
Beta对冲:BR ≈ 3.2
-
全对冲:BR ≈ 5.8
小练习#
-
尝试使用不同行业组合(如科技+医疗)复现对冲过程
-
修改Buckle公式计算函数,验证当ρ=0时BR=N
-
计算苹果(AAPL)与微软(MSFT)在不同对冲阶段的相关性变化
# 练习参考答案
# 1. 更换行业ETF代码为XLK(科技)和XLV(医疗)
# 2. 验证函数:
assert np.isclose(effective_breadth(10, 0), 10)
# 3. 苹果微软对冲分析:
tickers = ['AAPL', 'MSFT', 'SPY', 'XLK']
# ...重复上述对冲步骤...下节预告#
在(下)篇中,我们将深入探讨:
-
多因子风险模型的应用
-
动态对冲策略的构建
-
实盘交易中的对冲成本优化
通过本教程,我们验证了系统性风险对冲对提升策略有效性的重要作用。在实际操作中,建议在策略研发初期就纳入风险管理模块,而非事后补救。有效降低资产间相关性可以显著提升策略的夏普比率,为获取alpha收益创造更有利的条件。