R滚动cumprod

时间:2017-02-28 14:45:21

标签: r dplyr

我的数据包含截至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条记录,我都需要它来返回结果。

我写了一个循环,它将执行所需的子集和数学,但它显然非常慢。

2 个答案:

答案 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"))