当前位置:首页>python>《使用Python进行投资组合构建和分析》系列二:从 CAPM 到 Smart Beta 的完整知识地图

《使用Python进行投资组合构建和分析》系列二:从 CAPM 到 Smart Beta 的完整知识地图

  • 2026-10-11 08:29:39
《使用Python进行投资组合构建和分析》系列二:从 CAPM 到 Smart Beta 的完整知识地图

写在前面

资产管理领域有一个长期争论:超额收益究竟来自哪里?是运气、技艺,还是系统性地持有了某些"风险因子"的敞口?

EDHEC《Advanced Portfolio Construction and Analysis with Python》课程的第一个模块,正面回应了这个问题——从单因子 CAPM 到 Fama–French 多因子模型,从风格分析到 Smart Beta 构建,全程配以可运行的 Python 代码。

核心洞见:每一个持仓,本质上都是一组因子暴露的叠加,加上一块特有风险(idiosyncratic risk)。


一、什么是"因子"?

因子(Factor)是解释资产收益截面差异与时序变化的系统性维度。按来源可分为三大类:

类别
定义
典型例子
宏观因子
不可直接交易的宏观变量
通胀、利率、GDP周期、油价冲击
风格因子
由股票特征构建的可交易因子
价值、规模、动量、质量、低波动
统计因子
PCA/ICA 从协方差矩阵中提取
第一主成分、第二主成分

五大经典风格因子速览:

  • • HML(价值):高账面市值比股票 − 低账面市值比股票的多空组合收益
  • • SMB(规模):小市值股票 − 大市值股票的多空组合收益差
  • • MOM(动量):过去 12 个月(跳过最近 1 月)收益最高的股票组合
  • • RMW(盈利):高营业利润率股票 − 低营业利润率股票(FF5 新增)
  • • CMA(投资):低资产增速股票 − 高资产增速股票(FF5 新增)

二、第一步:CAPM 单因子模型

CAPM 是理解因子模型的基石。它假设资产的全部系统性风险可由市场组合的单一 β 来捕捉:

核心含义:

  • • :资产对系统性风险的敏感度
  • • :扣除  敞口后的风险调整超额收益(若市场有效, 统计上应不显著区别于零)
  • • :市场因子对该资产收益的解释程度

Python 实现

import statsmodels.api as smimport pandas as pd# excess: 资产超额收益序列;mkt_rf: 市场风险溢价y = excess['AAPL'].dropna()X = mkt_rf.loc[y.index].rename('Mkt-RF')X = sm.add_constant(X)# Newey-West 稳健标准误(处理异方差与自相关)model = sm.OLS(y, X).fit(    cov_type='HAC',    cov_kwds={'maxlags': 3})alpha = model.params['const']beta  = model.params['Mkt-RF']r2    = model.rsquaredprint(f"α = {alpha:.4f}  β = {beta:.4f}  R² = {r2:.3f}")print(model.summary())

实操提醒: 区分"样本内拟合"与"样本外有效性"——一个高  的模型并不意味着它在未来仍有预测力。


三、第二步:Fama–French 多因子模型

CAPM 被大量实证研究证伪——市值效应和账面市值比效应无法被单一 β 解释。多因子框架的演进历程如下:

CAPM (1964)  └── FF3 因子 (1993):+ SMB + HML        └── Carhart 四因子 (1997):+ MOM              └── FF5 因子 (2015):+ RMW + CMA

Carhart 四因子回归方程:

Python 实现

import pandas_datareader as pdrimport statsmodels.api as sm# 下载 Fama-French 月度因子数据(需翻墙或本地存储)factors = pdr.get_data_famafrench('F-F_Research_Data_Factors', start='2018')[0] / 100# 转为小数mom = pdr.get_data_famafrench('F-F_Momentum_Factor', start='2018')[0] / 100factors['MOM'] = mom['Mom   ']# 运行四因子回归factor_cols = ['Mkt-RF', 'SMB', 'HML', 'MOM']X = sm.add_constant(factors[factor_cols])result = sm.OLS(fund_excess, X).fit(    cov_type='HAC', cov_kwds={'maxlags': 3})print(result.summary())# 提取关键指标exposures = result.params.drop('const')t_stats   = result.tvalues.drop('const')alpha_ann = result.params['const'] * 12# 月度 → 年化

