首页 > 解决方案 > 如何计算 data.table 中的回报?

问题描述

我是堆栈溢出的新手和 R 初学者。

我想计算一个大数据集的回报,如下所示:

Date        C1  C2  C3
31.01.1985  NA  47  NA
28.02.1985  NA  45  NA
29.03.1985  130 56  NA
30.04.1985  140 67  NA
31.05.1985  150 48  93
28.06.1985  160 79  96
31.07.1985  160 56  94
30.08.1985  160 77  93
30.09.1985  160 66  93
31.10.1985  160 44  93
29.11.1985  160 55  93

这是一种data.table格式,假设它被称为价格,列是公司,值是价格,实际数据集有更多的列和行。我想建立一个新的 DT 来计算每月的回报,我知道你可以用这个diff()函数来做到这一点。但是如何在没有 for 循环的情况下构建包含这么多列的新数据表?

我想到了:

Returns <- diff(Prices[, names(Prices) != "Date"])

但这出于某种原因只给出了:

[1] 1 0 0

提前致谢。

标签: rdata.tablefinancequantitative-finance

解决方案


您获得该输出的原因是因为Prices[, names(Prices) != "Date"]返回一个逻辑向量:

> Prices[, names(Prices) != "Date"]
[1] FALSE  TRUE  TRUE  TRUE

而且因为您可以使用逻辑进行计算,所以您也可以diff在逻辑向量上使用。FALSE然后被视为 a0TRUEa 1。所以基本上你在做diff(c(0,1,1,1))


您想要的可能解决方案:

cols <- setdiff(names(Prices),"Date")

# option 1:
Prices[, paste0(cols,"_return") := lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA)), .SDcols = cols][]

# option 2:
Prices[, paste0(cols,"_return") := lapply(.SD, function(x) c(NA,diff(x))/shift(x, fill = NA)), .SDcols = cols][]

这使:

> Prices
          Date  C1 C2 C3  C1_return   C2_return   C3_return
 1: 1985-01-31  NA 47 NA         NA          NA          NA
 2: 1985-02-28  NA 45 NA         NA -0.04255319          NA
 3: 1985-03-29 130 56 NA         NA  0.24444444          NA
 4: 1985-04-30 140 67 NA 0.07692308  0.19642857          NA
 5: 1985-05-31 150 48 93 0.07142857 -0.28358209          NA
 6: 1985-06-28 160 79 96 0.06666667  0.64583333  0.03225806
 7: 1985-07-31 160 56 94 0.00000000 -0.29113924 -0.02083333
 8: 1985-08-30 160 77 93 0.00000000  0.37500000 -0.01063830
 9: 1985-09-30 160 66 93 0.00000000 -0.14285714  0.00000000
10: 1985-10-31 160 44 93 0.00000000 -0.33333333  0.00000000
11: 1985-11-29 160 55 93 0.00000000  0.25000000  0.00000000

如果要创建新的data.table,可以使用以下两个选项之一:

# option 1:
Returns <- Prices[, c(list(Date = Date), lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA))), .SDcols = cols]

# option 2:
Returns <- copy(Prices)
Returns[, (cols) := lapply(.SD, function(x) (x - shift(x, fill = NA))/shift(x, fill = NA)), .SDcols = cols]

使用数据:

Prices <- fread("Date        C1  C2  C3
31.01.1985  NA  47  NA
28.02.1985  NA  45  NA
29.03.1985  130 56  NA
30.04.1985  140 67  NA
31.05.1985  150 48  93
28.06.1985  160 79  96
31.07.1985  160 56  94
30.08.1985  160 77  93
30.09.1985  160 66  93
31.10.1985  160 44  93
29.11.1985  160 55  93")[, Date := as.Date(Date, "%d.%m.%Y")]

推荐阅读