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

R语言如何通过for循环按年份计算并存储历史波动率

原代码报错的几个直接原因
  • %>%管道的作用是把前一步的输出传给后一个函数的第一个参数,你直接接for循环根本跑不通,for不是可传参的函数
  • contains()是用来匹配列名的选择器,根本不能用来筛行里的年份值,用法完全错了
  • 循环里你从来没定义过data_hv_i这个对象,直接调用肯定报找不到对象
  • R里取数据框行数的函数是nrow(),没有nrows()这个函数,写了直接报错
  • 你之前手动按行号切年份的方法隐患极大,只要某一年交易日数因为休市、缺数据和你记的259/260对不上,切出来的子集就会串年份,结果全错,最稳妥的方法是直接从日期列提取年份分组。

可行实现方案

前置预处理:统一日期格式

首先把字符串格式的日期转成标准日期类型,从根源避免硬编码行号的问题:

library(dplyr)
library(lubridate) # 处理日期用,没装的话先跑install.packages("lubridate")

# 读入数据
data_hv <- read.csv("your_file_path.csv")
# 你的日期是日/月/年格式,用dmy直接转成标准日期
data_hv$date <- dmy(data_hv$date)
# 新增年份列,后续分组直接用
data_hv$year <- year(data_hv$date)

方案1:for循环实现,结果输出为命名列表

完全符合你要的循环逻辑,最终结果是带年份名的列表,每年对应一个波动率值:

# 自动提取数据里所有存在的年份,不用硬写2000:2022,缺数据的年份不会空跑
year_seq <- sort(unique(data_hv$year))
# 初始化存结果的空列表
hv_list <- list()

for (current_year in year_seq) {
  # 筛选当前年份的子集
  sub_data <- data_hv[data_hv$year == current_year, ]
  # 取价格列,注意这里列名要和你自己数据里的对应,示例数据是prices,你之前写的Wheat要按实际改
  sub_price <- sub_data$prices
  # 计算对数收益率:注意你之前写反了顺序,正确逻辑是当期log减上一期log,虽然标准差对称不影响波动率数值,但逻辑要对
  sub_ret <- log(sub_price) - log(dplyr::lag(sub_price))
  # 按你给的公式算波动率,乘当年实际交易日数的平方根
  current_hv <- sd(sub_ret, na.rm = TRUE) * sqrt(nrow(sub_data)) * 100
  # 结果存入列表,用年份做名字方便后续调用
  hv_list[[as.character(current_year)]] <- current_hv
}

# 打印查看结果
print(hv_list)

方案2:不用写循环的dplyr分组实现

代码更简洁,结果可以直接转成你要的列表格式:

hv_result <- data_hv %>%
  group_by(year) %>%
  summarise(
    trade_days = n(),
    ret_list = list(log(prices) - log(dplyr::lag(prices))),
    annual_hv = sd(unlist(ret_list), na.rm = TRUE) * sqrt(trade_days) * 100
  ) %>%
  select(year, annual_hv)

# 转成和循环方案一样的命名列表
hv_list <- as.list(setNames(hv_result$annual_hv, hv_result$year))

补充提醒:如果你的价格列列名不是示例里的prices,一定要把代码里对应位置改成你自己的列名,不然会报找不到对象的错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:51:19