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

使用rollapply计算月度Beta的回归问题求助(含样本数据)

解决滚动月度Beta计算的问题:错误排查与完整方案

先帮你拆解原来代码里的几个核心问题,再给你一套完全匹配需求的解决方案:

原来代码的错误点

  1. 固定天数窗口不符合需求:你用width=252是固定交易日数,但需求是「t-11至t月的日度数据」,应该按12个月的滚动时间窗口计算,而非固定天数(不同月份/年份的交易日数差异很大)。
  2. by.column=TRUE的逻辑错误:这个参数会把每一列单独传入FUN,导致你在函数里拿不到mktrf列,根本无法完成回归。
  3. 公式写法错误:paste0(" ", x , " ~ mktrf")里的x是整个窗口的数据集,不是股票列名,完全无法生成有效回归公式。
  4. 缺失值处理错误:lm函数不支持na.rm=T参数,应该用na.action=na.omit来剔除缺失的观测对;同时你没处理退市股票的全NA情况。
  5. 缺少观测数校验:没有判断回归的有效观测数是否≥150。

完整解决方案

我用dplyr+zoo+lubridate来实现,完全贴合你的需求:

1. 加载依赖包

library(zoo)
library(dplyr)
library(lubridate)

2. 数据预处理(添加年月标识)

先给数据加一个「年月」列,方便后续按月份做滚动窗口:

joined_data <- joined_data %>%
  mutate(year_month = floor_date(date, "month"))  # 把日期转换为当月第一天,用于分组

3. 定义Beta计算工具函数

这个函数负责单只股票的Beta计算,同时校验有效观测数:

calc_single_beta <- function(stock_returns, market_returns) {
  # 剔除股票收益和市场收益同时缺失的观测
  valid_pairs <- na.omit(data.frame(stock = stock_returns, mktrf = market_returns))
  
  # 检查有效观测数是否达标
  if(nrow(valid_pairs) < 150) {
    return(NA)  # 不足150个观测返回NA
  }
  
  # 执行回归,提取mktrf的系数(即Beta)
  beta_model <- lm(stock ~ mktrf, data = valid_pairs)
  return(coef(beta_model)[["mktrf"]])
}

4. 定义滚动窗口处理函数

这个函数负责处理每个12个月的滚动窗口,计算所有股票的Beta:

calc_window_betas <- function(window_data) {
  # 提取所有股票列(排除date、year_month、mktrf)
  stock_columns <- setdiff(colnames(window_data), c("date", "year_month", "mktrf"))
  
  # 遍历所有股票列,计算Beta
  beta_results <- sapply(stock_columns, function(col) {
    calc_single_beta(window_data[[col]], window_data[["mktrf"]])
  })
  
  # 返回窗口对应的月份+所有股票的Beta
  return(data.frame(
    year_month = last(window_data$year_month),  # 窗口对应的目标月份(最后一个月)
    t(beta_results),
    stringsAsFactors = FALSE
  ))
}

5. 执行滚动计算并整理输出

# 把数据转换为按年月索引的时间序列对象
ts_data <- read.zoo(joined_data, index = "year_month", split = NULL)

# 执行12个月的滚动计算:align="right"表示窗口结束于当前月份
rolling_beta_results <- rollapply(
  data = ts_data,
  width = 12,
  FUN = calc_window_betas,
  by = 1,
  align = "right",
  by.column = FALSE,  # 必须设为FALSE,才能传入整个窗口的所有列
  fill = NA
)

# 转换为标准数据框,调整格式和输入一致
final_betas <- do.call(rbind, rolling_beta_results) %>%
  # 如果需要对应月末日期,把下面的date行换成:date = ceiling_date(year_month, "month") - days(1)
  mutate(date = as.Date(year_month)) %>%
  select(date, all_of(stock_columns))  # 保持股票列的顺序和输入一致

关键特性说明

  • 精准匹配月度滚动需求:用12个月的时间窗口替代固定天数,完全符合「t月Beta用t-11至t月数据」的要求。
  • 观测数校验:自动检查有效观测数≥150,不足则返回NA。
  • 缺失值处理:自动剔除回归中的缺失观测对,退市股票的全NA情况会返回NA,保持输出格式和输入一致。
  • 输出格式对齐:最终输出的列名、结构和输入表格完全匹配,方便后续分析。

你的样本数据只有10天(不到1个月),运行后会返回全NA,但逻辑完全正确,替换成真实的长周期数据就能得到正常结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:15:17