实践:计算因子风险暴露#
滚动回归对比分析#
请完成以下任务:
-
获取阿里巴巴(BABA)和英伟达(NVDA)2020-2023年日度收益率数据
-
获取同期Fama-French五因子数据(代码:F-F_Research_Data_5_Factors_2x3)
-
分别计算90日和180日滚动窗口下的市场因子暴露
-
可视化对比不同窗口长度对暴露系数稳定性的影响
code
import yfinance as yf
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
from pandas_datareader import data as web
# 因子数据来自 Ken French Data Library,不是 Yahoo 行情代码
ff5 = web.DataReader(
'F-F_Research_Data_5_Factors_2x3_daily', 'famafrench',
start='2020-01-01', end='2023-12-31',
)[0] / 100
# 个股数据获取
tech_stocks = yf.download(
['BABA', 'NVDA'], start='2020-01-01', end='2023-12-31',
auto_adjust=True, group_by='column', multi_level_index=True,
)['Close']
tech_returns = tech_stocks.pct_change().dropna()
# 数据对齐,并把个股收益转换为相对无风险利率的超额收益
combined_data = tech_returns.join(ff5, how='inner').dropna()
combined_data[tech_returns.columns] = combined_data[tech_returns.columns].sub(
combined_data['RF'], axis=0
)构建追踪组合#
多因子中性组合优化#
请实现以下要求:
-
选取苹果、微软、特斯拉三只股票
-
判断仅使用这三只股票、且不允许做空时,能否同时对市场因子和动量因子(Mom)中性
-
组合需满足个股权重不超过40%的约束
-
检查求解器状态和约束残差;若不可行,说明需要增加何种对冲工具或放宽哪些约束
code
from scipy.optimize import minimize
import numpy as np
# 获取因子暴露数据示例
factor_exposures = pd.DataFrame({
'AAPL': [1.2, 0.8],
'MSFT': [0.9, 0.6],
'TSLA': [1.5, 1.1]
}, index=['Mkt-RF', 'Mom']).T
def multi_factor_neutral(benchmark_exposures):
n_assets = len(factor_exposures)
init_weights = np.ones(n_assets)/n_assets
def objective(w):
return np.sum(w**2) # 在可行解中降低权重集中度;这不是方差模型
constraints = (
{'type': 'eq', 'fun': lambda w: w @ factor_exposures.values - benchmark_exposures},
{'type': 'eq', 'fun': lambda w: np.sum(w)-1}
)
bounds = [(0,0.4) for _ in range(n_assets)]
res = minimize(objective, init_weights,
constraints=constraints, bounds=bounds)
if not res.success:
raise ValueError(f'优化不可行:{res.message}')
residual = res.x @ factor_exposures.values - benchmark_exposures
if np.max(np.abs(residual)) > 1e-8:
raise ValueError(f'因子约束未满足:{residual}')
return res.x
# 目标因子暴露(全市场中性)
target_exposures = [0, 0] # 市场因子和动量因子均为中性这里给出的三只股票对两个因子的暴露都为正,同时又要求权重非负且总和为 1,因此 target_exposures = [0, 0] 不可行。这个例子应当保留失败检查:要得到真正的因子中性组合,需要加入可做空的股票或因子对冲工具,并重新设置权重/总敞口约束;不能忽略求解器状态后直接使用 res.x。