我的数据包含截至2016年9月的最长165个月的证券的月度回报。我想计算从2003年1月1日到2013年9月30日的每个起点的每个证券的三年期回报,但有些证券来来去去,我担心幸存者的偏见。为了解决这个问题,我需要计算三年的平均年回报率,这将给我一个结果,即使一个证券在给定起点之外的记录少于36个,我也可以使用。当我分离计算单个证券和起点的平均年回报所需的37个记录时,这很简单:
library(dplyr)
df <-
df %>%
arrange(date) %>%
mutate(cumProds = cumprod(1 + return))
avgAnnRet <- with(tail(df,1), cumProds^(12/nrow(df)))
但是对于每个证券,我可以有多达129个起点来计算,而且我有数以千计的证券。我在dplyr组中尝试了各种迭代的rollapply和cumprod,但是我无法让它们中的任何一个工作。是否可以使用单个语句(dplyr或其他)按安全性和开始日期进行分组并进行滚动cumprod计算。当然,在我的实例中,无论是否有37条记录,我都需要它来返回结果。
我写了一个循环,它将执行所需的子集和数学,但它显然非常慢。
答案 0 :(得分:3)
RccpRoll的作者Kevin Ushey非常友好地给我一个解决方法,因为roll_prod不会返回部分窗口的值。它工作得很好,并且在大约200万条记录上非常快:
df %>%
arrange(secId, date) %>%
group_by(secId) %>%
mutate(product = as.numeric(rollapply(1 + return, 37, prod,
partial = TRUE, align = "left")))
答案 1 :(得分:0)
我有类似的问题,部分数据是不可接受的(即如果37个数据点中只有36个可用,那么我希望产品为NA
)。当我使用Tom的rollapply
想法与partial = TRUE
时,我收到了类似
Error in mutate_impl(.data, dots) :
Column `product` must be length 11 (the group size) or one, not 37
原来缺少的是fill = NA
:
df %>%
arrange(secId, date) %>%
group_by(secId) %>%
mutate(product = rollapply(1 + return, 37, prod, fill = NA, partial = FALSE, align = "left"))