优化R代码 - S& P500系列的采样返回

时间:2012-12-17 07:08:35

标签: r optimization

我试图了解“胜率”如何影响交易策略的回报。

我下载S& P的价格并计算每日回报。然后,我随机选择这些回报的x%,并说我正确地预测了它的方向,所以回报是正的。对于余下的1-x%,我说我错了,回报是否定的。我复制这个过程1000次并收集年化几何回报。

我以0.01增量间隔将x从0.5变为0.6。

这是我的代码:

library(quantmod)
library(multicore)

getSymbols("^GSPC", from = "1950-1-1")
ret <- ROC(GSPC)[-1,4]

set.seed(123)

winpct <- seq(0.5, 0.6, 0.01)
ret <- coredata(ret)

system.time(res <- simplify2array(mclapply(winpct, function(x) replicate(1000, drawsample(ret, x)))))

drawsample <- function(ret, winpct){
  len = length(ret)
  ret = abs(ret)

  win = sample(1:len, round(winpct * len))
  a = c(ret[win], -ret[-win])
  return(prod(1 + a) ^ (252 / length(a)) - 1)
}

所花费的时间:

   user  system elapsed 
 18.904   0.842   5.580 

我可以做些进一步的优化来加快速度吗?

2 个答案:

答案 0 :(得分:4)

我做了以下两个调整:

1 /使用exp(sum(a))而不是prod(1+a)。我想你无论如何都要这样,因为你已经用ROC(GSPC)[-1,6]创建了一个日志返回系列。根据{{​​1}},这让我加速了大约7%。

2 /来自rbenchmark的样本获取c(-1,-1)系列的长度,然后与ret系列相乘,以获得已签名的返回系列。这让我又增加了30%。

请注意,在我的代码中,我已将您的ret重新命名为a

bin

对你的drawsample2 <- function(ret, winpct){ len = length(ret) win = sample(c(-1,1), len, replace=TRUE, prob = c((1-winpct), winpct)) ret <- abs(ret) bin <- ret*win return(exp(sum(bin))^(252/length(ret)) - 1) } 进行基准测试我得到了~37%的加速。

drawsample()

在我的MBP上,这是基准:

bb <- benchmark(simplify2array(mclapply(winpct, function(x) replicate(1000, drawsample(ret, x)))), 
          simplify2array(mclapply(winpct, function(x) replicate(1000, drawsample2(ret, x)))),
          columns =c('test', 'elapsed', 'relative'),
          replications = 10,
          order = 'elapsed')

答案 1 :(得分:2)

这是对ricardo's函数的调整,对于较大的对象来说速度更快。我删除了对mclapply的调用,以便通过避免多核处理所需的网络开销来隔离函数的性能。

drawsample_r <- function(ret, winpct){
  len = length(ret)
  win = sample(c(-1,1), len, replace=TRUE, prob = c((1-winpct), winpct))
  ret <- abs(ret)
  bin <- ret*win
  return(exp(sum(bin))^(252/length(ret)) - 1)
}
drawsample_j <- function(ret, winpct){
  len <- length(ret)
  win <- c(-1L,1L)[sample.int(2L,len,TRUE,c(1-winpct,winpct))]
  exp(sum(abs(ret)*win))^(252L/len)-1L
}
library(rbenchmark)
set.seed(123)
ret <- rnorm(1e6)/100  # 1 million observations
winpct <- seq(0.5, 0.6, 0.01)
benchmark(sapply(winpct, drawsample_r, ret=ret),
          sapply(winpct, drawsample_j, ret=ret),
  replications=10, order='elapsed')[,1:5]
#                                    test replications elapsed relative user.self
# 2 sapply(winpct, drawsample_j, ret=ret)           10   6.963    1.000     6.956
# 1 sapply(winpct, drawsample_r, ret=ret)           10  10.852    1.559    10.689