Running backtests in parallel
btest
offers functionality to run several backtests,
or variations of backtests, automatically. Since such
computations are independent from each other, they can
also be distributed. btest
relies on the parallel
package to do this.
A simple example.
library("PMwR")
A simple, useless strategy: buy when the last observed
price is at least h
, which we set to 5.
signal <- function(h) { if (Close() >= h) 1 else 0 } btest(1:10, signal = signal, h = 5)
initial wealth 0 => final wealth 4
We may now specify variations for each argument.
btest(1:10, signal = signal, variations = list(h = 1:5))
[[1]] initial wealth 0 => final wealth 8 [[2]] initial wealth 0 => final wealth 7 [[3]] initial wealth 0 => final wealth 6 [[4]] initial wealth 0 => final wealth 5 [[5]] initial wealth 0 => final wealth 4
The default is to process these variations through a loop,
but this may be changed by specifying the argument
variations.settings
.
signal <- function(h) { Sys.sleep(0.1) if (Close() > h) 1 else 0 } system.time( btest(1:10, signal = signal, variations = list(h = 1:5))) system.time( btest(1:10, signal = signal, variations = list(h = 1:5), variations.settings = list(method = "parallel", cores = 5))) system.time( btest(1:10, signal = signal, variations = list(h = 1:5), variations.settings = list(method = "multicore", cores = 5)))
user system elapsed 0.022 0.000 4.532 user system elapsed 0.020 0.012 1.831 user system elapsed 0.005 0.005 0.914
Variations works for any argument, even functions.
signal1 <- function() 1 signal2 <- function() 2 btest(1:10, variations = list(signal = list(signal1, signal2)))
[[1]] initial wealth 0 => final wealth 8 [[2]] initial wealth 0 => final wealth 16
In some cases, the result of a backtest may be subject
to chance, and we may want to run the backtest several
times, but with the same parameters. To do so, specify
the replications
argument.
signal <- function() { sample(0:4, 1) } btest(1:10, signal = signal, replications = 5)
[[1]] initial wealth 0 => final wealth 12 [[2]] initial wealth 0 => final wealth 16 [[3]] initial wealth 0 => final wealth 16 [[4]] initial wealth 0 => final wealth 10 [[5]] initial wealth 0 => final wealth 15
For both variations
and replications
, the result
will be a list of backtests.