R编程使用数据表计算累积返回周期

时间:2016-04-22 13:21:30

标签: r data.table

我想请求一些关于如何创建库存数据累积回报的新列的帮助。我的数据结构如下:

Month      Stock    Ret

Jan-2001    A       0.01    
Feb-2001    B       0.02    
Jan-2002    B       0.01    
Feb-2002    B       0.03

数据为期10年。我想计算每个股票的12个月增量的累计回报。

例如,第一个回归期将涵盖2001年1月至2001年12月。第二阶段将是从2001年2月到 2002年1月等等。

这些计算将按库存完成,并将使用每个期间计算的非累积回报。由于我有很多年的股票,我想看看是否有更有效的方法来进行这些计算而不是for循环。

我一直在寻找尝试使用data.table包的方法,但我不确定如何做到这一点。

编辑:

也许我的循环功能可以更好地解释我想要实现的目标。

my.data <- data.frame(Date = seq.Date(as.Date('2001-01-01'), by ='month', length = 24), stock = factor(c(rep('A', 2*12), rep('B', 2*12))), Ret = c(rep(c(.02,.01,0,.03,.02,.01,02,.01,0,.03,.02,.01), 2)))  

final_table <- list()
num_periods <- 2*12-12


for(i in unique(my.data$stock)){

  ts_i = ts(my.data[my.data$stock==i, 'Ret'])

  table_i = matrix(nrow=length(ts_i), ncol=15)

  num_periods = length(ts_i)-12

  table_i[,1] = ts_i

  table_i[,14] = i

  table_i[,15] = ts(my.data[my.data$stock==i,'Date'])

  for(j in 1:num_periods){
     myperiod = cumprod(ts_i[j:(j+11)]+1)-1
     table_i[12+j,2:13] = myperiod
  }
 colnames(table_i) = c('original', paste0('p',-12:-2),'p1','stock','Date')
 final_table[[i]] = table_i
}

new.my.data = do.call('rbind',final_table)

new.my.data = na.omit(new.my.data)

2 个答案:

答案 0 :(得分:0)

如果我理解正确,你需要每年的个股总和。首先,我将从您的数据中提取数年

df <- cbind(do.call('rbind',strsplit(df$Month,"-")),df[,c(2,3)])
names(df)[c(1,2)] <- c("Month","Year")

然后按年份和库存汇总数据

aggregate(df[,"Ret"],by=list("Year" = df$Year,"Stock"=df$Stock),FUN=sum)

以此格式生成df

  Year Stock    x
1 2001     A 0.04
2 2002     B 0.04
3 2003     B 0.02

并且可视化它应该不是问题。

编辑:

这个怎么样?

aggregate(df[,"Ret"],by=list("Year" = df$Year,"Stock"=df$stock),FUN= function(x) {return (cumprod (x+1)-1)} )

应该产生这样的东西:

  Year Stock        x.1        x.2        x.3        x.4        x.5       x.6         x.7        x.8        x.9       x.10       x.11       x.12
1 2001     A 0.02000000 0.03020000 0.03020000 0.06110600 0.08232812 0.09315140 2.27945420 2.31224875 2.31224875 2.41161621 2.47984853 2.51464702
2 2002     A 0.02000000 0.03020000 0.03020000 0.06110600 0.08232812 0.09315140 2.27945420 2.31224875 2.31224875 2.41161621 2.47984853 2.51464702
3 2001     B 0.02000000 0.03020000 0.03020000 0.06110600 0.08232812 0.09315140 2.27945420 2.31224875 2.31224875 2.41161621 2.47984853 2.51464702
4 2002     B 0.02000000 0.03020000 0.03020000 0.06110600 0.08232812 0.09315140 2.27945420 2.31224875 2.31224875 2.41161621 2.47984853 2.51464702

这是每年报告的,但我认为您可以操作和分类月/年,以便它很容易满足您的要求。

答案 1 :(得分:0)

我认为 cumprod 函数可以进行您想要的计算:

taxes <- c(0.2, 0.4, 0.3)
cum_taxes = cumprod(taxes + 1) - 1

因此,问题的关键部分是将您的数据分成所需的块,即不同的年份。 split 函数是一个不错的选择: (让我将字符串日期值转换为 Date 类型并在拆分之前对它们进行排序...)

df <- tibble(a = c('1991-10-01', '1991-11-01', '1991-12-01', '1992-01-01','1992-02-01'), 
              b = c(0.5, 0.6, 0.8, 1.2, 1.4))
df <- df %>% 
  mutate(
    a = as.Date(a),
    y = year(a)
  ) %>% 
  arrange(
    a
  )

split_df <- split(df, df$y)

现在,我们可以为每个数据子集应用 cumprod。 由于 split_df 是一个列表,我们希望为每个列表元素执行此操作(与上述相同)。

split_df[[1]]$cum_taxes = cumprod(split_df[[1]]$b + 1) - 1

split_df[[2]]$cum_taxes = cumprod(split_df[[2]]$b + 1) - 1

但这不是重复的好解决方案,而是让我们使用 tidyverse mapmap2 函数来完成这项工作:

cum_taxes <- map(split_df, ~(cumprod(.x$b + 1) - 1))
merged_df <- map2(split_df, cum_taxes, ~tibble(.x, cum_taxes=.y))
df <- do.call(rbind, merged_df)

或者...在一块...

df <- tibble(a = c('1991-10-01', '1991-11-01', '1991-12-01', '1992-01-01','1992-02-01'), 
              b = c(0.5, 0.6, 0.8, 1.2, 1.4))
df <- df %>% 
  mutate(
    a = as.Date(a),
    y = year(a)
  ) %>% 
  arrange(
    a
  )
split_df <- split(df, df$y)

cum_taxes <- map(split_df, ~(cumprod(.$b + 1) - 1))
df <- do.call(rbind, 
              map2(split_df, cum_taxes, ~tibble(.x, cum_taxes=.y)))