AmiBroker RMath Demo R_SMA_01.p2

AFL and other code for AmiBroker
User avatar
progster
Posts: 948
Joined: Thu Jul 26, 2007 7:20 pm
Contact:

AmiBroker RMath Demo R_SMA_01.p2

Postby progster » Fri May 07, 2010 6:08 pm

The RMath Plugin for AmiBroker, graciously provided by Patrick for registered AB users in the AmiBroker.com Member Area, joins the world of R processing to the world of AmiBroker.

R is a free software environment for statistical computing and graphics, and adding the capabilities of R to those of AmiBroker creates a powerful combination indeed.

The RMath Plugin does the heavy lifting for programmatic cross-communication, but there remains a great deal of concept and practice for the new AB/R user to master.

As I climb this learning curve, I will post along the way as time permits tests, demos, and illustrations that may be of assistance to others beginning this journey.

Here is the first.

R_SMA_01.p2.jpg

R_SMA_01.p2 by Progster

Calculate SMA in R by using package:TTR .

This code demonstrates:

Doing a calculation in R and returning it for display in a plot or Exploration

Selecting an array from an R-side Matrix result for return to AB

Saving the R workspace so that all R-side variables can later be examined

Building R command strings based on AB parameters

You are allowed to bypass all calls to R by setting DoRStuff to N.
This allows inspection of native-only Close and MA for confidence building.

Thanks to Patrick who noted key concepts and provided corrected code!

This test worked with:

AB 5.3
RAndFriendsSetup2092V3.0-17-2.exe: R 2.9.2, statconnDCOM 3.1-2B6
RMath 1.0.0 per Tools -> Plug-ins ...

Note: package:TTR must be installed separately

After experimentation, use the Parameter Reset button to return to "correct" default values


I encourage others to post here their AB/R related code as well. Cheers!

Code: Select all

/*
   R_SMA_01.p2         by Progster

   Calculate SMA in R by using package:TTR .

   This code demonstrates:

      Doing a calculation in R and returning it for display in a plot or Exploration
   
      Selecting an array from an R-side Matrix result for return to AB
   
      Saving the R workspace so that all R-side variables can later be examined
   
      Building R command strings based on AB parameters

   You are allowed to bypass all calls to R by setting DoRStuff to N.
   This allows inspection of native-only Close and MA for confidence building.

   Thanks to Patrick who noted key concepts and provided corrected code!

   This test worked with:

   AB 5.3
   RAndFriendsSetup2092V3.0-17-2.exe:  R 2.9.2, statconnDCOM 3.1-2B6
   RMath 1.0.0      per Tools -> Plug-ins ...

   Note:  package:TTR must be installed separately

   After experimentation, use the Parameter Reset button to return to "correct" default values

*/

//   Uncomment to turn QuickAFL OFF
//   Many of the displayed numbers will not seem intuitive if QuickAFL is on.
//   Alignment issue can appear if QuickAFL is on.
//   So, to "get on with it" in the simplest fashion, turn QuickAFL OFF when working with R
SetBarsRequired( sbrAll, sbrAll );      

//   Parameter settings
PlotCandles = ParamToggle( "PlotCandles", "N|Y", 1 ) ;
PlotNativeMA = ParamToggle( "PlotNativeMA", "N|Y", 1 ) ;

MA_Length = Param( "MA_Length", 20, 1, 50, 1 ) ;

DoRStuff = ParamToggle( "DoRStuff", "N|Y", 1 ) ;

PlotRClose = ParamToggle( "PlotRClose", "N|Y", 1 ) ;
AddToRClose = Param( "AddToRClose", 0, -200, 200, 1 ) ;
RCloseShift = Param( "RCloseShift", 0, -20, 20, 1 ) ;
RMAShift = Param( "RMAShift", 0, -20, 20, 1 ) ;
ExplorationShift = Param( "ExplorationShift", 0, -20, 20, 1 ) ;

