You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R Studio中构建Fama-French模型动量因子的方法咨询

R高效实现Fama-French t-12至t-2动量因子

核心计算口径说明

t期动量因子值为跳过最近1个月(t-1月),回溯t-12至t-2共11个月的累计复合收益率。你的数据中RET.USD为百分比收益率,计算前需除以100转换为小数收益率;如果使用调整后的收益指数RI计算,可直接通过指数比值得到累计收益,无需额外处理收益率。


方案1:data.table原生向量计算(速度最优,推荐大样本使用)

该方法完全基于向量运算,无逐窗口迭代开销,百万级行的面板数据可在毫秒级完成计算,远快于滚动apply类方法。
核心逻辑:区间累计收益 = 区间期末累计净值 / 区间期初前一期累计净值 - 1,不需要逐段连乘收益率。

library(data.table)
setDT(DS.monthly)
# 必须先按股票ID、日期升序排序,是所有时序计算的前提
setorder(DS.monthly, Id, Date)

DS.monthly[, `:=`(
  # 百分比收益率转小数
  RET = RET.USD / 100
), by = Id]

DS.monthly[, `:=`(
  # 累计净值序列
  cum_nav = cumprod(1 + RET),
  # 动量计算:t-2期净值 / t-13期净值 -1,刚好对应t-12到t-2的累计收益
  MOM = shift(cum_nav, n = 2) / shift(cum_nav, n = 13) - 1,
  # 如果直接用RI(收益指数)计算,可跳过cum_nav步骤,结果完全一致
  MOM_RI = shift(RI, n = 2) / shift(RI, n = 13) - 1
), by = Id]

注意:shift函数默认对排序后的数据按行取滞后值,前12个月因窗口不足会自动返回NA,符合因子计算的常规要求。


方案2:tidyverse + slider 滚动窗口实现

如果习惯tidyverse语法,可使用slider包的滚动计算函数,逻辑更直观:

library(dplyr)
library(slider)

DS.monthly <- DS.monthly |>
  arrange(Id, Date) |>
  group_by(Id) |>
  mutate(
    RET = RET.USD / 100,
    MOM = slide_dbl(
      .x = RET,
      .f = ~ prod(1 + .x) - 1, # 窗口内复合收益
      .before = 11, # 包含当前行往前11行
      .after = -2, # 排除当前行、当前行前1行(即t月、t-1月),窗口刚好覆盖t-2到t-12
      .complete = TRUE # 仅窗口满11个观测时计算,不足则返回NA
    )
  ) |>
  ungroup()

此前方案的问题说明

  1. 手动生成t_1到t_12列的实现:每生成一列就要做一次全表分组计算,冗余操作多、效率极低,且排序、列生成步骤多容易引入错位错误。
  2. 之前的slide_dbl建议代码存在两个核心错误:
    • 未将百分比收益率转换为小数,计算结果完全偏离实际值
    • 窗口偏移设置错误,无法准确对齐t-2到t-12的区间,且last(cumprod(1+.x))的写法存在冗余
  3. 最初的全局cumprod代码:是从上市日开始的全周期累计收益,无法截取指定11个月的区间,因此不适用。

注意事项

计算完成后可随机抽取单只股票,截取15-30行的区间,对比不同方法计算的MOM值,排除浮点精度误差后结果应完全一致。如果存在数据缺月,需要先按Id+Date补全连续月度序列再计算,避免行号错位导致结果错误。

内容的提问来源于stack exchange,提问作者Antisa Qipro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:12:24