当前位置: 首页 > news >正文

保姆级教程:用Python和baostock复现Fama-French三因子模型,手把手教你分析A股

用Python实战Fama-French三因子模型:从理论到A股分析全流程解析

在量化投资领域,Fama-French三因子模型犹如一盏明灯,为理解股票收益提供了清晰的框架。不同于传统CAPM模型的单一市场视角,这一诺奖级理论通过引入市值和账面市值比因子,显著提升了解释力。本文将带您用Python和baostock数据,完整走通从数据获取到模型应用的闭环,特别针对A股市场特性进行适配优化。

1. 环境准备与数据源配置

工欲善其事,必先利其器。复现经典模型首先需要搭建稳定的工具链:

# 核心工具栈安装 !pip install baostock statsmodels pandas numpy matplotlib seaborn --upgrade

关键数据源选择依据

  • baostock:提供稳定免费的A股历史行情,相比其他接口更适配本土市场
  • 央财因子数据:国内权威计算的因子数据,避免自行构建的计算偏差
  • 数据周期:建议选择3-5年窗口期,既能捕捉市场特征又避免过度拟合

注意:baostock需注册获取token,每日调用限额5000次,批量处理时建议添加延时

2. 因子数据深度处理

原始数据往往需要清洗才能用于建模。央财提供的五因子数据包含我们需要的三大核心因子:

字段名含义计算方式单位
mkt_rf市场风险溢价市场组合收益 - 无风险利率%
smb市值因子小市值组合 - 大市值组合收益%
hml账面市值比因子高BM组合 - 低BM组合收益%
# 数据加载与预处理示例 factors = pd.read_csv('fivefactor_daily.csv', index_col='trddy', parse_dates=['trddy'], usecols=['trddy','mkt_rf','smb','hml','rf']) # 处理异常值 factors = factors[(factors.abs() < 3).all(axis=1)] # 剔除3σ以外的极端值 factors = factors.asfreq('D').fillna(method='ffill') # 交易日对齐

3. 个股数据处理技巧

以中国平安(601318.SH)为例,需特别注意A股特有的数据处理要点:

复权处理关键参数

  • adjustflag=1:前复权
  • adjustflag=2:后复权
  • adjustflag=3:不复权(推荐用于学术研究)
# baostock数据获取最佳实践 def get_stock_data(code, start, end): bs.login() rs = bs.query_history_k_data_plus( code, fields="date,close,volume", start_date=start, end_date=end, frequency="d", adjustflag="3" # 保持原始价格 ) df = rs.get_data().set_index('date') df.index = pd.to_datetime(df.index) bs.logout() return df.astype(float) zgpa = get_stock_data('sh.601318', '2020-01-01', '2023-06-30')

4. 收益率计算与特征工程

对数收益率在金融建模中具有数学优势:

# 收益率计算对比 price = zgpa['close'] simple_ret = price.pct_change() # 简单收益率 log_ret = np.log(price/price.shift(1)) # 对数收益率 # 可视化对比 plt.figure(figsize=(10,4)) plt.plot(simple_ret.cumsum(), label='简单收益率') plt.plot(log_ret.cumsum(), label='对数收益率') plt.legend(); plt.title('收益率计算方式对比')

关键发现

  • 短期来看两种计算方法差异不大
  • 长期累计时对数收益率更稳定
  • 多因子模型通常采用对数收益率

5. 模型构建与结果解读

使用statsmodels进行回归分析时,需要特别关注金融数据的特性:

# 合并数据集 data = pd.merge(factors, log_ret.to_frame('return'), left_index=True, right_index=True) data['excess_return'] = data['return'] - data['rf'] # 计算超额收益 # 三因子模型回归 model = sm.OLS( data['excess_return'], sm.add_constant(data[['mkt_rf', 'smb', 'hml']]) ) results = model.fit(cov_type='HAC', cov_kwds={'maxlags': 5}) # 考虑自相关

回归结果关键指标解读

系数经济含义中国平安(2020-2023)统计显著性
constα(超额收益)-0.0002p=0.12
mkt_rf市场风险暴露0.92***p<0.001
smb小市值风险暴露-0.31**p=0.03
hml价值股风险暴露0.45***p<0.001

*** p<0.01, ** p<0.05:中国平安呈现显著的价值股特征,对市值因子呈负暴露

6. 多股票对比分析

建立自动化分析流程可提升研究效率:

def analyze_stock(code, start, end): # 获取数据 stock_data = get_stock_data(code, start, end) log_ret = np.log(stock_data['close']/stock_data['close'].shift(1)) # 合并因子 merged = pd.merge(factors, log_ret.to_frame('return'), left_index=True, right_index=True) merged = merged.dropna() # 模型回归 model = sm.OLS( merged['return'] - merged['rf'], sm.add_constant(merged[['mkt_rf','smb','hml']]) ) results = model.fit() return pd.Series({ 'alpha': results.params['const'], 'beta': results.params['mkt_rf'], 'smb_beta': results.params['smb'], 'hml_beta': results.params['hml'], 'rsquared': results.rsquared }) # 示例:对比不同行业股票 stocks = { '消费':'sh.600519', # 茅台 '金融':'sh.601318', # 平安 '科技':'sh.600588', # 用友 '医药':'sh.600276', # 恒瑞 } results = pd.DataFrame({name: analyze_stock(code, '2020-01-01','2023-06-30') for name, code in stocks.items()})

