【发布时间】:2021-11-26 07:23:48
【问题描述】:
我有一些漂移的随机游走。我的目标是创建一个函数,在此data.table 中添加一列,根据其累积百分比增益和百分比回撤标记其所在的“区域”。
library(data.table)
set.seed(1)
# generate random returns with drift
df <- data.table(
"date" = 1:50,
"ret" = rnorm(50, mean = .002, sd = .01)
)
# calculate the value of the random-walk over-time
df[, val := cumprod(1 + ret)]
df[, draw_down := val / cummax(val) - 1]
第一个区域出现在第一行并上升,直到出现5% cumulative gain 或2% drawdown。
第二个区域在第一个区域结束后开始一行,一直持续到同样的情况再次发生,5% cumulative gain 或 2% drawdown
这会重复,直到这些事情都没有发生,在这种情况下,区域会继续到最后一行。
这是一个可重现的例子:
# start with the first row and zone of 1
idx <- 1
count <- 1
res <- data.table()
while (idx <= nrow(df)) {
# grab the start of the zone and all future rows
tmp <- df[idx:.N]
# calculate the necessary things
tmp[, val := cumprod(1 + ret)]
tmp[, draw_down := val / cummax(val) - 1]
# find out if we crossed our drawdown threshold
loss_idx <- which(
tmp$draw_down == min(tmp$draw_down[tmp$draw_down <= -.02])
)
# find out if we crossed gain threshold
gain_idx <- which(tmp$val == min(tmp$val[tmp$val >= 1.05]))
# if we have no thresholds, label the rest of the zones
# and exit
if (length(loss_idx) == 0 & length(gain_idx) == 0) {
tmp[, zone := count]
res <- rbind(res, tmp)
break
}
# mark the zone
tmp[1:min(gain_idx, loss_idx), zone := count]
# increment our index
idx <- tmp[min(gain_idx, loss_idx)]$date + 1
print(idx)
# increment our zone
count <- count + 1
res <- rbind(res, tmp[!is.na(zone)])
}
我已尝试获取这些区域点出现位置的索引。但是后来我遇到了需要根据最后一个区域的索引重新计算val 和drawdown 的问题。我想不出一种方法来矢量化它。也许在这里使用roll 函数会有效?
问题归结为知道按区域的回撤,但需要前一个区域才能计算回撤。与累积回报类似。如果这个函数依赖于之前的值,是否可以对这个函数进行向量化?
在尝试实现以下所需输出时,我们将不胜感激任何方向的帮助。
想要的输出:
> res
date ret val draw_down zone
<int> <dbl> <dbl> <dbl> <dbl>
1 -0.0042645381 0.9957355 0.0000000000 1
2 0.0038364332 0.9995555 0.0000000000 1
3 -0.0063562861 0.9932021 -0.0063562861 1
4 0.0179528080 1.0110328 0.0000000000 1
5 0.0052950777 1.0163863 0.0000000000 1
6 -0.0062046838 1.0100800 -0.0062046838 1
7 0.0068742905 1.0170236 0.0000000000 1
8 0.0093832471 1.0265665 0.0000000000 1
9 0.0077578135 1.0345305 0.0000000000 1
10 -0.0010538839 1.0334402 -0.0010538839 1
11 0.0171178117 1.0511304 0.0000000000 1
12 0.0058984324 1.0058984 0.0000000000 2
13 -0.0042124058 1.0016612 -0.0042124058 2
14 -0.0201469989 0.9814807 -0.0242745373 2
15 0.0132493092 1.0132493 0.0000000000 3
16 0.0015506639 1.0148205 0.0000000000 3
17 0.0018380974 1.0166859 0.0000000000 3
18 0.0114383621 1.0283151 0.0000000000 3
19 0.0102122120 1.0388164 0.0000000000 3
20 0.0079390132 1.0470636 0.0000000000 3
21 0.0111897737 1.0587800 0.0000000000 3
22 0.0098213630 1.0691787 0.0000000000 3
23 0.0027456498 1.0721143 0.0000000000 3
24 -0.0178935170 1.0529304 -0.0178935170 3
25 0.0081982575 1.0615626 -0.0098419551 3
26 0.0014387126 1.0630899 -0.0084174023 3
27 0.0004420449 1.0635598 -0.0079790782 3
28 -0.0127075238 1.0500446 -0.0205852077 3
29 -0.0027815006 0.9972185 0.0000000000 4
30 0.0061794156 1.0033807 0.0000000000 4
31 0.0155867955 1.0190202 0.0000000000 4
32 0.0009721227 1.0200108 0.0000000000 4
33 0.0058767161 1.0260051 0.0000000000 4
34 0.0014619496 1.0275051 0.0000000000 4
35 -0.0117705956 1.0154108 -0.0117705956 4
36 -0.0021499456 1.0132277 -0.0138952351 4
37 -0.0019428995 1.0112591 -0.0158111376 4
38 0.0014068660 1.0126818 -0.0144265157 4
39 0.0130002537 1.0258469 -0.0016138103 4
40 0.0096317575 1.0357276 0.0000000000 4
41 0.0003547640 1.0360951 0.0000000000 4
42 -0.0005336168 1.0355422 -0.0005336168 4
43 0.0089696338 1.0448306 0.0000000000 4
44 0.0075666320 1.0527365 0.0000000000 4
45 -0.0048875569 0.9951124 0.0000000000 5
46 -0.0050749516 0.9900623 -0.0050749516 5
47 0.0056458196 0.9956520 0.0000000000 5
48 0.0096853292 1.0052952 0.0000000000 5
49 0.0008765379 1.0061764 0.0000000000 5
50 0.0108110773 1.0170543 0.0000000000 5
【问题讨论】:
-
一个疑问:当
draw_down=0时,你打算如何计算2% drawdown?因为没有阈值,因为 0*0.98 为 0。因此,第 4 行将具有区域 2。 -
我不确定我是否理解。 2% 的回撤实际上是一个 -2% 的阈值。所以 0 的回撤不会触发任何事情
标签: r data.table vectorization