查看全集:💎Quantopia量化分析56讲
因子模型是量化金融中的核心工具,用于分解资产收益的来源。其基本形式为:
小练习:假设某基金年化主动收益为5%,主动风险为8%,请计算其信息比率。
import yfinance as yf
import pandas as pd
# 获取因子数据(示例使用Fama-French三因子)
ff3 = yf.download('F-F_Research_Data_Factors', start='2015-01-01', end='2020-01-01')['Adj Close']
# 获取个股数据
stocks = yf.download(['AAPL', 'MSFT', 'GOOG'], start='2015-01-01', end='2020-01-01')['Adj Close']
stock_returns = stocks.pct_change().dropna()
import statsmodels.api as sm
def calculate_factor_exposure(returns, factors):
X = sm.add_constant(factors)
model = sm.OLS(returns, X).fit()
return model.params[1:] # 返回因子暴露系数
# 示例:计算苹果股票的因子暴露
aapl_returns = stock_returns['AAPL']
factor_exposures = calculate_factor_exposure(aapl_returns, ff3[['Mkt-RF', 'SMB', 'HML']])
print(f"AAPL因子暴露:\n市场因子: {factor_exposures[0]:.2f}\n规模因子: {factor_exposures[1]:.2f}\n价值因子: {factor_exposures[2]:.2f}")
# 滚动窗口设置(60天窗口)
window_size = 60
rolling_betas = pd.DataFrame(index=aapl_returns.index, columns=ff3.columns)
for i in range(window_size, len(aapl_returns)):
X = sm.add_constant(ff3.iloc[i-window_size:i])
model = sm.OLS(aapl_returns.iloc[i-window_size:i], X).fit()
rolling_betas.iloc[i] = model.params[1:]
rolling_betas.plot(figsize=(12,6))
plt.title('苹果股票滚动因子暴露')
plt.ylabel('Beta系数');
def calculate_fmcar(betas, factor_cov, active_risk):
"""
betas: 因子暴露向量
factor_cov: 因子协方差矩阵
active_risk: 主动风险值
"""
marginal_contributions = betas * (factor_cov @ betas)
return marginal_contributions / (active_risk**2)
# 示例计算
factor_cov = ff3[['Mkt-RF', 'SMB', 'HML']].cov()
active_risk = aapl_returns.std()
fmcar = calculate_fmcar(factor_exposures, factor_cov, active_risk)
print("各因子边际风险贡献:")
for factor, contribution in zip(fmcar.index, fmcar.values):
print(f"{factor}: {contribution:.2%}")
plt.pie(fmcar, labels=fmcar.index, autopct='%1.1f%%')
plt.title('风险贡献分解');
假设需要构建对价值因子(HML)中性的组合:
from scipy.optimize import minimize
def neutralize_factor(benchmark_exposure, stock_exposures):
n_stocks = len(stock_exposures)
initial_weights = np.ones(n_stocks)/n_stocks
def objective(weights):
return np.sum((weights @ stock_exposures - benchmark_exposure)**2)
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x)-1})
bounds = [(0,1) for _ in range(n_stocks)]
result = minimize(objective, initial_weights,
constraints=constraints, bounds=bounds)
return result.x
# 示例:中性化价值因子
hml_exposures = pd.DataFrame({
'AAPL': 0.12,
'MSFT': -0.08,
'GOOG': 0.05
}, index=['HML'])
optimal_weights = neutralize_factor([0], hml_exposures.T)
print("最优组合权重:", optimal_weights)
小练习:选取5只中国A股股票,使用FF3模型计算其2022年因子暴露,并分析行业因素的影响。
附录:yfinance数据获取注意事项
# 获取多只股票数据正确方式
data = yf.download(['AAPL', 'MSFT'], start='2020-01-01', end='2023-01-01')
# 数据清洗步骤示例
closes = data['Adj Close'].ffill().dropna()
returns = closes.pct_change().dropna()