## Wednesday 6 June 2012

### Creation of a Simple Benchmark Suite

For some time now I have been toying with the idea of creating a simple benchmark suite to compare my own back test system performance with that of some public domain trading systems. I decided to select a few examples from the Trading Blox Users' Guide, specifically:
• exponential moving average crossovers of periods 10-20 and 20-50
• triple moving average crossover system with periods 10-20-50
• Bollinger band breakouts of periods 20 and 50 with 1 & 2 standard deviations for exits and entries
• donchian channel breakouts with periods 20-10 and 50-25
This is a total of 7 systems, and in the Rcpp code below these form a sort of "committee" to vote to be either long/short 1 contract, or neutral.

``````# This function takes as inputs vectors of opening and closing prices
# and creates a basic benchmark output suite of system equity curves
# for the following basic trend following systems
# exponential moving average crossovers of 10-20 and 20-50
# triple moving average crossovers of 10-20-50
# bollinger band breakouts of 20 and 50 with 1 & 2 standard deviations
# donchian channel breakouts of 20-10 and 50-25
# The libraries required to compile this function are
# "Rcpp," "inline" and "compiler." The function is compiled by the command
# > source("basic_benchmark_equity.r") in the console/terminal.

library(Rcpp) # load the required library
library(inline) # load the required library
library(compiler) # load the required library

src <- '
#include
#include

Rcpp::NumericVector open(a) ;
Rcpp::NumericVector close(b) ;
Rcpp::NumericVector market_mode(c) ;
Rcpp::NumericVector kalman(d) ;
Rcpp::NumericVector tick_size(e) ;
Rcpp::NumericVector tick_value(f) ;
int n = open.size() ;
Rcpp::NumericVector sma_10(n) ;
Rcpp::NumericVector sma_20(n) ;
Rcpp::NumericVector sma_50(n) ;
Rcpp::NumericVector std_20(n) ;
Rcpp::NumericVector std_50(n) ;

// create equity output vectors
Rcpp::NumericVector market_mode_long_eq(n) ;
Rcpp::NumericVector market_mode_short_eq(n) ;
Rcpp::NumericVector market_mode_composite_eq(n) ;
Rcpp::NumericVector sma_10_20_eq(n) ;
Rcpp::NumericVector sma_20_50_eq(n) ;
Rcpp::NumericVector tma_eq(n) ;
Rcpp::NumericVector bbo_20_eq(n) ;
Rcpp::NumericVector bbo_50_eq(n) ;
Rcpp::NumericVector donc_20_eq(n) ;
Rcpp::NumericVector donc_50_eq(n) ;
Rcpp::NumericVector composite_eq(n) ;

// position vectors for benchmark systems
Rcpp::NumericVector sma_10_20_pv(1) ;
sma_10_20_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector sma_20_50_pv(1) ;
sma_20_50_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector tma_pv(1) ;
tma_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector bbo_20_pv(1) ;
bbo_20_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector bbo_50_pv(1) ;
bbo_50_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector donc_20_pv(1) ;
donc_20_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector donc_50_pv(1) ;
donc_50_pv[0] = 0.0 ; // initialise to zero, no position

Rcpp::NumericVector comp_pv(1) ;
comp_pv[0] = 0.0 ; // initialise to zero, no position

// fill the equity curve vectors with zeros for "burn in" period
// and create the initial values for all indicators

for ( int ii = 0 ; ii < 50 ; ii++ ) {

if ( ii >= 40 ) {
sma_10[49] += close[ii] ; }

if ( ii >= 30 ) {
sma_20[49] += close[ii] ; }

sma_50[49] += close[ii] ;

std_20[ii] = 0.0 ;
std_50[ii] = 0.0 ;

market_mode_long_eq[ii] = 0.0 ;
market_mode_short_eq[ii] = 0.0 ;
market_mode_composite_eq = 0.0 ;
sma_10_20_eq[ii] = 0.0 ;
sma_20_50_eq[ii] = 0.0 ;
bbo_20_eq[ii] = 0.0 ;
bbo_50_eq[ii] = 0.0 ;
tma_eq[ii] = 0.0 ;
donc_20_eq[ii] = 0.0 ;
donc_50_eq[ii] = 0.0 ;
composite_eq[ii] = 0.0 ; } // end of initialising loop

sma_10[49] = sma_10[49] / 10.0 ;
sma_20[49] = sma_20[49] / 20.0 ;
sma_50[49] = sma_50[49] / 50.0 ;