如何解读回归结果:

指标
含义
截距 
风格外超额收益;是否显著区别于零是判断主动能力的关键
系数 
对第  个因子的暴露强度
全部因子对该基金收益的联合解释度
t 统计量
暴露的统计显著性;绝对值 > 2 通常认为显著

四、第三步:风格分析(RBSA)

给投资者一份基金净值序列,不看持仓,能推断出它的风格权重吗?William Sharpe 1992 年提出的 RBSA(Return-Based Style Analysis) 正是为此而生——用带约束的回归,将基金收益"分解"到一组风格指数上。

优化问题的形式:

这两个约束使得权重可被解释为"风格配置比例",截距(残差方差)则捕捉主动管理成分。

Python 实现(scipy 二次规划)

import numpy as npfrom scipy.optimize import minimizedefrbsa(fund_ret, style_ret):"""    fund_ret  : 1D array,基金超额收益序列    style_ret : 2D array (T × K),风格指数收益矩阵    返回: K 维权重向量    """    K = style_ret.shape[1]# 目标:最小化残差平方和defobjective(w):return np.sum((fund_ret - style_ret @ w) ** 2)    constraints = [        {'type': 'eq', 'fun': lambda w: w.sum() - 1},   # 权重和为 1    ]    bounds = [(0, 1)] * K  # 权重非负    w0 = np.ones(K) / K    # 初始等权    res = minimize(objective, w0, bounds=bounds, constraints=constraints,                   method='SLSQP')return res.x# 示例调用style_names = ['Value', 'Growth', 'Small', 'Large', 'Bond']weights = rbsa(fund_excess.values, style_matrix.values)for name, w inzip(style_names, weights):print(f"{name:10s}: {w:.1%}")# 输出示例:# Value     : 32.0%# Growth    : 28.0%# Small     : 15.0%# Large     : 18.0%# Bond      :  7.0%

应用场景:

  • • 识别基金的风格漂移(Style Drift)
  • • 基金尽职调查:宣称"价值风格"但实际暴露在成长因子上
  • • 业绩归因:超额收益来自风格配置还是选股

五、第四步:市值加权的局限与 Smart Beta

标准指数(如沪深300、标普500)采用流通市值加权。这在理论上有 CAPM 支撑,但现实中暴露出两个明显弱点:

缺陷一:高度集中

以标普500为例,前10只股票(约占总数2%)的权重常超过30%,HHI 集中度远高于等权组合。

缺陷二:价格驱动权重

市值 = 价格 × 股数。股价涨越多,权重越高——相当于系统性地"追涨杀跌",潜在动量偏置与估值偏离。

五种加权方式对比

加权方式
HHI 集中度
主要优势
主要劣势
市值加权
高
容量大、成本低、理论自洽
集中于超大盘;价格驱动偏置
等权
低(= 1/n)
分散化充分;历史有规模溢价
换手率高;小盘容量受限
基本面加权
中
反转价格偏差;有价值倾斜
依赖会计数据质量
最小方差
中
真实波动率最低
对协方差估计敏感
风险平价
低
风险贡献均衡;对相关性稳健
需要杠杆才能匹配市场收益

Python 实现:HHI 集中度 + 风险平价

import numpy as npfrom scipy.optimize import minimize# ── HHI(赫芬达尔指数)──────────────────────────────defhhi(weights):"""HHI 越接近 1 越集中,等权时 HHI = 1/n"""return (np.array(weights) ** 2).sum()n = 300# 假设300只成分股cap_w = np.random.dirichlet(np.ones(n) * 0.3)  # 模拟市值分布ew    = np.ones(n) / n                          # 等权print(f"市值加权 HHI : {hhi(cap_w):.4f}")print(f"等权     HHI : {hhi(ew):.4f}  (= 1/n = {1/n:.4f})")# ── 风险平价(Risk Parity)──────────────────────────defrisk_parity(cov):"""使各资产风险贡献相等"""    n = cov.shape[0]defobjective(w):        port_var = w @ cov @ w        rc = w * (cov @ w) / port_var   # 各资产风险贡献比例return np.sum((rc - 1/n) ** 2)  # 目标:风险贡献均等    bounds = [(1e-6, 1)] * n    constraints = {'type': 'eq', 'fun': lambda w: w.sum() - 1}    w0 = np.ones(n) / n    res = minimize(objective, w0, bounds=bounds,                   constraints=constraints, method='SLSQP')return res.x# 使用历史收益率协方差矩阵cov_matrix = returns.cov().values  # (n × n)rp_weights = risk_parity(cov_matrix)print(f"\n风险平价 HHI : {hhi(rp_weights):.4f}")