Save_R_Workspace = ParamToggle( "Save_R_Workspace", "N|Y", 0 ) ;

//   Load needed non-default R libraries
if( DoRStuff ){
   EnableTextOutput( False ) ;
   RMathDebugOn() ;
   RMathProcedure( "library( TTR )" ) ;            //   package:TTR   (Technical Trading Rules)
   RMathProcedure( "library( fSeries )" ) ;      //   package:fSeries
   RMathDebugOff() ;
}

//   Build R command strings
Close_RStr = "MyClose <- MyClose + " + NumToStr(AddToRClose, 1.0)  ;
printf( "Close_RStr:  " + Close_RStr + "\n" ) ;            //   e.g.  MyClose <- MyClose + 0

//   Dynamically build the R command string to calculate the specified SMA
MA_RStr = "MyMA <- SMA( MyClose, " + NumToStr(MA_Length, 1.0) + ")" ;
printf( "MA_RStr:      " + MA_RStr + "\n" ) ;            //   e.g.  MyMA <- SMA(MyClose, 20)

//   Do R-side calculations
if( DoRStuff ){

   RMathSetArray(Close, "MyClose" ) ;                     //   send AB Close array to R
   
   // To prove changes can be made on R side, and then returned
   //   RMathProcedure( " MyClose <- MyClose + 1 " ) ;      //   not dynamic

   //   default Close_RStr:  "MyClose <- MyClose + 0" 
   RMathProcedure( Close_RStr ) ;   
   
   //   These work but they are are not dynamic
   //   RMathProcedure( " MyMA <- SMA(MyClose) " ) ;       // works on R side, per examination of saved workspace
   //   RMathProcedure( " MyMA <- SMA(MyClose, 3) " ) ;    // works on R side, per examination of saved workspace
   
   //   Dynamic MA calc in R, varies per MA_Length parameter.
   //   default MA_RStr:  "MyMA <- SMA(MyClose, 20)"
   //   Note: MyMA is not an Array, it is a Matrix! (that's the TTR package implementation)
   RMathProcedure( MA_RStr ) ;       // works on R side, per examination of saved workspace
   

   //   IMPORTANT:   Nothing will come out right if you attempt to pass back NA values from R to AB!
   //   One way to fix this is shown here, using substituteNA()

   //   Deal with R-side NA values   
   RMathProcedure( " MA_Clean <- substituteNA(MyMA, type = <DQ>zeros<DQ>) " ) ;      //   substitution to new name OK
   
   RMathProcedure( " MyMA <- substituteNA(MyMA, type = <DQ>zeros<DQ>) " ) ;         //   self-substitution also OK
}

//   RMathDebugOn() ;
bi = BarIndex() ;         //   0 to (N - 1)

//   from 1 to N, this is the one that will match the crosshairs, PROVIDED QuickAFL is OFF
bn = bi + 1 ;   

arrayitem = SelectedValue( bi ) - bi[ 0 ];
printf( "Close at selected bar:" + NumToStr( Close[ arrayitem ], 1.2 ) + "\n" ) ;

LBI = LastValue( bi ) ;
SBI = SelectedValue( bi ) ;
SBN = SelectedValue( bn ) ;
FVB = Status("firstvisiblebar");
LVB = Status("lastvisiblebar");
LVBI = Status("lastvisiblebarindex");      //   note:  case matters!
BTR = LBI - LVBI  ;   //   actual bars to the Right of selected bar

