MQL4 Custom Indicator EA Example
In the previous article, we walked you through the process of converting a custom indicator into an iCustom function as a necessary first step before it can be deployed in an expert advisor. We defined the 6 different parameters of an iCustom function, paying particular attention to the last three: Indicator Parameters, Mode, and Shift.
We used the example of converting a complicated custom indicator, the NonLagMA_7.1, into an iCustom indicator function, and we walked you through the deductive discovery process of finding its Indicator Parameters and Mode.
In this MQL4 Custom Indicator EA Example article we will continue to use the example of the NonLagMA_7.1, and explore the different ways of weaving the iCustom function into different expert advisors. If you have forgotten or have not seen what a NonLagMA custom indicator looks like, here is a screenshot:
Previously, when discussing the detective work in discovering the mode parameter (lines/signals) of the iCustom function, I pointed out that that the data table highlighted in red provides the visual clues. We deduced that the NonLagMA is the first mode (mode=0) represented by the line itself, Up is the second mode (mode =1) represented by the the blue line, and Dn is the third mode (mode = 2) represented by the red line. Not visually represented here is the fourth mode of Trend (mode = 3), but it is represented in the code itself, with the logic being that if trend == 1, trend is up, if trend = -1, trend is down.
Now what you roughly know the four modes of the NonLagMA custom indicator, you can create at least three types of expert advisors based on the different modes:
- EA that works with the MA line itself (Mode=0), as in a crossover.
- EA that works with the Up Blue Line (Mode=1) and Dn Red Line (Mode=2), taking buys when the NonLagMA turns blue and taking sells when it turns red.
- EA that works with the Trend signal (Mode=3), buy when trend is up, sell when trend is down.
All three EAs will share same extern variables below:
extern int Length = 150;
extern int Displace = 0; //DispLace or Shift
extern double PctFilter = 0; //Dynamic filter in decimal
extern int Color = 1; //Switch of Color mode (1-color)
extern int ColorBarBack = 1; //Bar back for color mode
extern double Deviation = 0; //Up/down deviation
extern int AlertMode = 0; //Sound Alert switch (0-off,1-on)
extern int WarningMode = 0; //Sound Warning switch(0-off,1-on)
extern int Shift = 1;
I went over the process of discovering the above indicator parameters in the previous article, but I will recap. The easiest way was to copy and paste the extern variables from the indicator source code over to the expert advisor, and then to populate the iCustom function indicator with the above identifiers, letting them fall AFTER the third parameter (the indicator name) and BEFORE the last two parameters (the mode and shift).
Thus, you would be converting your iCustom indicator from this:
Note: While this particular indicator has 9 indicator parameters, it should be pointed out that the most important one is the Length. Just like the moving average, changing the length changes the fundamental structure of the NonLagMA. The other parameters can be left at the default value of 0.
NonLagMA EA #1: Working with the MA line signal (mode = 0)
|Intent||//Buy: when close crosses over NonLagMA|
//Sell: when close crosses under NonLagMA
|double macurrent = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,Length,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 0,Shift).|
double maprevious = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 0,Shift+1).
double close_current = iClose (NULL,0,Shift);
|BuyCond||if (close_current >= macurrent && close_previous <= maprevious)|
|SellCond||if (close_current <= macurrent && close_previous >= maprevious)|
There is not much to explain here. We are using this NonLagMA crossover in much the same way as we conducted a MA crossover. One could represent a fast NonLagMA crossing over/under a slow NonLagMA, but for illustration purposes, I just represented the current close crossing under/over the NonLagMA. The end result will be more or less similar.
In indicator calling, notice that mode parameter of my iCustom indicator functions (the second from last), is set to 0. As we have seen above, 0 refers to the NonLagMA line itself.
Notice that when I represent current close and previous close I use the iClose function. The iClose function is useful if you wanted to work with the closing price of a different time frame, currency symbol, or shift value. If you worked with Close or Bid, you are referring to only current price of the current symbol. In my case, I want to work with a different shift value, the current close (Shift) and the previous close (Shift+1), and so I needed to construct a variable called close_current = iClose (NULL,0,Shift) and a variable called close_previous = iClose (NULL,0,Shift+1).
NonLagMA EA #2: Blue UP and Red Dn Color Change (Mode 1 and 3)
|NonLagMA Line Color Change|
|Intent||//Buy: when current line is up and blue and previous line is down and red|
//Sell: when current line is down and red and previous line is up and blue
|double buy_macurrent = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 1,Shift).|
double buy_maprevious = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 1,Shift+1).
double sell_macurrent = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 2,Shift).
double sell_maprevious = iCustom(NULL, 0, “NonLagMA_v7.1”,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 2,Shift+1).
|BuyCond||if (sell_maprevious!=EMPTY_VALUE && sell_macurrent==EMPTY_VALUE && buy_macurrent!=EMPTY_VALUE)|
|SellCond||if(buy_maprevious!=EMPTY_VALUE && buy_macurrrent==EMPTY_VALUE && sell_macurrent!=EMPTY_VALUE)|
In the indicator calling section, you will see that created variables for a buy_ma (the blue line) and sell_ma (the red line), and made a current and previous version of each by setting a different in the last parameter, the Shift: current (Shift) and previous (Shift+1). What distinguishes the buy_ma versus the sell_ma is the second to last parameter, the mode parameter. The buy_ma has a mode of 1, which as we have discovered, is the blue (UP) line, and the sell_ma has a mode of 2, which as we have discovered, is the red (Dn) line.
When you see the entry conditions, the first thing that might strike you as odd is these EMPTY_VALUE words and exclamation marks. You would be scratching your head wondering what I am doing with all that EMPTY_VALUE.
Well, internally, in geek-speak, EMPTY_VALUE refers to a function:
This function sets the drawing line to an empty value. Empty values are not drawn or shown in the DataWindow. By default, empty value is EMPTY_VALUE.
In plain English, EMPTY_VALUE is when the data window shows nothing for that Line / Signal/ Arrow. In the case of the NonLagMA, whenever the line is blue, the UP row in the data window shows the indicator data value, and at the same time the Dn row in the data window shows nothing, empty value. Conversely, whenever the line is red, the Dn row in the data window shows the indicator data value, and at the same time the Up row shows nothing, empty value.
Now, when we say that buy_macurrent = EMPTY_VALUE, we are trying to say that we do not want the blue line at all (we want it to be empty of value). If we say buy_macurrent! = EMPTY_VALUE, the exclamation mark (!) indicates “DO NOT WANT”; thus, we do not want the blue line to be empty of value, or, to put it another way, we want the blue line to be represented, to have value.
If we look at the buy condition in plain English, we are saying: we are going to buy when the previous red line did exist (sell_maprevious!=EMPTY_VALUE) and now it does not (sell_macurrent=EMPTY_VALUE) and instead the blue line exists (buy_macurrent!=EMPTY_VALUE).
Conversely, with the sell condition we are saying: we are going to buy when the previous blue line did exist (buy_maprevious!=EMPTY_VALUE) and now it does not (buy_macurrent=EMPTY_VALUE) and instead the red line exists (sell_macurrent!=EMPTY_VALUE).
NonLagMA EA #3: Trend Change (Mode 4)
|Intent||//Buy: when current trend is up and previous trend is down|
//Sell: when current trend is up and previous trend is down
|double trend_macurrent = iCustom(NULL, 0,”NonLagMA_v7.1″,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 3,Shift).|
double trend_maprevious = iCustom(NULL, 0, NonLagMA_v7.1″,Price,FastLen,Displace, PctFilter, Color, ColorBarBack, Deviation, AlertMode, WarningMode, 3,Shift+1).
|BuyCond||if (trend_macurrent==1 && trend_maprevious==-1)|
|SellCond||if (trend_macurrent==-1 && trend_maprevious==1)|
The difference between the trend_ma and the previous types versions in the above two EAs is the second to last parameter, the mode. The mode is 3, which as we have discovered, refers to the trend signal. The trend signal does not appear in the data window, like the previous modes, but it does appear in the code of the indicator:
if (MABuffer[shift]-MABuffer[shift+1] > Filter) trend[shift]= 1;
if (MABuffer[shift+1]-MABuffer[shift] > Filter) trend[shift]=-1;
The code calculates how the trend is formed. In plain English, if trend = 1, then the trend is long, and if the trend = -1, the trend is short.
To put the above into an entry condition is very simple. For a buy condition, I just need to say that I wanted the current trend to be up (trend_current==1) and previous trend to be down (trend_previous==-1). For sell condition, I just needed to say that I wanted the current trend to be down (trend_current==-1) and the previous trend to be up (trend_previous==1).