// the main calculation loop
for ( int ii = 50 ; ii < n-2 ; ii++ ) {

// calculate the smas
sma_10[ii] = ( sma_10[ii-1] - sma_10[ii-10] / 10.0 ) + ( close[ii] / 10.0 ) ;
sma_20[ii] = ( sma_20[ii-1] - sma_20[ii-20] / 20.0 ) + ( close[ii] / 20.0 ) ;
sma_50[ii] = ( sma_50[ii-1] - sma_50[ii-50] / 50.0 ) + ( close[ii] / 50.0 ) ;

// calculate the standard deviations
for ( int jj = 0 ; jj < 50 ; jj++ ) {

if ( jj < 20 ) {
std_20[ii] += ( close[ii-jj] - sma_20[ii] ) * ( close[ii-jj] - sma_20[ii] )  ; } // end of jj if

std_50[ii] += ( close[ii-jj] - sma_50[ii] ) * ( close[ii-jj] - sma_50[ii] ) ; } // end of standard deviation loop

std_20[ii] = sqrt( std_20[ii] / 20.0 ) ;
std_50[ii] = sqrt( std_50[ii] / 50.0 ) ;

//-------------------------------------------------------------------------------------------------------------------

// calculate the equity values of the market modes
// market_mode uwr and unr long signals
if ( market_mode[ii] == 1 || market_mode[ii] == 2 ) {
market_mode_long_eq[ii] = market_mode_long_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
market_mode_short_eq[ii] = market_mode_short_eq[ii-1] ;
market_mode_composite_eq[ii] = market_mode_composite_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; }

// market_mode dwr and dnr short signals
if ( market_mode[ii] == 3 || market_mode[ii] == 4 ) {
market_mode_long_eq[ii] = market_mode_long_eq[ii-1] ;
market_mode_short_eq[ii] = market_mode_short_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
market_mode_composite_eq[ii] = market_mode_composite_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; }

// calculate the equity values of the market modes
// market_mode cyc long signals
if ( market_mode[ii] == 0 && kalman[ii] > kalman[ii-1] ) {
market_mode_long_eq[ii] = market_mode_long_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
market_mode_short_eq[ii] = market_mode_short_eq[ii-1] ;
market_mode_composite_eq[ii] = market_mode_composite_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; }

// market_mode cyc short signals
if ( market_mode[ii] == 0 && kalman[ii] < kalman[ii-1] ) {
market_mode_long_eq[ii] = market_mode_long_eq[ii-1] ;
market_mode_short_eq[ii] = market_mode_short_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
market_mode_composite_eq[ii] = market_mode_composite_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; }

//----------------------------------------------------------------------------------------------------------------------------

// calculate the equity values and positions of each benchmark system
// sma_10_20_eq
if ( sma_10[ii] > sma_20[ii] ) {
sma_10_20_eq[ii] = sma_10_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
sma_10_20_pv[0] = 1.0 ; } // long

// sma_10_20_eq
if ( sma_10[ii] < sma_20[ii] ) {
sma_10_20_eq[ii] = sma_10_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
sma_10_20_pv[0] = -1.0 ; } // short

// sma_10_20_eq
if ( sma_10[ii] == sma_20[ii] && sma_10[ii-1] > sma_20[ii-1] ) {
sma_10_20_eq[ii] = sma_10_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
sma_10_20_pv[0] = 1.0 ; } // long

// sma_10_20_eq
if ( sma_10[ii] == sma_20[ii] && sma_10[ii-1] < sma_20[ii-1] ) {
sma_10_20_eq[ii] = sma_10_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
sma_10_20_pv[0] = -1.0 ; } // short

//-----------------------------------------------------------------------------------------------------------

// sma_20_50_eq
if ( sma_20[ii] > sma_50[ii] ) {
sma_20_50_eq[ii] = sma_20_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
sma_20_50_pv[0] = 1.0 ; } // long

// sma_20_50_eq
if ( sma_20[ii] < sma_50[ii] ) {
sma_20_50_eq[ii] = sma_20_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
sma_20_50_pv[0] = -1.0 ; } // short

// sma_20_50_eq
if ( sma_20[ii] == sma_50[ii] && sma_20[ii-1] > sma_50[ii-1] ) {
sma_20_50_eq[ii] = sma_20_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
sma_20_50_pv[0] = 1.0 ; } // long

// sma_20_50_eq
if ( sma_20[ii] == sma_50[ii] && sma_20[ii-1] < sma_50[ii-1] ) {
sma_20_50_eq[ii] = sma_20_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
sma_20_50_pv[0] = -1.0 ; } // short

//-----------------------------------------------------------------------------------------------------------

// tma_eq
if ( tma_pv[0] == 0.0 ) {

// default position
tma_eq[ii] = tma_eq[ii-1] ;

// unless one of the two following conditions is true

if ( sma_10[ii] > sma_20[ii] && sma_20[ii] > sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
tma_pv[0] = 1.0 ; } // long

if ( sma_10[ii] < sma_20[ii] && sma_20[ii] < sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
tma_pv[0] = -1.0 ; } // short

} // end of tma_pv == 0.0 loop

if ( tma_pv[0] == 1.0 ) {

// default long position
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; // long

// unless one of the two following conditions is true

if ( sma_10[ii] < sma_20[ii] && sma_10[ii] > sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] ;
tma_pv[0] = 0.0 ; } // exit long, go neutral

if ( sma_10[ii] < sma_20[ii] && sma_20[ii] < sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
tma_pv[0] = -1.0 ; } // short

} // end of tma_pv == 1.0 loop