行业对比发现

  • 消费股呈现低市场风险暴露(β≈0.8)
  • 科技股具有显著的小市值特征(SMBβ>0)
  • 金融股普遍呈现价值股特性(HMLβ>0.4)

7. 策略回测与绩效评估

完整的量化研究需要验证模型的实际效果:

# 回测框架关键指标计算 def backtest(returns, factors, window=252): """ params: returns: 个股收益率序列 factors: 因子数据 window: 滚动窗口长度 """ results = [] for i in range(window, len(returns)): # 滚动回归 train_data = pd.merge( returns.iloc[i-window:i], factors.iloc[i-window:i], left_index=True, right_index=True ) model = sm.OLS( train_data.iloc[:,0] - train_data['rf'], sm.add_constant(train_data[['mkt_rf','smb','hml']]) ) res = model.fit() # 预测下一期 current_factors = factors.iloc[i] pred = res.predict([1, current_factors['mkt_rf'], current_factors['smb'], current_factors['hml']]) results.append(pred[0] + current_factors['rf']) # 转回总收益 return pd.Series(results, index=returns.index[window:]) # 执行回测 pred_ret = backtest(log_ret, factors) actual_ret = log_ret[pred_ret.index] # 计算IC信息系数 ic = pred_ret.corr(actual_ret) print(f'信息系数(IC): {ic:.2%}')

绩效评估矩阵

指标计算公式中国平安行业平均
年化收益率(1+总收益)^(252/天数)-18.2%6.5%
最大回撤最大峰值到谷值跌幅-23.4%-28.1%
夏普比率年化收益/年化波动0.820.65
预测IC预测与实际收益相关系数0.150.08

8. 常见问题与解决方案

Q1:因子数据频率如何选择?

  • 日频数据噪声较大但样本充足
  • 月频数据更稳定但可能丢失短期特征
  • 推荐做法:先用月频验证理论,再用日频优化

Q2:如何处理缺失数据?

# 缺失数据处理方案 factors = factors.fillna(method='ffill') # 前向填充 factors = factors.dropna() # 或直接删除 # 交易日对齐技巧 factors = factors.reindex(pd.date_range(start, end, freq='D'))

Q3:回归结果不显著怎么办?

  • 检查因子共线性:factors[['mkt_rf','smb','hml']].corr()
  • 尝试扩展时间窗口
  • 考虑加入行业虚拟变量

在实战中,我发现A股市场的市值效应呈现明显的阶段性特征。2015年前小盘股超额收益显著,但近年来随着注册制改革,这种效应正在减弱。建议每半年重新检验一次因子有效性,动态调整模型参数。

http://www.jsqmd.com/news/780823/

相关文章:

  • 量子优化算法在工程仿真中的实践与性能提升
  • FPGA实战:手把手教你用OV7725摄像头采集RGB565图像(附Verilog代码)
  • 从‘虚轴’到‘实轴’:倍福NC过程映像如何成为控制层与物理层的翻译官?
  • Bookmark Ninja:将浏览器书签转为AI可读JSON索引的本地工具
  • 交互式媒体回放引擎:从状态快照到精准复现的架构实践
  • 告别混乱布局!用eGUI的Panel在Rust里快速搭建桌面应用主界面
  • ARM SME指令集:矩阵运算优化与数据加载技术详解
  • 基于Vue3+TypeScript的ChatGPT风格对话应用前端架构与实现
  • 端到端课程自用 6 规划 端到端的模型训练范式 AI 笔记
  • Infio-Copilot:让AI成为你的Obsidian知识管理副驾驶
  • Vue3项目实战:用vuedraggable-next搞定拖拽列表,附带动画过渡与常见报错解决
  • 强化学习结合连续思维链提升大模型推理能力
  • Unity性能优化实战:用Magica Cloth的Virtual Deformer把高模裙子顶点数砍掉80%
  • 基于Agentic Template的智能体应用开发脚手架:从架构设计到生产部署
  • 矩阵乘法加速:协同设计突破带宽墙
  • 基于Obsidian CLI与OpenClaw实现每日笔记自动化归档与链接维护
  • ARM SME指令集:LD1W与LDNT1B深度解析与优化实践
  • 开源大模型部署利器Bedrock:统一API编排与生产级实践指南
  • 别再死记公式了!用Python+LTspice仿真,5分钟搞懂采样保持电路的KT/C噪声到底怎么算
  • 开源技能库OpenClaw:结构化管理与复用开发技巧的工程实践
  • 基于多智能体架构的AI模拟法庭系统:律师案件预演的革命性工具
  • SafeLink:基于智能合约与ERC-8004的AI Agent去信任协作协议
  • 保姆级教程:用R语言从FinnGen数据库下载并整理GWAS数据(附完整代码)
  • Canvas动画光标库ani-cursor.js:原理、实现与性能优化
  • Python后端Flask如何实现短信验证码发送_调用云厂商API实现功能
  • XAP SDK:构建AI智能体间可信经济协作的结算协议与Python实践
  • 从微波炉到飞机:聊聊那些“说明书”里没写的安全边界,以适航管理为例
  • 本地部署大语言模型聊天应用:从原理到实战的完整指南
  • LLM维基百科插件:实时知识检索增强大语言模型应用
  • 智能体协作框架SkillOrchestra:动态技能转移与高效路由分配