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

如何在R中计算各ID事件日前后5天的Buy and Hold收益率?

R中事件窗口买入持有收益率计算完整方案

需求说明

  • 按ID分组,以EventDate为基准,计算事件日前5天至后5天共11个交易日的买入持有收益率
  • 收益率公式:(当日Price ÷ 事件日前6天的Price) - 1
  • 为原数据表新增BuyHoldReturn列,仅事件窗口内的日期计算收益率,其余日期设为NA

原数据示例

# 示例数据结构
data <- tibble(
  ID = c(1, 1, 1, 2),
  Date = as.Date(c("2011-03-06", "2011-03-07", "2011-03-12", "2011-06-19")),
  Price = c(10, 9, 12, 67),
  EventDate = c(NA, NA, as.Date("2011-03-12"), as.Date("2011-06-19"))
)

预期结果示例

IDDatePriceEventDateBuyHoldReturn
12011-03-079NA-0.1
12011-03-12122011-03-120.2
22011-06-1457NA0.14

完整解决方案代码

library(dplyr)

# 转换日期格式(确保Date和EventDate为标准日期类型)
data$Date <- as.Date(data$Date)
data$EventDate <- as.Date(data$EventDate)

# 分组计算收益率
data_processed <- data %>%
  # 按ID和日期排序,保证交易日顺序正确
  arrange(ID, Date) %>%
  group_by(ID) %>%
  # 提取当前ID的事件日(假设每个ID仅有1个非NA的EventDate)
  mutate(event_day = first(EventDate[!is.na(EventDate)])) %>%
  # 定位事件日在当前分组中的行索引
  mutate(event_row = which(Date == event_day)) %>%
  # 获取事件日前6个交易日的基准价格(索引越界时设为NA)
  mutate(base_price = ifelse(event_row - 6 >= 1, Price[event_row - 6], NA)) %>%
  # 标记是否在事件窗口内(前5天至后5天)
  mutate(in_window = between(Date, event_day - 5, event_day + 5)) %>%
  # 计算买入持有收益率,仅窗口内日期计算,其余为NA
  mutate(BuyHoldReturn = ifelse(in_window, (Price / base_price) - 1, NA)) %>%
  # 移除辅助计算列
  select(-event_day, -event_row, -in_window) %>%
  ungroup()

关键说明

  1. 排序要求:必须先按ID和Date排序,保证交易日顺序正确,否则基准价格和窗口判断会出错
  2. 多事件日处理:如果一个ID对应多个EventDate,需将group_by(ID)改为group_by(ID, EventDate),并调整事件窗口逻辑
  3. 边界情况处理:若事件日前6天无交易日(如新股上市),base_price会返回NA,对应的收益率也为NA,可根据需求补充默认值或过滤逻辑
  4. 非交易日过滤:若原数据包含非交易日,需先通过filter()过滤,确保仅保留交易日数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:48:27