if ( tma_pv[0] == -1.0 ) {

// default short position
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; // short

// unless one of the two following conditions is true

if ( sma_10[ii] > sma_20[ii] && sma_10[ii] < sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] ;
tma_pv[0] = 0.0 ; } // exit short, go neutral

if ( sma_10[ii] > sma_20[ii] && sma_20[ii] > sma_50[ii] ) {
tma_eq[ii] = tma_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
tma_pv[0] = 1.0 ; } // long

} // end of tma_pv == -1.0 loop

//------------------------------------------------------------------------------------------------------------

// bbo_20_eq
if ( bbo_20_pv[0] == 0.0 ) {

// default position
bbo_20_eq[ii] = bbo_20_eq[ii-1] ;

// unless one of the two following conditions is true

if ( close[ii] > sma_20[ii] + 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
bbo_20_pv[0] = 1.0 ; } // long

if ( close[ii] < sma_20[ii] - 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
bbo_20_pv[0] = -1.0 ; } // short

} // end of bbo_20_pv == 0.0 loop

if ( bbo_20_pv[0] == 1.0 ) {

// default long position
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; // long

// unless one of the two following conditions is true

if ( close[ii] < sma_20[ii] + std_20[ii] && close[ii] > sma_20[ii] - 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] ;
bbo_20_pv[0] = 0.0 ; } // exit long, go neutral

if ( close[ii] < sma_20[ii] - 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
bbo_20_pv[0] = -1.0 ; } // short

} // end of bbo_20_pv == 1.0 loop

if ( bbo_20_pv[0] == -1.0 ) {

// default short position
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; // short

// unless one of the two following conditions is true

if ( close[ii] > sma_20[ii] - std_20[ii] && close[ii] < sma_20[ii] + 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] ;
bbo_20_pv[0] = 0.0 ; } // exit short, go neutral

if ( close[ii] > sma_20[ii] + 2.0 * std_20[ii] ) {
bbo_20_eq[ii] = bbo_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
bbo_20_pv[0] = 1.0 ; } // long

} // end of bbo_20_pv == -1.0 loop

//-------------------------------------------------------------------------------------------------

// bbo_50_eq
if ( bbo_50_pv[0] == 0.0 ) {

// default position
bbo_50_eq[ii] = bbo_50_eq[ii-1] ;

// unless one of the two following conditions is true

if ( close[ii] > sma_50[ii] + 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
bbo_50_pv[0] = 1.0 ; } // long

if ( close[ii] < sma_50[ii] - 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
bbo_50_pv[0] = -1.0 ; } // short

} // end of bbo_50_pv == 0.0 loop

if ( bbo_50_pv[0] == 1.0 ) {

// default long position
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; // long

// unless one of the two following conditions is true

if ( close[ii] < sma_50[ii] + std_50[ii] && close[ii] > sma_50[ii] - 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] ;
bbo_50_pv[0] = 0.0 ; } // exit long, go neutral

if ( close[ii] < sma_50[ii] - 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
bbo_50_pv[0] = -1.0 ; } // short

} // end of bbo_50_pv == 1.0 loop

if ( bbo_50_pv[0] == -1.0 ) {

// default short position
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; // short

// unless one of the two following conditions is true

if ( close[ii] > sma_50[ii] - std_50[ii] && close[ii] < sma_50[ii] + 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] ;
bbo_50_pv[0] = 0.0 ; } // exit short, go neutral

