Trader’s Tech – Writing Your Own EA Part 14 – Functions

Forex RobotCasey and Nathan are working my tail off here in Latrobe. We’re coming up with some awesome new strategy ideas that we’re coding into EAs for testing. Keep watching for some great new stuff here at Winner’s Edge over the next few months.

If you’re new to this series and want to check it out from the beginning, you can find that here.

In Part 13, we discussed a few MQL4 concepts and developed the function to determine if there is already an  open trade – IsThereAnOpenTrade(). In this part, we’ll be moving right along with developing our functions. Our next function is IsThereACrossover(). This will return an int (integer) value or 0 if there is no crossover, 1 if the first moving average crosses up over the second moving average and -1 if the first moving average crosses down over the second.  So we’ll start with our initial function structure:

int IsThereACrossover()
    {
    int CrossOver=false;
    double currMA1, currMA2;
    double priorMA1, priorMA2;
    int currLoc, priorLoc;

    return(CrossOver);
    }

As with our prior function, I have created the variable named CrossOver to keep track of the return value of the function. I’ve initialized it with false so all we’ve got to do is change it to true if we actually find a crossover. Again note that we have preceded the function name with the type that is returned by the function (int.) I’ve also added variables to contain the current and prior moving average prices and variables we will use to remember the locations of the moving averages with respect to each other.

Time to talk a little about MQL4 functions again. The function we’ll discuss is the iMA() function which returns the current price level of the specified moving average. The iMA() function returns a double (prices are always expressed as variable type double.) It requires several parameters:

string symbol – you can use NULL to represent the current chart symbol

int timeframe – you can use 0 to represent the current chart time frame, otherwise the time frame is expressed in minutes

int period – this is the number of bars you will use to calculate your average. For our purposes, each moving average period was declared in the external variables (MA1, MA2.)

int ma_shift – this is the line offset compared to the chart price. Like dragging the moving average line backwards in time. For our purposes, this will be 0.

int ma_method – this is the method we want to use for the calculation of the moving average. The possible responses are simple, exponential, smoothed or linear weighted. MQL4 helps us out by assigning constants so we don’t have to remember the integer value for each of these items. MODE_SMA, MODE_EMA, MODE_SMMA, and MODE_LWMA respectively. For our current EA, we’ll use simple (MODE_SMA.)

int applied_price – this is a value that represents what price we’ll be using for the moving average calculation. It can be either the open, close, high or low. As before, MQL4 has constants for these, PRICE_OPEN, PRICE_CLOSE, PRICE_HIGH, and PRICE_LOW respectively. We’ll be using the close (PRICE_CLOSE.)

And lastly,

int shift – this is the number of candles back  for which you want to find the price value of the moving average. 0 will give you the current (open) moving average, 1 is the moving average of the last closed candle, 2 is the candle prior to that and so on. Since we want to find out if there was a crossover after the last closed candle, we’ll use 1 and 2 for our shifts for the current and prior candles, respectively.

So here’s our code to assign the values of the moving average variables:

currMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 1);
currMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 1);
priorMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 2);
priorMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 2);

Now we’ll determine the locations of the moving averages with respect to each other:

if (priorMA1 > priorMA2)
    priorLoc = 1;
if(priorMA1 < priorMA2)
    priorLoc = -1;
if(priorMA1 == priorMA2)
    priorLoc = 0;

if(currMA1 > currMA2)
    currLoc = 1;
if(currMA1 < currMA2)
    currLoc = -1;
if(currMA1 == currMA2)
    currLoc = 0;

Now all we have to do is compare these to see if there has been a crossover. For the purposes of this function, we want a clear crossover, not just a touch of the moving averages, so we’ll only consider a -1 to 1 value a clear crossover:

if(priorLoc == -1 && currLoc == 1)
 CrossOver = 1;
if(priorLoc == 1 && currLoc == -1)
 CrossOver = -1;

And we’ve introduced you to a new operator, the && (logical and) operator. What this says is for the if operation to be completely true, then both values connected with the and operator must be true. For example, if the prior relative location of the MAs is 1 (MA1 above MA2) and the current relative location is -1 (MA1 below MA2), then we have a crossover in the downward direction (CrossOver = -1). So here is our completed IsThereACrossover() function:

int IsThereACrossover()
    {
    int CrossOver = 0;
    double currMA1, currMA2;
    double priorMA1, priorMA2;
    int currLoc, priorLoc;

    //Assign the prices for the moving averages
    currMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 1);
    currMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 1);
    priorMA1 = iMA(NULL, 0, MA1, 0, MODE_SMA, PRICE_CLOSE, 2);
    priorMA2 = iMA(NULL, 0, MA2, 0, MODE_SMA, PRICE_CLOSE, 2);

    //Determine relative locations of the prior closed candle moving averages
    if (priorMA1 > priorMA2)
        priorLoc = 1;
    if(priorMA1 < priorMA2)
        priorLoc = -1;
    if(priorMA1 == priorMA2)
        priorLoc = 0;

    //Determine relative locations of the current closed candle moving averages
    if(currMA1 > currMA2)
        currLoc = 1;
    if(currMA1 < currMA2)
        currLoc = -1;
    if(currMA1 == currMA2)
        currLoc = 0;

    //Determine if a crossover has taken place
    if(priorLoc == -1 && currLoc == 1)
        CrossOver = 1;
    if(priorLoc == 1 && currLoc == -1)
        CrossOver = -1;

    return(CrossOver);
    }

And that’s all for today. We’ll continue our functions next week. Have a great weekend and thanks for your attention. Please follow me on Twitter.

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!

The following two tabs change content below.
Winners Edge Trading was founded in 2009 and is working to create the most current and useful Forex information and training available on the internet.

Winner’s Edge Trading, as seen on:

Winner's Edge Trading in the news

  • Hi Dave,
    Sorry for the delay in responding.

    That’s an excellent point. As you say, that could save us from a meaningless trade. I believe we’ll add that to our list of future modifications. Thanks for this and your other excellent suggestions.

    Tim

  • Dave Hanna

    Considering that you’re comparing doubles, which are almost never exactly equal (unless they actually start with the same number), I would put a guard-band around your == comparison of MA1 and MA2, i.e.

    if (abs(currentMA1-currentMA2) < .000005) // Or some suitably small number

    currLoc = 0;

    Otherwise, you could get a case where currentMA1 is 1/10000000000 of a point above currentMA2, and priorMA1 is 1/1000000000 of a point below priorMA2 triggering a crossover that is entirely meaningless.