【问题标题】:Calculating stock's return by a variable interval in data.table通过 data.table 中的可变间隔计算股票的回报
【发布时间】:2019-12-31 10:14:49
【问题描述】:

这是我的数据表

structure(list(index = structure(c(17007, 17008, 17009, 17010, 
17011, 17014, 17015, 17016, 17017), tzone = "UTC", tclass = "Date", class = "Date"), 
    close = c(97.339996, 96.669998, 102.949997, 104.339996, 104.209999, 
    106.050003, 104.480003, 105.790001, 105.870003), daily_return = c(-0.688306993560994, 
    6.49632681279251, 1.35016905342893, -0.124589807344833, 1.76566933850562, 
    -1.48043371578217, 1.25382653367649, 0.0756234041438208, 
    1.5207329313101), group = c(0, 0, 3, 3, 3, 3, 3, 3, 3), qq = c(1, 
    0, 6, 5, 4, 3, 2, 1, 0)), class = c("data.table", "data.frame"
), row.names = c(NA, -9L), .internal.selfref = <pointer: 0x558d2914e9a0>, sorted = "index")

它看起来如下 -

        index  close daily_return group qq
1: 2016-07-25  97.34   -0.6883070     0  1
2: 2016-07-26  96.67    6.4963268     0  0
3: 2016-07-27 102.95    1.3501691     3  6
4: 2016-07-28 104.34   -0.1245898     3  5
5: 2016-07-29 104.21    1.7656693     3  4
6: 2016-08-01 106.05   -1.4804337     3  3
7: 2016-08-02 104.48    1.2538265     3  2
8: 2016-08-03 105.79    0.0756234     3  1
9: 2016-08-04 105.87    1.5207329     3  0

在这个 data.table 中,我需要通过 qq 列中给定的间隔为每个组找到返回(从列关闭)。例如。在第 3 行,前瞻间隔为 6,返回要在第 3 列和第 9 列之间计算(3 + 6 前瞻)。

当组发生变化时,返回是在第一组的最后一个元素和第二组的第一个元素之间计算。例如,当组在第 2 行和第 3 行之间变化时,会在这两行之间计算回报。

以下是想要的结果——

        index  close daily_return group qq desired_result
1: 2016-07-25  97.34   -0.6883070     0  1          -0.68
2: 2016-07-26  96.67    6.4963268     0  0           6.49
3: 2016-07-27 102.95    1.3501691     3  6           2.83
4: 2016-07-28 104.34   -0.1245898     3  5           1.46
5: 2016-07-29 104.21    1.7656693     3  4           1.59
6: 2016-08-01 106.05   -1.4804337     3  3          -0.16
7: 2016-08-02 104.48    1.2538265     3  2           1.33
8: 2016-08-03 105.79    0.0756234     3  1           0.07
9: 2016-08-04 105.87    1.5207329     3  0             NA

我相信一定有一种简单的方法可以使用 data.table 完成此操作。

我尝试了以下方法,它仅适用于特定行,因为 k 是恒定的。

lead(Delt(close, k = 6, type = "arithmetic") * 100, n = 6)

有没有办法在 Delt 命令的 k 变量中动态传递 qq 列? 或者,这个问题还有其他解决方案吗?

【问题讨论】:

  • 迷你建议,更理论化,也许取对数回报,因为股票分布比正常更对数正态(布莱克-斯科尔斯),因此使用对数可以让你的回报正常。
  • 明白,因为我使用算术只是为了测试目的,因为它很容易测试。谢谢!
  • 为什么第 3 行的期望结果是 2.76 而不是 (105.87-102.95)/102.95=2.84?
  • 我已经修复了上述问题中所需的结果列。感谢您的检查。

标签: r data.table


【解决方案1】:

这是一种使用data.table语法没有循环的方法:

idx2 <- close[, .I + ifelse(group == shift(group, -1L), qq, 1L)]
close[, return := (close[idx2] - close) / close * 100][]
        index  close daily_return group qq     return
1: 2016-07-25  97.34   -0.6883070     0  1 -0.6883070
2: 2016-07-26  96.67    6.4963268     0  0  6.4963268
3: 2016-07-27 102.95    1.3501691     3  6  2.8363342
4: 2016-07-28 104.34   -0.1245898     3  5  1.4663667
5: 2016-07-29 104.21    1.7656693     3  4  1.5929412
6: 2016-08-01 106.05   -1.4804337     3  3 -0.1697313
7: 2016-08-02 104.48    1.2538265     3  2  1.3303981
8: 2016-08-03 105.79    0.0756234     3  1  0.0756234
9: 2016-08-04 105.87    1.5207329     3  0         NA

idx2 包含根据本地索引 .I 加上 qq 计算的行索引,除非新组从下一行开始。

idx2
[1]  2  3  9  9  9  9  9  9 NA

计算return的公式取自help("Delt", "quantmod")

默认使用算术差异:Lag = (x2(t) - x1(t-k))/x1(t-k)

因此,我不清楚为什么 OP 的预期结果不同。另见chinsoon's comment

【讨论】:

  • 非常感谢!我正在寻找一个没有 for 循环的解决方案,它回答了我的问题。
【解决方案2】:

这符合您的要求,但据我所知,您显示的所需结果与按照您描述的算法获得的结果不太匹配。

反正算法很简单,循环完成:

# Creates a zero-filled column to hold the results
df$desired_result <- numeric(length(df$close))

# Loops through each row
for(i in seq_along(df$desired_result))
{
  # We don’t want to do anything in the final row
  if(i == length(df$desired_result)) break;

  # if the row’s qq value is 0, get the difference between this row and next row’s close value
  # otherwise use the row’s qq value to look ahead that number of rows
  if(df$qq[i] == 0) df$desired_result[i] <- df$close[i + 1] - df$close[i]
  else df$desired_result[i] <-  df$close[i + df$qq[i]] - df$close[i]
} 

现在你可以这样做了:

#> df
#>       index  close daily_return group qq desired_result
#> 1 2016-07-25  97.34   -0.6883070     0  1      -0.670000
#> 2 2016-07-26  96.67    6.4963268     0  0       6.279997
#> 3 2016-07-27 102.95    1.3501691     3  6       2.920006
#> 4 2016-07-28 104.34   -0.1245898     3  5       1.530007
#> 5 2016-07-29 104.21    1.7656693     3  4       1.660004
#> 6 2016-08-01 106.05   -1.4804337     3  3      -0.180000
#> 7 2016-08-02 104.48    1.2538265     3  2       1.390000
#> 8 2016-08-03 105.79    0.0756234     3  1       0.080002
#> 9 2016-08-04 105.87    1.5207329     3  0       0.000000

【讨论】:

  • @Saurabh 谢谢。我已经相应地更新了我的答案
  • @Saurabh 我已发表评论以使其更易于关注
  • 感谢艾伦的 cmets!
猜你喜欢
  • 1970-01-01
  • 2021-12-25
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 2021-11-09
  • 2021-04-07
相关资源
最近更新 更多