EnableTextOutput( True ) ;
printf( "\n" + "The following numbers make obvious sense only if QuickAFL is OFF : \n" ) ;
printf( "LBI: " + NumToStr(LBI, 1.0) + "\n" ) ;
printf( "BarCount: " + NumToStr(BarCount, 1.0) + "\n" ) ;
printf( "SBI: " + NumToStr(SBI, 1.0) + "\n" ) ;      //   Selected Bar Index
printf( "SBN: " + NumToStr(SBN, 1.0) + "\n" ) ;      //   Selected Bar Number
printf( "FVB: " + NumToStr(FVB, 1.0) + "\n" ) ;
printf( "LVB: " + NumToStr(LVB, 1.0) + "\n" ) ;
printf( "LVBI: " + NumToStr(LVBI, 1.0) + "\n" ) ;
printf( "BTR: " + NumToStr(BTR, 1.0 ) + "\n\n" ) ;
EnableTextOutput( False ) ;

//   Return R-side calculations to AB
if( DoRStuff ){

   rtnClose = RMathGetArray( "MyClose" ) ;

   //   rtnMA = RMathGetArray( "MyMA" ) ;            //   bogus call!  MyMA is a Matrix, not an array!

   /*
   RMathDebugOn() ;
   RMathProcedure( " class(MyMA) " ) ;            //   display the R type of MyMA in the RMath debug window
   RMathDebugOff() ;
   */

   rtnMA = RMathGetArray( "MyMA[,1]" ) ;            //   NOTE: Matrix notation !!!
   rtnClean = RMathGetArray( "MA_Clean[,1]" ) ;      //   NOTE: Matrix notation !!!

}

//   Optionally save the R workspace image.
//   If saved, you can later reopen it in an interactive session of R and examine everything.
if(Save_R_Workspace){
   RMathDebugOn() ;
   //   Set desired output directory
   RMathProcedure( "  setwd( <DQ>C:/Users/Steve/Documents<DQ> )  " ) ;
   //   Save the workspace to specified file in the cwd
   RMathProcedure( " save.image( file=<DQ>R_SMA_01.p2.Rdata<DQ>) " ) ;      //   works!
   RMathDebugOff() ;
}

if(PlotCandles == 1)
   Plot( Close, "Candle Close", colorGrey50, styleCandle, 0, 0, 0, 0 ) ;

if(PlotNativeMA == 1)
   Plot( MA(Close, MA_Length), "NativeMA", colorWhite, styleLine, 0, 0, 0, 7 ) ;

if( DoRStuff ){

   if(PlotRClose){
      //   Plot( rtnClose, "rtnClose", colorWhite, styleLine, 0, 0, 0, 8 ) ;                     //   Zorder of 8 puts this on top
      Plot( Ref(rtnClose, RCloseShift ), "rtnClose", colorWhite, styleLine, 0, 0, 0, 8 ) ;      //   Zorder of 8 puts this on top
   }   
   
   Plot(Ref(rtnMA, RMAShift), "rtnMA", colorRed, styleDashed, 0, 0, 0, 8 ) ;
   //   Hack to prevent plot of leading zeros which are really NA (but affects all zeros!)
   //   Plot(IIf( Ref(rtnMA, RMAShift) != 0, Ref(rtnMA, RMAShift), Null ), "rtnMA", colorRed, styleDashed, 0, 0, 0, 8 ) ;
   
   //   Plot(Ref(rtnClean, RMAShift), "rtnClean", colorYellow, styleDashed, 0, 0, 0, 8 ) ;
   //   Hack to prevent plot of leading zeros which are really NA (but affects all zeros!)
   Plot(IIf( Ref(rtnClean, RMAShift) != 0, Ref(rtnClean, RMAShift), Null ), "rtnClean", colorYellow, styleDashed, 0, 0, 0, 8 ) ;
}

EnableTextOutput( True ) ;
printf( "Close: " + NumToStr(Close, 6.2 ) + "\n" ) ;
if( DoRStuff ) printf( "rtnMA: " + NumToStr(rtnMA, 6.2 ) + "\n" ) ;
EnableTextOutput( False ) ;

//   Show all results in the Exploration
Filter = 1 ;

AddColumn( Close, "Close" ) ;

