我正在尝试找到一个基于向量a的值更新向量b值的向量化解决方案。我遇到的问题是:
> # Vector a is the "driver" meaning if there is 1 or -1 in vector a
> # -1 or 1 needs to follow in vector b. The challenge I have is when
> # I have 1 or -1 in a and in b I have two or more -1 or 1
> # then all but first same values in b should be set to 0 if values
> # in a does not change
> a <- c(0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 1,-1,-1, 0, 0, 1, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0)
> b <- c(0, 0,-1, 0,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1, 0, 0,-1, 0, 0, 1, 0,-1,-1, 0,-1, 0)
> a
[1] 0 1 0 0 0 0 0 -1 0 0 1 1 -1 -1 0 0 1 0 0 -1 0 1 0 0 0 0 0
> b
[1] 0 0 -1 0 -1 0 0 0 0 1 1 -1 -1 1 1 0 0 -1 0 0 1 0 -1 -1 0 -1 0
>
> # I need a vectorized function(a, b), if possible, that changes b
> # based on a like below (removing some repeated values in b)
> # like below
> b[5] <- 0
> b[11] <- 0
> b[24] <- 0
> b[26] <- 0
> a
[1] 0 1 0 0 0 0 0 -1 0 0 1 1 -1 -1 0 0 1 0 0 -1 0 1 0 0 0 0 0
> b
[1] 0 0 -1 0 0 0 0 0 0 1 0 -1 -1 1 1 0 0 -1 0 0 1 0 -1 0 0 0 0
如何以矢量化方式做到这一点的任何帮助/提示都受到高度赞赏。
我尝试了使用rle,cumsum,diff等的“标准”方法......
# I tried to play around with
test <- data.frame(
a=a,
b=b,
a.plus.b=a + b,
diff.a.plus.b=c(0, diff(a + b)),
cumsum.a.plus.b=cumsum(a + b),
diff.cumsum.a.plus.b=c(0, diff(cumsum(a + b)))
)
test
rle(b)
rle(b)$values
rle(b)$lengths
编辑: 根据大卫要求更清楚我要做的事情,我将详细解释问题。
我正在构建简化的交易回溯测试功能(因为quantstrat是复杂的,并且可以减缓我的需求)。
当我得到上面的值为1(变长)或-1(变短)的入口信号向量时,出现上面的问题(在消息的顶部)。进入信号后,可能会发生三件事(保存在矢量b中):
- 点击时间停止(在白天结束时退出b == - 1如果长,b == 1,如果很短),
- 达到利润目标(再次b == - 1,b == 1)或
- 触发止损(再次b == - 1,b == 1)。
因此,向量b表示每个条目后可能的事件/退出(没有重叠交易 - 一个在输入另一个之前关闭)。有时交易直接对我有利,我们立即达到了利润目标。大。有时我们在达到利润目标之前就停止了。有时候我们都没有达到止损,也没有达到每天结束时的利润目标,因此,我们将在一天结束时离开。
我需要在输入后删除除第一个退出事件之外的所有事件(a == 1或a == - 1)。既然不是所有的都可以/将要发生,只有第一个(从时间的角度来看)应该留下来,我应该删除后续的。
让我举个例子。我们在9:31进入一个长期交易(在第一分钟正常交易时间结束时)。所以变成了:
a <- c(1, 0, 0, 0, 0, ..., 0)
我们总是在最后一分钟结束时退出(时间停止),所以我们将最后一个可能的退出添加到b:
b <- c(0, 0, 0, 0, 0, ...,-1)
我们也知道(在回测中)我们的利润目标已经在9:35的柱子收盘时达到,所以我们将这个事实添加到b(b [5]&lt; - -1):
b <- c(0, 0, 0, 0,-1, ...,-1)
并且,我们也知道(在回测中)停止会在9:33触发,所以我们将其添加到b(b [3]&lt; - -1),现在变为:
b <- c(0, 0,-1, 0,-1, ...,-1)
所以,由于我的利润目标永远不会达到(之前止损)并且我们不会在市场交易中关闭我应该设置b [5]&lt; - 0和b [length(b)] &lt; - 0。因此,在输入后删除b中除了第一个退出触发器之外的所有触发器(a == 1)。 b应该成为:
b <- c(0, 0,-1, 0, 0, ..., 0)
过去我需要处理这一千天......
我希望这能澄清我想要做的事情。
答案 0 :(得分:1)
我不确定我是否真的明白你要做什么,但如果做明白我认为我有一个矢量化解决方案。
> f <- function(a,b){
+ b[unique(c(which(a[-length(a)] == 0 & b[-1] != 0) + 1,which(b[-length(b)] == b[-1] & b[-1] != 0)))] <- 0
+ return(b)
+ }
> f(a,b)
[1] 0 0 -1 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 -1 0 0 1 0 0 0 0 0 0
这是我的理性。我想你想根据两种不同的场景将b的值设置为零:
1)当b的非零值重复时。如果是这样,应该找到那些指数:
which(b[-length(b)] == b[-1] & b[-1] != 0)
2)当a的前一个索引为零时,出现非零值b。如果是这样,这应该可以解决问题:
which(a[-length(a)] == 0 & b[-1] != 0) + 1
希望我在这里没有误解你的目标。
编辑:
第二次尝试这里。我仍然非常确定我不明白你要做什么,因为我的解决方案仍然标志着b [10](你说它不应该),但是从你写的最好我能理解的是你想要做出以下改变:
“a”的零值之后的非零值“b”必须设置为零。
由于此规则错误标记b [10],请告诉我为什么它不正确?我认为这个问题需要用这种方式来表达,以便我给你一个解决方案,因为财务谈话对我来说听起来像是胡言乱语。
无论如何,这是我列出的规则的矢量化解决方案。:
> f <- function(a,b) {
+ b[which(b != 0)[which(!which(b != 0) %in% (which(a[-length(a)] != 0) + 1))]] <- 0
+ return(b)
+ }
> f.indices <- function(a,b) which(b != 0)[which(!which(b != 0) %in% (which(a[-length(a)] != 0) + 1))]
> f(a,b)
[1] 0 0 -1 0 0 0 0 0 0 0 0 -1 -1 1 1 0 0 -1 0 0 1 0 -1 0 0 0 0
> f.indices(a,b)
[1] 5 10 11 24 26
编辑:第三次尝试就是魅力......
现在在目标是设定的情况下操作b的所有非零值除了在非零值a之后的第一个值之外都是零。我不确定是否/如何完全矢量化,但这应该是一个快速的解决方案:
> a <- c(0, 1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 1,-1,-1, 0, 0, 1, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0)
> b <- c(0, 0,-1, 0,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1, 0, 0,-1, 0, 0, 1, 0,-1,-1, 0,-1, 0)
>
> f <- function(a,b){
+ #non-zero b indices
+ nz.b <- which(b != 0)
+ #non-zero a indices
+ nz.a <- which(a != 0)
+ #non-zero b indices that do not follow non-zero a indices
+ nz.b.rm <- nz.b
+ for(i in nz.a){
+ nz.b.rm <- nz.b.rm[!nz.b.rm %in% nz.b[nz.b > i][1]]
+ }
+ #print non-zero b indices that do no folow non-zero a indices
+ print(paste0("Indices Removed: ",paste(nz.b.rm,collapse=",")))
+ #remove non-zero b indices that do not follow non-zero a indices
+ return(b[-nz.b.rm])
+ }
>
> b.new <- f(a,b)
[1] "Indices Removed: 5,11,24,26"
> b.new
[1] 0 0 -1 0 0 0 0 0 1 -1 -1 1 1 0 0 -1 0 0 1 0 -1 0 0