The case for Fuzzy Logic in Trading - Pt. 2: Amibroker

Backtesting Fuzzy Logic in Amibroker

In pt.1 we backtested a "fuzzified" trading strategy in Matlab (read part 1):

Buy when RSI(3) is Low and it's before Expiration week.

Although it was easy to develop this fuzzy model in Matlab, due to the intuitive GUI, it is difficult to get meaningful backtest results, visual signals, statistics and, of course, portfolio level backtesting. Everything is possible in Matlab but it takes considerable time and effort. I would rather backtest in Amibroker and get all my usual statistics, equity curves, visual arrows, as well as 1 click portfolio backtesting.

So how do we code this in Amibroker?

Again here's the basic idea:

You can say buy when RSI(3)<25
Or you can say Buy when  RSI(3)  is fairly Low
You can say Buy on Monday of Expiration Week
Or Buy around the middle of the month.

I will be using some custom functions I developed:

//Let's keep these for reference
 indicators = "rsi3,Day_M";
Property_ind1 = "Low,Neutral,High";
Property_ind2 = "EarlyMonth,AroundExpirationWeek,EndMonth";

Output = "Action";
Property_Action = "Buy,Hold,Sell";

  RSI3 = RSI( 3 ); //0-100
  Day_M = Day(); //1-31

 SetMember(  "rsi3", "Low", TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
 SetMember(  "rsi3", "Neutral", TRIMember( rsi3, 10, 50, 90 ) );
 SetMember(  "rsi3", "High", TRIMember( rsi3, 60, 100, 140 )  );

 SetMember( "Day_M", "EarlyMonth",  GaussMember( Day_M, 5.27, -0.164 )  );
 SetMember( "Day_M", "AroundExpirationWeek",  GaussMember( Day_M, 3.94, 15.83 ) );
 SetMember( "Day_M", "EndMonth", GaussMember( Day_M, 5.266, 31) );

Now, these are custom functions:
SetMember() creates an array named "rsi3Low", and fills it with values from TRIMember() function.
TRIMember() function "transforms" the RSI(3) values to a membership function [0 1] of 'Low" Rsi.
If the above make no sense, don't worry, it's much easier than you think.

Now, how did these numbers come up: TRIMember( rsi3, -40.5, 0.475, 40.34 ).
Well if you look at the Matlab membership function we created in the last post, these are the numbers under "parameters".

In other words   
SetMember(  "rsi3", "Low", TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
 SetMember(  "rsi3", "Neutral", TRIMember( rsi3, 10, 50, 90 ) );
 SetMember(  "rsi3", "High", TRIMember( rsi3, 60, 100, 140 )  );

is basically this:



and


 SetMember( "Day_M", "EarlyMonth",  GaussMember( Day_M, 5.27, -0.164 )  );
 SetMember( "Day_M", "AroundExpirationWeek",  GaussMember( Day_M, 3.94, 15.83 ) );
 SetMember( "Day_M", "EndMonth", GaussMember( Day_M, 5.266, 31) );
is this:


So now we'll use two more custom functions that create the rules
1. FuzzyAndInf() - Stands for Fuzzy "AND" inference
2.FuzzyInf()


   FuzzyAndInf( 0, "rsi3", "Low", "Day_M", "AroundExpirationWeek", "Action", 1 );
   FuzzyAndInf( 1, "rsi3", "High", "Day_M", "EarlyMonth", "Action", -1 );
   FuzzyInf(    2, "rsi3", "High" , "Action", -1 );


that roughly corresponds to these statements:
If RSI(3) is Low and it's AroundExpirationWeek then Action is Buy 
If RSI(3) is High and it's  EarlyMonth  then Action is Sell
If RSI(3) is High then Sell




Then we have to weight the rules and defuzzify. Here  I will simplify things since I cannot yet code a proper output membership function and de-fuzzify algorithm (help would be appreciated from math inclined people...).

Anyways, here are the reults. Remember this is a very simple concept of low RSI and expiration week positive bias...

1. SPY from 1995-August 2012
2. $0.006 commission per trade
3. Start with 100,000. Long only


Profit = 1359462.71 (1359.46%),
CAR = 16.37%,
MaxSysDD = -358582.04 (-43.88%),
CAR/MDD = 0.37,
# winners = 363 (68.75%),
 # losers = 165 (31.25%)







So here's the whole code:


 indicators = "rsi3,Day_M";
Property_ind1 = "Low,Neutral,High";
Property_ind2 = "EarlyMonth,AroundExpirationWeek,EndMonth";
Output = "Action";
Property_Action = "Buy,Hold,Sell";

    RSI3 = RSI( 3 ); //0-100
    Day_M = Day(); //1-31

    SetMember(  "rsi3", "Low", TRIMember( rsi3, -40.5, 0.475, 40.34 ) );
    SetMember(  "rsi3", "Neutral", TRIMember( rsi3, 10, 50, 90 ) );
    SetMember(  "rsi3", "High", TRIMember( rsi3, 60, 100, 140 )  );

    SetMember( "Day_M", "EarlyMonth",  GaussMember( Day_M, 5.27, -0.164 )  );
    SetMember( "Day_M", "AroundExpirationWeek",  GaussMember( Day_M, 3.94, 15.83 ) );
    SetMember( "Day_M", "EndMonth", GaussMember( Day_M, 5.266, 31) );

    FuzzyAndInf( 0, "rsi3", "Low", "Day_M", "AroundExpirationWeek", "Action", 1 );
  FuzzyAndInf( 1, "rsi3", "High", "Day_M", "EarlyMonth", "Action", -1 );
    FuzzyInf(    2, "rsi3", "High" , "Action", -1 );
//FuzzyAndInf( 3, "rsi3", "Low", "Day_M", "EndMonth", "Action", 0 );

   weight=0;
    weight[0]=Param( "w0", 1, 0.1, 1, 0.1 );
    weight[1]=Param( "w1", 1, 0.1, 1, 0.1 );
    weight[2]=Param( "w2", 1, 0.1, 1, 0.1 );
   // weight[3]=Param( "w3", 1, 0.1, 1, 0.1 );

 Sellout = Holdout = Buyout = 0;

    for ( k = 0;k <= 2;k++ )
    {
        Buyout = Buyout +( Nz( getRuleRes( 1, k ) ) ) * weight[k];
        Holdout = Holdout +( Nz( getRuleRes( 0, k ) ) ) * weight[k];
        Sellout = Sellout + (Nz( getRuleRes( -1, k ) ) )* weight[k];
    }

    decision = ( 0 * Sellout + 0.5 * Holdout + 1 * Buyout ) / ( Sellout + Holdout + Buyout );
   decision=IIf( ( Sellout + Holdout + Buyout )==0,0 ,decision );

//Plot(decision,"decision",colorRed);

Buy=decision>0.5;
Sell=decision<0.5;

Labels: , , , , , , ,