if( DoRStuff ){
   AddColumn( rtnClose, "rtnClose" ) ;

   //   Seems correct at ExplorationShift = 0
   AddColumn( Ref(rtnMA, ExplorationShift), "rtnMA" ) ;
   AddColumn( Ref(rtnClean, ExplorationShift), "rtnClean" ) ;

}
You do not have the required permissions to view the files attached to this post.

pcavatore
Posts: 2
Joined: Tue May 06, 2008 9:23 pm
Contact:

Re: AmiBroker RMath Demo R_SMA_01.p2

Postby pcavatore » Fri May 14, 2010 8:41 am

As per my post on AB newsletter
http://finance.groups.yahoo.com/group/a ... age/149370
-----------------------------------------------------------------------------------
Glad to see more posts on RMath-plug-in...this is a long overdue task on my to
do list. Hopefully I will get some hints from here.

2 thinks I'm struggling to accomplish with it are:

-send the investable universe - let's say a wathclist - to R which calculate a
sub-universe and send it back to AB for further backtesting (something like
every months I get a new investable universe - based on some calculation - which
is then used within the backtest together with some buy/sell rules)

-send historical metrics - like 1year sharpe ratio - for selected strategies to
R which filter them based on some statistical filter and send the historical
passing strategies and signals back to AB for final backtesting using the active
strategies for every data point in history

Any thoughts about that?

Paolo

User avatar
progster
Posts: 948
Joined: Thu Jul 26, 2007 7:20 pm
Contact:

Re: AmiBroker RMath Demo R_SMA_01.p2

Postby progster » Sat May 15, 2010 2:34 pm

Paolo,

Speaking for myself, I'm just getting started with the AB/R connection. Not
being a previous R user, I have much to learn about R and I'm studying and
experimenting as time is available.

Eventually, I hope to reach the inflection point and make this combination
really productive for analysis, as I have no doubt it can be.

As I proceed I hope to capture and post successful steps in a series of demos,
and I encourage you or anyone to do the same. Anything that's attempted,
puzzled over, and then eventually solved (over hours or days) is valuable to
share even if it seems simple/trivial after-the-fact.

If there are enough participants interested in using AB/R to even muster a few
shared working examples each month, progress will be much faster for all of us,
IMO.

So, sorry I can't offer direct thoughts on your goal(s) at this point, because
I'm not there yet. Eventually though ...

Glad to hear of your interest here, thanks for writing.

- Progster

User avatar
progster
Posts: 948
Joined: Thu Jul 26, 2007 7:20 pm
Contact:

Re: AmiBroker RMath Demo R_SMA_01.p2

Postby progster » Sat May 15, 2010 2:41 pm

Currently, I'm trying to get to the point of choosing a time-series class, loading and saving files to/from it interactively, and then creating the class objects with data passed from AB.

I'm finding all the R docs to be very terse, with no diagrams and minimal examples. This area is thus very slow going for me right now.

I'd like to be able to load a file like this one:

Code: Select all

Date,Time,Open,High,Low,Close,Up,Down
05/02/2001,0030,421.20,421.20,421.20,421.20,11,0
05/02/2001,0130,421.20,421.40,421.20,421.40,7,0
05/02/2001,0200,421.30,421.30,421.30,421.30,0,5
05/02/2001,0230,421.60,421.60,421.50,421.50,26,1

into zoo, and have both the dates and times become part of the index.

This line will give me an index based on dates only (thus a non-unique index, not good):

z <- read.zoo("foo_hs.csv", format = "%m/%d/%Y", sep=",", header = TRUE )

So far, getting the time to be part of the index has eluded me.

This is probably slightly off-topic wrt. AB/R, as we have no requirement to use separate date and time columns when dealing with quotes sourced from AB. Nevertheless, a file format like the above is very common and I'm hoping to be able to load such into R as a starting point for experiments.


Return to “AmiBroker Code”

Who is online

Users browsing this forum: No registered users and 0 guests