六、常见坑与实操注意事项

理论转落地,有几处容易踩坑的地方值得特别提醒。

① 样本窗口过短估计因子暴露至少需要 36 个月以上的月度数据,窗口过短会导致 β 估计极不稳健,换手率虚高。滚动回归时窗口长度的选择是稳健性与时效性之间的 trade-off。

② 数据频率与对齐日度与月度混用、节假日缺失处理不当,都会引入幽灵 alpha。务必先统一时间轴,再做回归。

# 正确做法:先对齐,再计算aligned = pd.concat([fund_returns, factor_returns], axis=1).dropna()y = aligned.iloc[:, 0]X = aligned.iloc[:, 1:]

③ 因子共线性SMB 与 HML 历史上的相关系数并不低,小样本下会导致系数剧烈波动。可考虑正交化(Gram-Schmidt)或 Ridge 正则化处理:

from sklearn.linear_model import Ridgeridge = Ridge(alpha=0.01, fit_intercept=True)ridge.fit(X_factors, y_fund)print("Ridge 系数:", ridge.coef_)

④ 忽略容量与成本等权策略在小盘股上的理论溢价,在规模化后往往因市场冲击成本消失殆尽。回测一定要加入合理的交易费率与滑点假设:

# 简单的单边交易成本扣除(假设 bps 为每次换手的单边成本)defnet_return(gross_ret, turnover, bps=10):    cost = turnover * bps / 10000return gross_ret - cost

七、完整知识框架总结

因子投资框架├── 因子识别│   ├── 宏观因子(不可交易)│   ├── 风格因子(可交易多空组合)│   └── 统计因子(PCA 提取)│├── 因子模型│   ├── CAPM(单因子)│   ├── Fama-French 3因子│   ├── Carhart 4因子(+MOM)│   └── FF5(+RMW +CMA)│├── 风格分析(RBSA)│   ├── 带约束回归:w ≥ 0, Σw = 1│   └── 应用:风格漂移检测、业绩归因│└── Smart Beta 构建    ├── 等权(Equal Weight)    ├── 基本面加权(Fundamental Weight)    ├── 最小方差(Minimum Variance)    └── 风险平价(Risk Parity)

八、自学练习建议

  1. 1. 因子暴露估计:下载 Fama–French 月度数据,估计三支公募基金过去 5 年的因子暴露与年化 alpha,对比主动与被动基金的差异。
  2. 2. Smart Beta 对比:用 A 股数据构建等权与市值加权两组组合,对比年化收益、波动率、Sharpe 比率与 HHI 集中度。
  3. 3. RBSA 实战:选取一支宣称"价值风格"的基金,用 RBSA 验证其实际风格暴露是否与宣传一致。
  4. 4. Smart Beta 因子组合:构造"价值 + 质量"的简单多空组合,用四因子模型检验其 alpha 是否显著。

参考文献

  • • Fama, E. F., & French, K. R. (1993). Common risk factors in the returns on stocks and bonds. Journal of Financial Economics.
  • • Carhart, M. M. (1997). On persistence in mutual fund performance. Journal of Finance.
  • • Sharpe, W. F. (1992). Asset allocation: Management style and performance measurement. Journal of Portfolio Management.
  • • Ang, A. (2014). Asset Management: A Systematic Approach to Factor Investing. Oxford University Press.
  • • EDHEC Business School. Advanced Portfolio Construction and Analysis with Python, Coursera, Course 2, Module 1.

最新文章

随机文章