我想请求一些关于如何创建库存数据累积回报的新列的帮助。我的数据结构如下:
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)
答案 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 map 和 map2 函数来完成这项工作:
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)))