if ( close[ii] > sma_50[ii] + 2.0 * std_50[ii] ) {
bbo_50_eq[ii] = bbo_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
bbo_50_pv[0] = 1.0 ; } // long

} // end of bbo_50_pv == -1.0 loop

//-----------------------------------------------------------------------------------------------------

// donc_20_eq
if ( donc_20_pv[0] == 0.0 ) {

// default position
donc_20_eq[ii] = donc_20_eq[ii-1] ;

// unless one of the two following conditions is true

if ( close[ii] > *std::max_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
donc_20_pv[0] = 1.0 ; } // long

if ( close[ii] < *std::min_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
donc_20_pv[0] = -1.0 ; } // short

} // end of donc_20_pv == 0.0 loop

if ( donc_20_pv[0] == 1.0 ) {

// default long position
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; // long

// unless one of the two following conditions is true

if ( close[ii] < *std::min_element( &close[ii-10], &close[ii] ) && close[ii] > *std::min_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] ;
donc_20_pv[0] = 0.0 ; } // exit long, go neutral

if ( close[ii] < *std::min_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
donc_20_pv[0] = -1.0 ; } // short

} // end of donc_20_pv == 1.0 loop

if ( donc_20_pv[0] == -1.0 ) {

// default short position
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; // short

// unless one of the two following conditions is true

if ( close[ii] > *std::max_element( &close[ii-10], &close[ii] ) && close[ii] < *std::max_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] ;
donc_20_pv[0] = 0.0 ; } // exit short, go neutral

if ( close[ii] > *std::max_element( &close[ii-20], &close[ii] ) ) {
donc_20_eq[ii] = donc_20_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
donc_20_pv[0] = 1.0 ; } // long

} // end of donc_20_pv == -1.0 loop

//-------------------------------------------------------------------------------------------------

// donc_50_eq
if ( donc_50_pv[0] == 0.0 ) {

// default position
donc_50_eq[ii] = donc_50_eq[ii-1] ;

// unless one of the two following conditions is true

if ( close[ii] > *std::max_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
donc_50_pv[0] = 1.0 ; } // long

if ( close[ii] < *std::min_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
donc_50_pv[0] = -1.0 ; } // short

} // end of donc_50_pv == 0.0 loop

if ( donc_50_pv[0] == 1.0 ) {

// default long position
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; // long

// unless one of the two following conditions is true

if ( close[ii] < *std::min_element( &close[ii-25], &close[ii] ) && close[ii] > *std::min_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] ;
donc_50_pv[0] = 0.0 ; } // exit long, go neutral

if ( close[ii] < *std::min_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ;
donc_50_pv[0] = -1.0 ; } // short

} // end of donc_50_pv == 1.0 loop

if ( donc_50_pv[0] == -1.0 ) {

// default short position
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; // short

// unless one of the two following conditions is true

if ( close[ii] > *std::max_element( &close[ii-25], &close[ii] ) && close[ii] < *std::max_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] ;
donc_50_pv[0] = 0.0 ; } // exit short, go neutral

if ( close[ii] > *std::max_element( &close[ii-50], &close[ii] ) ) {
donc_50_eq[ii] = donc_50_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ;
donc_50_pv[0] = 1.0 ; } // long

} // end of donc_50_pv == -1.0 loop

//-------------------------------------------------------------------------------------------------

// composite_eq
comp_pv[0] = sma_10_20_pv[0] + sma_20_50_pv[0] + tma_pv[0] + bbo_20_pv[0] + bbo_50_pv[0] + donc_20_pv[0] + donc_50_pv[0] ;

if ( comp_pv[0] > 0 ) {
composite_eq[ii] = composite_eq[ii-1] + tick_value[0] * ( (open[ii+2]-open[ii+1])/tick_size[0] ) ; } // long

if ( comp_pv[0] < 0 ) {
composite_eq[ii] = composite_eq[ii-1] + tick_value[0] * ( (open[ii+1]-open[ii+2])/tick_size[0] ) ; } // short

if ( comp_pv[0] == 0 ) {
composite_eq[ii] = composite_eq[ii-1] ; } // neutral

} // end of main for loop

// Now fill in the last two spaces in the equity vectors
market_mode_long_eq[n-1] = market_mode_long_eq[n-3] ;
market_mode_long_eq[n-2] = market_mode_long_eq[n-3] ;

market_mode_short_eq[n-1] = market_mode_short_eq[n-3] ;
market_mode_short_eq[n-2] = market_mode_short_eq[n-3] ;

