在R中按ID计算事件日前后(-5~+5)的Buy and Hold收益
R中按ID计算事件日前后11天的买入持有收益解决方案
需求说明
针对每个ID,以EventDate为基准,计算事件日前5天到后5天(共11天)的买入持有收益(Buy and Hold return),计算逻辑为:当日Price ÷ 事件日前6天的Price - 1,非该时间范围内的记录收益值设为NA。
解决方案代码
library(dplyr) library(lubridate) # 确保日期列是日期格式(若原始数据未转换) data$Date <- as.Date(data$Date) data$EventDate <- as.Date(data$EventDate) # 分组计算收益 data <- data %>% group_by(ID) %>% # 提取每个ID对应的基准价:EventDate前6天的Price mutate(base_price = Price[Date == EventDate - days(6)]) %>% # 仅在事件日前后5天范围内计算收益,其余设为NA mutate(BuyHoldReturn = if_else( Date >= EventDate - days(5) & Date <= EventDate + days(5), (Price / base_price) - 1, NA_real_ )) %>% ungroup()
关键说明
- 若某ID的
EventDate前6天无对应Price记录,base_price会返回NA,对应的收益值也会是NA,可根据业务需求添加过滤或填充逻辑(比如filter(!is.na(base_price))) - 若日期数据是连续的日度数据,也可以不用
lubridate,直接用EventDate - 6做日期减法(前提是日期列已转换为Date类型) - 代码中用
if_else替代ifelse,是因为if_else在dplyr分组操作中类型一致性更好,避免隐式类型转换问题
示例验证
示例输入(简化版)
| ID | Date | EventDate | Price |
|---|---|---|---|
| 1 | 2023-01-01 | 2023-01-07 | 100 |
| 1 | 2023-01-02 | 2023-01-07 | 102 |
| 1 | 2023-01-03 | 2023-01-07 | 101 |
| 1 | 2023-01-07 | 2023-01-07 | 105 |
| 1 | 2023-01-12 | 2023-01-07 | 108 |
示例输出(简化版)
| ID | Date | EventDate | Price | BuyHoldReturn |
|---|---|---|---|---|
| 1 | 2023-01-01 | 2023-01-07 | 100 | NA |
| 1 | 2023-01-02 | 2023-01-07 | 102 | 0.02 |
| 1 | 2023-01-03 | 2023-01-07 | 101 | 0.01 |
| 1 | 2023-01-07 | 2023-01-07 | 105 | 0.05 |
| 1 | 2023-01-12 | 2023-01-07 | 108 | 0.08 |
内容的提问来源于stack exchange,提问作者catin
相关产品推荐
相关产品推荐

