Trader’s Tech – Writing Your Own EA Part 41 – EA Mods

Forex Robot

If you’re new to this series and want to check it out from the beginning, you can find that here. And look here for a list of all the programming articles.

In Part 40 we wrapped up our discussion of test data for the Strategy Tester. Since I promised further refinements to our EA in this installment, let’s change make a couple of changes. Firstly, you know how frustrating it is to want to change the time frame on the chart and to be afraid that changing the time frame might trigger a trade. So, let’s tie the crossover to a specific time frame of our choosing. Secondly, having fixed SLPips and TPPips doesn’t allow very much versatility in terms of using our EA for different pairs and time frames. So, let’s change our SLPips and TPPips to reflect the Average True Range of our trigger time frame.

To start, we need to add external variables for our trigger time frame and our ATR.

extern int TriggerTF=240;
extern bool UseATR=true;
extern int ATRTF=1440;
extern int ATRBars=100;
extern double ATRSLFactor=0.5;
extern double ATRTPFactor=1.0;

TriggerTF – int – this is the time frame we will use to trigger the trades. The value must be one of the standard time frame values (1, 5, 15, 30, 60, 240, 1440, 10080, 43200) or 0 for the chart time frame. Just to clarify, MQL4 uses the word period and the term time frame interchangeably. I try to stick to the term time frame for consistency.

UseATR – bool – this will determine whether we use ATR or SLPips and TPPips for our stop loss and target.

ATRTF – int – the time frame for our ATR. Again, the value must be one of the standard time frame values.

ATRBars – int – the number of bars to average into the ATR.

ATRSLFactor – double – ATR multiplication factor for our SL. In other words, 0.5 in this variable means we will use ATR * 0.5 as our SL.

ATRTPFactor – double – ATR multiplication factor for our TP.

Our next modification is in the start() function. We must modify the

CrossOver = MAXover(MOD_SMA,MA1,MS2,0,0);

line. And this brings us to our first annoyance. We (read that as I) didn’t have the foresight when writing the MAXover() function to give it a variable time frame capability. So we must start by modifying that include file. There are several ways to go about this. If we haven’t used the MAXover() function in any other EAs, we can make the change the right way:

 

//+------------------------------------------------------------------+
//|                                                      MAXover.mq4 |
//|                          Copyright © 2010, T Black & Associates. |
//|                                    http://www.winnersedgetrading.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, T Black and Associates"
#property link "http://www.winnersedgetrading.com"

//MAXover() - return -1 for bearish cross, 1 for bullish cross, 0 for no cross
//MAtype 0=sma, 1=ema
//MAPer1 first moving average Period
//MAPer2 second moving average Period
//LookBack how many candles to look back for another cross
//MultiXMaxX how many crosses are acceptable in the look back
int MAXover(int MAType,int TF,int MAPer1,int MAPer2,int LookBack,int MultiXMaxX)
   {
   int  XOver=0;      //-1=bearish cross, 0=no cross, 1=bullish cross
   double MA1_CurrVal,MA2_CurrVal;
   double MA1_PrevVal,MA2_PrevVal;
   double MA1_LookBackVal,MA2_LookBackVal;
   int  CurrLoc=0;   //-1 = below both, 0=between, 1 = above both
   int  PrevLoc=0;
   int  LookBackLoc=0;
   int  i;
   int XCount;

   //assign the vars
   MA1_CurrVal = iMA(NULL,TF,MAPer1,0,MAType,PRICE_CLOSE,1); //most recently closed candle
   MA2_CurrVal = iMA(NULL,TF,MAPer2,0,MAType,PRICE_CLOSE,1);
   MA1_PrevVal = iMA(NULL,TF,MAPer1,0,MAType,PRICE_CLOSE,2); //1st prior to most recently closed candle
   MA2_PrevVal = iMA(NULL,TF,MAPer2,0,MAType,PRICE_CLOSE,2);

   //are we above?
   if(MA1_CurrVal > MA2_CurrVal) //yes we're above
      CurrLoc=1;
   else if(MA1_CurrVal < MA2_CurrVal) //No, below              
      CurrLoc=-1;        
   else              
      CurrLoc=0;                        
   //Were we previously above        
   if(MA1_PrevVal > MA2_PrevVal) //yes we're above
      PrevLoc=1;
   else if(MA1_PrevVal < MA2_PrevVal) //no, below              
      PrevLoc=-1;        
   else              
      PrevLoc=0;                 
   //cross?        
   if(PrevLoc == -1 && CurrLoc == 1)              
      XOver = 1;        
   else if(PrevLoc == 1 && CurrLoc == -1)              
      XOver = -1;        
   else              
      XOver = 0;               
   if(XOver != 0 && LookBack > 0) //check the lookbacks for no XOver - MA must be on same side for last "lookback" bars
      {
      XCount=0;
      for(i=3;i<LookBack+3;i++)                    
         {                    
         MA1_LookBackVal = iMA(NULL,0,MAPer1,0,MAType,PRICE_CLOSE,i);                    
         MA2_LookBackVal = iMA(NULL,0,MAPer2,0,MAType,PRICE_CLOSE,i);                              
         if(MA1_LookBackVal > MA2_LookBackVal)
            LookBackLoc = 1;
         else if(MA1_LookBackVal < MA2_LookBackVal) //No, below
            LookBackLoc=-1;
         else
            LookBackLoc=0;

         if(PrevLoc != LookBackLoc)
            {
            XCount++;
            } // if(PrevLoc != LookBackLoc)
         } // for(i=3;i<LookBack+3;i++)          if(XCount>MultiXMaxX)
            XOver=0;
      } // if(XOver !=0)

   return(XOver);

}
All we did was add the:

int TF

to the parameter list and change the iMA() assignments from 0 to TF:

   MA1_CurrVal = iMA(NULL,TF,MAPer1,0,MAType,PRICE_CLOSE,1); //most recently closed candle
   MA2_CurrVal = iMA(NULL,TF,MAPer2,0,MAType,PRICE_CLOSE,1);
   MA1_PrevVal = iMA(NULL,TF,MAPer1,0,MAType,PRICE_CLOSE,2); //1st prior to most recently closed candle
   MA2_PrevVal = iMA(NULL,TF,MAPer2,0,MAType,PRICE_CLOSE,2);

We can still assign 0 to the TF parameter if we want to use the current chart time frame.

But, what if we’ve already used this include file in other EAs? We can add

int TF=0

to the end of the parameter list. That way previous uses of the MAXover() include file will be unaffected. What we’ve done is caused the parameter list to default to 0 for any parameter that is not included when calling the function.

As you may already know, I prefer to do things the right way, but sometimes expediency indicates that we must use workarounds. Just know that either method will work but for this series, we’ll do it the former way.

Now, the line in our start() function will look like this:

CrossOver = MAXover(MOD_SMA,TriggerTF,MA1,MS2,0,0);

And that will use the TriggerTF external variable for the crossover time frame.
That will do it for today (and this week.) Have a great weekend.
Thanks for your attention and please follow me on Twitter and LinkedIn.

Tim

 

here_for_you_001

1359774937_facebook 1359774984_linkedin 1359774949_twitter 1359774960_google 1359774973_rss 1360027635_youtube

Connect_With_Winners_Edge

Get trade set ups everyday!

Follow our social media:
1359774937_facebook 1359774984_linkedin 1359774949_twitter 1359774960_google 1359774973_rss 1360027635_youtube

Winner’s Edge Trading, as seen on:

Winner's Edge Trading in the news