2017-02-28 81 views
1

我的数据包含2016年9月结束的最多165个月的证券月报表。我想从2003年1月1日至9月的每个起点计算每个证券的三年期收益。 30 2013年,但一些证券来来去去,我担心幸存者的偏见。为了解决这个问题,我需要计算三年的平均年回报率,即使安全性超出给定起点的36条记录,我也可以使用这个结果。这很简单,当我分离了37条记录来计算一个单一的安全和出发点的平均年回报率要求:R rolling cumprod

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或其他)按安全性和开始日期进行分组,并执行滚动式生产计算。在我的例子当然,我会需要它返回结果是否有37个或更少的记录。

我写了一个循环来完成所需的子集和数学运算,但它显然非常慢。

+1

有包RcppRoll和滚动那些已经在做这些事情。 –

+0

RollingWindow包中的函数RollingCompound以非常直接和高效的方式满足您的要求。 – hvollmeier

+0

RcppRoll的roll_prod几乎可以完美工作,但对于记录数少于窗口大小的分组,它会返回NA。文档列出了我猜测会处理这些问题的“部分”论据,但目前尚未实现。 – Tom

回答

2

Kevin Ushey,RccpRoll的作者,给了我一个解决方法,因为roll_prod不会返回部分窗口的值。它的工作完美,是真快上约2万条记录:

df %>% 
arrange(secId, date) %>% 
group_by(secId) %>% 
mutate(product = as.numeric(rollapply(1 + return, 37, prod, 
    partial = TRUE, align = "left"))) 
0

我也有类似的问题,即部分数据是不能接受的(例如,如果只有37个数据点的36个可用的话,我想要的产品是NA)。当我用汤姆的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")) 
相关问题