R语言使用For循环计算月度股票收益率的实现问题
计算股票月度复利收益率的实现方案
你当前持有的日度收益率为「公司为行、日期为列」的宽表格式,更简便的实现方式是先转换为长表按公司+年月分组计算复利,效率比手写循环更高也更易维护。
完整实现代码(基于tidyverse生态)
需要提前加载dplyr、tidyr、lubridate三个工具包,计算逻辑和你原有单月计算逻辑完全一致:
# 加载依赖包 library(dplyr) library(tidyr) library(lubridate) # 批量计算全周期月度收益率 monthly_return <- R2 %>% # 将行名转换为公司名字段,避免后续计算丢失公司标识 rownames_to_column("company") %>% # 宽表转长表,所有日期列转换为「日期-收益率值」的行结构 pivot_longer(cols = -company, names_to = "date") %>% # 转换日期格式,生成标准月份标识 mutate( date = as.Date(date), year_month = format(date, "%Y-%m") ) %>% # 按公司+月份分组 group_by(company, year_month) %>% # 计算月度复利乘积,na.rm设为FALSE保证整月无数据的公司结果仍为NA,和你原有逻辑一致 summarise(monthly_return = prod(value, na.rm = FALSE)) %>% # 如果需要转回你原有「公司为行、月份为列」的宽表格式,保留下面这行即可 pivot_wider(names_from = year_month, values_from = monthly_return)
该方案会自动覆盖数据中所有存在的月份,不需要硬编码1996-2020的时间范围,也不会出现循环匹配的错位问题。
循环方案的修正版
如果你坚持使用循环实现,原有代码的问题在于没有将i、j的变量值拼接为正确的月份字符串,也没有补全月份的前导0(比如1月需要匹配1996-01而非1996-1),修正后代码如下:
# 初始化结果表 R3 <- data.frame(company = rownames(R2)) rownames(R3) <- R3$company for(i in 1996:2020) { for(j in 1:12) { # 生成标准月份字符串,补全月份前导0 month_str <- paste0(i, "-", sprintf("%02d", j)) # 匹配当前月份的所有日度数据列 month_cols <- grep(month_str, colnames(R2), value = TRUE) # 跳过无数据的月份 if(length(month_cols) == 0) next # 计算月度收益率并存入对应列 R3[[month_str]] <- apply(R2[, month_cols], 1, prod, na.rm = FALSE) } } # 去掉多余的公司名字段,和你原有格式保持一致 R3 <- R3[, -1]
内容的提问来源于stack exchange,提问作者Apl4n1
相关产品推荐
相关产品推荐

