R Bridge

The R bridge connects Zorro scripts to the R environment and allows R computations from your C code.

R is an interactive script language for data analysis and charting, developed in 1996 by Ross Ihaka and Robert Gentleman of Oakland University as successor to the S language. The latter was developed by John M. Chambers and his colleagues in the Bell Labs company in 1976. Today, R is still being improved by the R Development Core Team including John Chambers. Although R is an interpreted language and thus slow compared to 'real' programming languages such as C, it has many advantages:

This makes R an excellent research tool for analyzing and predicting financial time series, using the newest published methods. However, R is not a clean programming language such as C - it is full of traps to the beginner, so using it effectively needs experience. It's also no environment suited for trading (although some packages provide rudimentary backtest, optimization, and even broker connection functions!). The solution to this is the R bridge that allows triggering R computations in a Zorro strategy and using their results for trade signals. The lite-C script starts the R session, sends price data or indicator values to it, and calls training and predicting functions from a R machine learning package. The bridge uses the mt4R.dll by Bernd Kreuss. Its original distribution with source code is contained in the Zorro\Source folder.

Many problems can be solved in lite-C as well as in R, but R often has already a dedicated command implemented for that. For instance, downloading historical price data from Yahoo requires 11 code lines in lite-C (here), but only a single line in R (read.csv("http://ichart.finance.yahoo.com/table.csv?...")).

Installation and test

R bridge functions

The r.h header defines several functions to directly assign and read data types without the need for manually formatting and executing snippets of R code for these purposes. Not all possible data types are directly supported, the main emphasis is on vectors and matrices containing floating point values. Once you have transferred the bulk of your data as vectors or matrices into the R session, you can execute snippets of R code to combine them or convert them into something more complex if needed.

Normally you want to get huge amounts of numeric data into the R session quickly, but not the other way. The assumption is that you want to feed it with price data on order to crunch numbers, and only need to get back a single value or a vector as a result.

All vector functions have a parameter for the number of elements. Be careful that the array you supply has the correct size, or it will crash the R console. Expressions or code snippets have a maximum size of 1000 characters per command; larger pieces of code must be sent with several commands or - much better - be called as a function in the R environment. See RTest.c for example usage.

Rstart(string source, int debuglevel): int

Start a new R session, and load R functions and variables from the file source. This must be called in the INITRUN before any R computations can be done. Returns 0 when the R session could not be started, otherwise nonzero.

Parameters:

source

Name of a .r file in the Strategy folder containing all needed R functions and variables (f.i. "MySource.r"), or "" (default) for not sourcing a file.

debuglevel

0 - only output fatal errors (default)
1 - output warnings and notes
2 - output every R message
The R output goes to the system debug monitor. Use the free DebugView tool from Microsoft, or call Rx(..., 3) to view R output).

Rrun(): int

Return 1 if the R session is ready for input, 2 if the session is busy with a computation, and 0 if the session is terminated. R will terminate on any fatal error in the code. You should check this regularly. The last command prior to the termination will be found in the debug output. If R is not running anymore, the R bridge won't emit any more messages and will silently ignore all commands.

Rx(string code, int mode): int

Execute a line of R code. Similar to the Ri / Rd / Rv functions below, as evaluating an expression is also just executing code; the difference is that Rx() can send commands asynchronously, allows R and Zorro to do computations in parallel, and prints R output to the Zorro window.

Parameters:

code R code line to be executed (1000 characters max).
mode

0 - synchronous. Wait until the computation was finished (default).
1 - asynchronous. Return immediately. Rrun() can be used to check when the next R command can be sent.
2 - asynchronous, with a wait loop. Return 1 when finished, or quit with returning 0 when the session was aborted due hitting [Stop] or due to a fatal R error.
3 - asynchronous with a wait loop, and direct R print output to the Zorro window. The debuglevel must be set accordingly.

Rset(string name, int n)

Rset(string name, var d)

Rset(string name, var *v, int elements)

Rset(string name, var *m, int rows, int cols)

Store an int, var, series or matrix in the R variable name.

Parameters:

name Name of the R variable.
i int value to be assigned to a R integer variable.
d var value to be assigned to a R floating point variable.
v Pointer of the var array or series to be assigned to a R vector.
m Pointer of the var array to be assigned to a R matrix, by row order.
elements Length of the vector or series. Make sure to give the exact number of elements.
rows, cols Number of rows and columns of the matrix.
 

Ri(string expression): int

Rd(string expression): var

Rv(string expression, var *v, int elements)

Evaluate the given R expression, and return the result as an int, double, or vector. The expression can be a single variable, a R function, or any R code that will evaluate to the required variable type.

Parameters:

expression R expression to be evaluated (1000 characters max).
v Pointer of the var array to be filled with the R vector.
elements Number of elements of the vector; must be identical in the R code and in the lite-C script.

Remarks:

Examples (see also advise):

// do some R calculations
#include <default.c>
#include <r.h> function main() { Rstart("",2); // enable output var vecIn[5],vecOut[5]; int i; for(i=0; i<5; i++) vecIn[i] = i; Rset("rin",vecIn,5); // set up a vector Rx("rout <- rin * 10"); // perform some arithmetics Rx("print(rout)",3); // print rout to the Zorro window Rv("rout",vecOut,5); // read it back if(!Rrun()) printf("Error - R session aborted!"); else for(i=0; i<5; i++) printf("%.0f ",vecOut[i]); }
//Example for computing trade signals in R
#include <r.h>

int Size = 200; // number of candles needed by the R algorithm  

bool RCheck()
{
   if(!Rrun()) {
     quit("R session aborted!");
     return false;     
   }
   return true;
}

function run()
{
  BarPeriod = 60;
  LookBack = Size;
  asset("EUR/USD");  
  
  if(is(INITRUN)) {
    Rstart("MySignals.r",1);
// load all required R objects from a file in the Zorro Data folder 
    Rx(strf("load('%sData/MyObjects.bin')",slash(ZorroFolder)));
// make sure everything loaded ok
    if(!RCheck()) return;
  }

// generate reverse price series (latest price comes last)
  vars O = rev(series(priceOpen())),
    H = rev(series(priceHigh())),
    L = rev(series(priceLow())),
    C = rev(series(priceClose()));
    
  if(!is(LOOKBACK)) {
// send the last 200 candles to R
    Rset("Open",O,Size);
    Rset("High",H,Size);
    Rset("Low",L,Size);
    Rset("Close",C,Size);

// let R compute the signal
    var Signal = Rd("Compute(Open,High,Low,Close)");
    if(!RCheck()) return;
    
    if(Signal > 0 && !NumOpenLong)
      enterLong();
    if(Signal < 0 && !NumOpenShort)
      enterShort();
  }
}
// export historical price data to R
string name = "Data\\Export.csv";

function run()
{
  BarPeriod = 60;
  StartDate = 20140101;

  if(is(INITRUN)) // write the header
    file_write(name,"Date, Open, High, Low, Close",0);
  else
    file_append(name,strf(
      "\n%04i-%02i-%02i %02i:%02i, %.5f, %.5f, %.5f, %.5f",
      year(),month(),day(),hour(),minute(),
      priceOpen(),priceHigh(),priceLow(),priceClose()));
}

/* in R:
> Data <- read.csv('C:/Projects/Zorro/Data/export.csv') # mind the forward slashes
> plot(Data$Close)
> ...
*/

See also:

Code conversion, DLL interface, advise

► latest version online