Inspired by the artical http://gallery.rcpp.org/articles/parallel-distance-matrix/, I try to use RcppParallel to run brute-force search in high-dimensional parametric space for backtesting using multithreads. I am stuck in how to call a self-defined function in the struct
part. The idea is like this:
First, create a parametric matrix NumericMatrix params_mat
in R first, and use the backtesting data with List, NumericVector, CharacterVector
datatype, such as List Data_1, NumericVector Data_2, CharacterVector Data_3, ...
, which are static for each parametric scenario params_vec
(Note that it is the row of params_mat
).
Next, define the backtesting function that output a vector that consisting 3 key variables to evaluate the strategy performance.
Here is an example of my params_mat
and Backtesting_Fun
that can be run in R and Rcpp, respectively.
//[[Rcpp::export]]
NumericMatrix data_frame_rcpp(const Rcpp::List& list_params)
{
NumericMatrix res = list_params[0];
return res;
}
# R codes to generate params_mat
params <- expand.grid (x_1=seq(1,100,1), x_2=seq(3,100,2), ..., x_n=seq(4,200,1));
list_params = list(ts(params));
tmp_params_data = data_frame_rcpp(list_params);
params_mat = matrix(tmp_params_data, ncol = ncol(tmp_params_data), dimnames = NULL);
params_vec = params_mat[ii,];
# User-defined Rcpp codes for backtesting
NumericVector Backtesting_Fun (List Data_1, NumericVector Data_2, CharacterVector Data_3, ..., NumericVector params_vec)
{
// Main function parts to run backtesting for each params_vec scenario.
... etc
// save 3 key result variables together with each params_vec (just a simple illustration).
NumericVector res = NumericVector::create(params_vec[0],...,params_vec[size-1],
key_1, key_2, key_3);
return res;
}
Certainly we need to rewrite/modify the original Rcpp Backtesting_Fun
with RVector/RMatrix types, and then use the following RcppParallel
codes to call Backtesting_Fun
in struct Backtest_parallel
:
// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
using namespace RcppParallel;
RVector<double> Backtesting_Fun (const RVector<double> Data_1, const RVector<double> Data_2,
const RVector<string> Data_3,..., const RVector<double> params_vec)
{
// Main function parts to run backtesting for each params_vec scenario.
... etc;
// save 3 key result variables together with each params_vec
... etc;
return res;
}
struct Backtest_parallel : public Worker
{
// input matrix to read from
const RVector<List> Data_1;
const RVector<double> Data_2;
const RVector<string> Data_3;
...
const RMatrix<double> params_mat;
// output matrix to write to
RMatrix<double> rmat;
// initialize from Rcpp input and output matrixes (the RMatrix class
// can be automatically converted to from the Rcpp matrix type)
Backtest_parallel(const List Data_1, const NumericVector Data_2,
const CharacterVector Data_3, ..., const NumericMatrix params_mat)
: Data_1(Data_1), Data_2(Data_2), Data_3(Data_3), ..., params_mat(params_mat) {}
// function call operator that work for the specified range (begin/end)
void operator()(std::size_t begin, std::size_t end)
{
for (std::size_t ii = begin; ii < end; i++)
{
// params rows that we will operate on
RMatrix<double>::Row params_row = params_mat.row(ii);
// Run the backtesting function defined above
RVector<double> res = Backtesting_Fun(Data_1, Data_2, ..., params_row)
for (std::size_t jj = 0; jj < res.length(); jj++)
{
// write to output matrix
rmat(ii,jj) = res[jj];
}
}
}
};
// [[Rcpp::export]]
NumericMatrix rcpp_parallel_backtest(List Data_1, NumericVector Data_2, CharacterVector Data_3,
..., NumericMatrix params_mat)
{
// allocate the matrix we will return
NumericMatrix rmat(params_mat.nrow(), params_mat.nrow()+3);
// create the worker
Backtest_parallel backtest_parallel(Data_1, Date_2, ..., params_mat);
// call it with parallelFor
parallelFor(0, rmat.nrow(), backtest_parallel);
return rmat;
}
Here are my questions:
Can
RVector
containsList
datatype, or is there any specific container inRcppParallel
to containList
;In the
Backtesting_Fun
, the input should beRVector/RMatrix
types, does that mean we really need to convert the orginal Rcpp main codes withNumericVector
intoRVector
?
Or is there any better way to do parallel computing for my case in RcppParallel? Thanks in advance.
EDIT:
I look at the other examples regarding RcppPararrel in http://gallery.rcpp.org/articles/parallel-matrix-transform/, http://gallery.rcpp.org/articles/parallel-inner-product/, the common idea in
struct operator()
is to use pointers to manipulate the data input foroperator()
, so is there any way to build a user defined function in my case with pointer inputs?If the above way doesn't work, is it feasible to use
wrap
to convertRVector/RMatrix
back into Rcpp datatype, i.e.,NumericVector..
inoperator()
so that the input types of user-defined functionBacktesting_Fun
can remain unchanged.