从CAPM到Barra:多因子模型的演进与基于AmazingData的实战
一、规则选股 vs Alpha因子为什么统计检验如此重要1.1 规则选股的问题传统的规则选股基于主观逻辑设定阈值例如筛选PE小于15的股票。这种方式存在四大缺陷。第一缺乏统计验证未检验该规则与未来收益的相关性是否显著。第二存在幸存者偏差回测时可能只纳入存活至今的股票。第三有过拟合风险阈值可能是数据挖掘的结果。第四参数敏感将15改为16结果可能大相径庭。1.Alpha因子的定义Alpha因子需满足严格的统计标准。第一显著性与未来收益的相关系数IC统计显著t统计量绝对值大于2。第二稳定性IC在不同时间窗口、不同市场中保持稳定。第三可解释性具有清晰的经济学逻辑支撑。第四低相关性与其他已知因子的相关性较低。以下是一个基于AmazingData的单因子IC分析框架import AmazingData as adimport pandas as pdimport numpy as npfrom scipy import stats# 登录AmazingDataad.login(usernameyour_username, passwordyour_password,hostyour_host, portyour_port)# 获取基础数据和市场数据base_data ad.BaseData()market_data ad.MarketData(base_data.get_calendar())# 获取沪深A股代码列表stock_codes base_data.get_code_list(security_typeEXTRA_STOCK_A)# 获取历史K线数据日频kline_dict market_data.query_kline(code_liststock_codes,begin_date20200101,end_date20241231,periodad.constant.Period.day.value)# 构建因子值DataFrame以PE为例info_data ad.InfoData()income_data info_data.get_income(stock_codes)balance_data info_data.get_balance_sheet(stock_codes)# 计算PE因子def calc_pe_factor(income_dict, base_data_obj):计算PE因子市盈率使用PIT原则确保使用当时可获取的财务数据pe_factors {}for code in income_dict.keys():df income_dict[code]if df is None or len(df) 0:continue# 获取净利润使用TTM或最新报告期net_profit df[NETPROINCLMIN_INT_INC].astype(float)# 获取对应日期的市值数据从K线计算if code in kline_dict:kline kline_dict[code]# 计算总市值 收盘价 * 总股本# 这里简化处理实际需从股本结构数据获取market_cap kline[close] * 1e8 # 假设股本数据# 计算PEpe market_cap / net_profit.iloc[-1] if net_profit.iloc[-1] ! 0 else np.nanpe_factors[code] pereturn pd.Series(pe_factors)# 单因子IC分析def factor_ic_analysis(factor_series, forward_return, methodspearman):因子IC分析factor_series: 因子值Series (index为股票代码)forward_return: 未来一期收益Series# 对齐数据merged pd.concat([factor_series, forward_return], axis1)merged.columns [factor, return]merged merged.dropna()if len(merged) 30: # 最小样本量return Noneif method spearman:ic, pvalue stats.spearmanr(merged[factor], merged[return])else:ic, pvalue stats.pearsonr(merged[factor], merged[return])results {IC: ic,pvalue: pvalue,sample_size: len(merged)}return results# 计算未来一期收益简化示例def calc_forward_return(kline_dict, period5):计算未来N期收益forward_returns {}for code, kline in kline_dict.items():if len(kline) period 1:continuefuture_return (kline[close].shift(-period) / kline[close] - 1).iloc[-period-1]forward_returns[code] future_returnreturn pd.Series(forward_returns)二、风格因子 vs Alpha因子风险与收益的分工1.核心区别风格因子和Alpha因子在五个维度上存在本质区别。经济含义方面风格因子解释市场风险的系统性来源Alpha因子获取超额收益的非系统性来源。典型代表方面风格因子包括市值、估值、动量和波动率Alpha因子包括质量、分析师预期和事件驱动。收益特征方面风格因子波动大、长期超额不稳定可能数年失效Alpha因子追求稳定、持续的超额收益。组合作用方面风格因子用于风险暴露管理和业绩归因基准Alpha因子用于收益增强和分散化叠加。风险属性方面风格因子承担系统性风险有BetaAlpha因子追求与市场低相关的Alpha。2.基于AmazingData的风格因子计算from AmazingData.operator.time_series_function import TimeSeriesFunctionfrom AmazingData.operator.math_function import MathFunctiondef calc_style_factors(kline_dict, info_data):基于AmazingData计算经典风格因子style_factors {}for code, kline in kline_dict.items():if len(kline) 252: # 至少一年数据continuefactors {}# 市值因子Size使用收盘价作为代理实际应从股本结构获取factors[size] np.log(kline[close].iloc[-1])# 估值因子ValuePB 市值 / 净资产# 实际应从财务数据获取净资产factors[value] 1 / kline[close].iloc[-1] # 简化代理# 动量因子Momentum过去252日收益factors[momentum] (kline[close].iloc[-1] / kline[close].iloc[-252] - 1)# 波动率因子Volatility过去20日收益标准差returns kline[close].pct_change().dropna()factors[volatility] TimeSeriesFunction.STD(returns, 20).iloc[-1]style_factors[code] factorsreturn pd.DataFrame(style_factors).T# 使用截面函数进行因子标准化from AmazingData.operator.cross_section_function import CrossSectionFunctiondef normalize_factors(factor_df):截面Z-score标准化return CrossSectionFunction.CSZSCORE(factor_df)三、多因子模型的演进史1.CAPM1964单因子时代CAPM模型的公式为期望收益等于无风险利率加上Beta乘以市场风险溢价。其核心假设是投资者只关心系统性风险唯一的因子是市场风险Market Beta。其局限性在于无法解释市场异象如小市值效应和价值效应。2.Fama-French三因子1993三因子模型在CAPM基础上新增了两个因子。SMBSmall Minus Big是市值因子代表小市值股票溢价。HMLHigh Minus Low是价值因子代表高账面市值比溢价。三因子模型的解释力从CAPM的约70%提升至约90%。3.Fama-French五因子2015五因子模型在三因子基础上又新增了两个因子。RMWRobust Minus Weak是盈利因子代表高盈利公司溢价。CMAConservative Minus Aggressive是投资因子代表低投资公司溢价。五因子模型的核心发现是盈利能力和投资风格是独立的定价因子。4.Barra风险模型工业标准MSCI Barra模型是当前业界最广泛使用的风险模型。以Barra USE4模型为例一级因子共13个包括10个风格因子和按GICS分类的行业因子。风格因子包括Beta、动量、规模、盈利、波动率、成长性、价值、杠杆率、流动性和非线性市值。Barra模型的核心应用包括四个方面。第一是风险分解分析组合风险来源于哪些因子暴露。第二是业绩归因比较实际收益与因子预期收益。第三是组合优化在风险约束下最大化预期收益。第四是压力测试进行因子冲击情景分析。以下是一个基于AmazingData的Barra协方差矩阵结构示意import numpy as npdef barra_covariance(factor_exposures, factor_cov, specific_var):Barra协方差矩阵系统性风险 特质风险V X * F * X^T DX: 因子暴露矩阵 (N×K)F: 因子协方差矩阵 (K×K)D: 特质方差对角矩阵 (N×N)systematic_risk factor_exposures factor_cov factor_exposures.Tspecific_risk np.diag(specific_var)total_cov systematic_risk specific_riskreturn total_cov# 基于AmazingData计算因子暴露def calc_factor_exposure(stock_returns, factor_returns):计算个股对因子的暴露Beta使用AmazingData的统计函数from AmazingData.operator.math_function import StatisticsFunction# 计算每个股票对每个因子的Betabetas {}for code in stock_returns.columns:stock_ret stock_returns[code]factor_betas {}for factor_name in factor_returns.columns:factor_ret factor_returns[factor_name]# 使用BETA函数计算beta StatisticsFunction.BETA(stock_ret, factor_ret, 252)factor_betas[factor_name] beta.iloc[-1] if hasattr(beta, iloc) else betabetas[code] factor_betasreturn pd.DataFrame(betas).T四、模型演进的核心逻辑从CAPM到Barra多因子模型的演进遵循统一逻辑每增加一个解释变量残差特质收益就降低定价准确性提高从而更精准识别真实Alpha。关键洞察在于残差项代表模型无法解释的部分。残差越小说明因子对收益的解释力越强。真正的Alpha存在于残差中即因子模型无法解释的稳定超额收益。五、实战建议因子投资的实战建议有五条。第一因子挖掘应从经典文献出发而非数据挖掘。第二正交化处理需剔除已知风格因子的影响寻找纯Alpha。第三样本外验证要区分训练集、验证集和测试集防止过拟合。第四每个因子必须有清晰的经济学解释。第五因子会衰减、会拥挤需定期评估有效性。