market_mode_composite_eq[n-1] = market_mode_composite_eq[n-3] ;
market_mode_composite_eq[n-2] = market_mode_composite_eq[n-3] ;

sma_10_20_eq[n-1] = sma_10_20_eq[n-3] ;
sma_10_20_eq[n-2] = sma_10_20_eq[n-3] ;

sma_20_50_eq[n-1] = sma_20_50_eq[n-3] ;
sma_20_50_eq[n-2] = sma_20_50_eq[n-3] ;

tma_eq[n-1] = tma_eq[n-3] ;
tma_eq[n-2] = tma_eq[n-3] ;

bbo_20_eq[n-1] = bbo_20_eq[n-3] ;
bbo_20_eq[n-2] = bbo_20_eq[n-3] ;

bbo_50_eq[n-1] = bbo_50_eq[n-3] ;
bbo_50_eq[n-2] = bbo_50_eq[n-3] ;

donc_20_eq[n-1] = donc_20_eq[n-3] ;
donc_20_eq[n-2] = donc_20_eq[n-3] ;

donc_50_eq[n-1] = donc_50_eq[n-3] ;
donc_50_eq[n-2] = donc_50_eq[n-3] ;

composite_eq[n-1] = composite_eq[n-3] ;
composite_eq[n-2] = composite_eq[n-3] ;

return List::create(
_["market_mode_long_eq"] = market_mode_long_eq ,
_["market_mode_short_eq"] = market_mode_short_eq ,
_["market_mode_composite_eq"] = market_mode_composite_eq ,
_["sma_10_20_eq"] = sma_10_20_eq ,
_["sma_20_50_eq"] = sma_20_50_eq ,
_["tma_eq"] = tma_eq ,
_["bbo_20_eq"] = bbo_20_eq ,
_["bbo_50_eq"] = bbo_50_eq ,
_["donc_20_eq"] = donc_20_eq ,
_["donc_50_eq"] = donc_50_eq ,
_["composite_eq"] = composite_eq ) ; '

basic_benchmark_equity <- cxxfunction(signature(a = "numeric", b = "numeric", c = "numeric",
d = "numeric", e = "numeric", f = "numeric"), body=src,
plugin = "Rcpp")
``````

This Rcpp function is then called thus, using Rstudio

``````library(xts)  # load the required library

tick_size <- 0.01
tick_value <- 12.50

# extract other vectors of interest
open <- data[,2]
close <- data[,5]
market_mode <- data[,228]
kalman <- data[,283]

results <- basic_benchmark_equity(open,close,market_mode,kalman,tick_size,tick_value)

# coerce the above results list object to a data frame object
results_df <- data.frame( results )
df_max <- max(results_df) # for scaling of results plot
df_min <- min(results_df) # for scaling of results plot

# and now create an xts object for plotting
results_xts <- xts(results_df,as.Date(data[,'V1']))

# a nice plot of the results_xts object
par(col="#0000FF")
plot(results_xts[,'market_mode_long_eq'],main="USDYEN Pair",ylab="\$ Equity Value",ylim=c(df_min,df_max),type="l")
par(new=TRUE,col="#B0171F")
plot(results_xts[,'market_mode_short_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE,col="#00FF00")
plot(results_xts[,'market_mode_composite_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE,col="#808080")
plot(results_xts[,'sma_10_20_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'sma_20_50_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'tma_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'bbo_20_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'bbo_50_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'donc_20_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE)
plot(results_xts[,'donc_50_eq'],main="",ylim=c(df_min,df_max),type="l")
par(new=TRUE,col="black")
plot(results_xts[,'composite_eq'],main="",ylim=c(df_min,df_max),type="l")

``````

to output .png files which I have strung together in this video
Non-embedded view here.
The light grey equity curves are the individual curves for the benchmark systems and the black is the "committee" 1 contract equity curve. Also shown are the long and short 1 contract equity curves ( blue and red respectively ), along with a green combined equity curve for these, for my Naive Bayesian Classifier following the simple rules
• be long 1 contract if the market type is uwr, unr or cyclic with my Kalman filter pointing upwards
• be short 1 contract if the market type is dwr, dnr or cyclic with my Kalman filter pointing downwards
Again this is just a toy example of the use of my Bayesian Classifier.  After I have completed Andrew Ng's machine learning course, as mentioned in my previous post, I will have a go at coding a neural net which may end up replacing the Bayesian Classifier.