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.