MetaTrader MQL Course. Module 10: Implementing a Cross Over with MQL

Implementing a Cross Over with MQL

In the last module we used the MQL time functions to close trades at a certain time.   If you’d like to review that module, click here: Using MQL Time Functions.

In this module we will learn how to implement a cross-over strategy.  Almost any two lines that you can see on a price chart can be used for a cross-over. One well known cross-over strategy is to use the +DI and -DI lines of the ADX indicator.

To implement the cross-over strategy we’ll only need the iADX MQL function, but we’ll need to use the correct “mode” and “shift” parameters.  There are two types of cross-overs that must be checked for separately: the cross up and the cross down.

So, what does it mean for one line to cross up through another?  It means this: Before, the value of line A was less than the value of line B, and now, the value of line A is greater than the value of line B.  To test if the +DX line has crossed up through the -DX line we will need 4 values. The values of +DX and -DX from “before” and the values of +DX and -DX from “now”.  In price chart talk, “before” means the last fully formed candle and “now” means this candle.

We’ll use the mode parameter of the iADX function to get the +DX value or a -DX values.

We’ll use the shift parameter of the iADX function to get value for the last candle and for this candle.

So our 4 values are dx_plus_now, dx_plus_before, dx_minus_now and dx_minus_before.

This is the MQL code for getting the dx values of the iADX function.

int fnCheckEntry()
{

double dx_plus_now = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_PLUSDI, 0);
double dx_plus_before = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_PLUSDI, 1);
double dx_minus_now = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MINUSDI, 0);
double dx_minus_before = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MINUSDI, 1);

}

 

We’ll create a new user-function called “fnCheckEntry”.  This function will return OP_BUY to open a buy trade, OP_SELL to open a sell trade, or -1 to do nothing.

Here is the logic to check that +DX crossed up through -DX:

if( (dx_plus_before < dx_minus_before) && (dx_plus_now > dx_minus_now) )

Here is the logic to check that +DX crossed down through -DX:

if( (dx_plus_before > dx_minus_before) && (dx_plus_now < dx_minus_now) )

This is the MQL programming code of our Expert Advisor making full use of the “fnCheckEntry” function.  Notice where and how the function is used.

// these are all externs so they can be changed when the EA is attached to a chart
// the values set are default values
extern int stoploss=200;
extern int takeprofit=200;
extern double lots = 1.0;
extern int magic_number=12345;
extern int rsi_period=12;
extern double rsi_buy_level=75.0;
extern double rsi_sell_level=25.0;

extern int close_day=5;
extern int close_hour=14;

int start()
{
// get the rsi value
double rsi_value = iRSI(Symbol(), Period(), rsi_period, PRICE_CLOSE, 0);
// this variable will hold the number of trades open for this EA (as defined by magic number)
int my_trades=0;
// this variable will holds the total number of trades for the entire account
int all_trades=OrdersTotal();

// use a for loop to cycle through all of the trades, from 0 up to all_trades
for( int cnt=0;cnt<all_trades;cnt++ )
{
// use OrderSelect to get the info for each trade, cnt=0 the first time, then 1, 2, .., etc
// if OrderSelect fails it returns false, so we just continue
if( OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES) == false )
continue;

// compare the magic_number of our EA (as passed in as an input parameter) to the order’s magic number
// if they are equal, increment my_trades
if( magic_number == OrderMagicNumber() )
{
my_trades++;

if( OrderType() == OP_BUY )
{
// this is the explicit close logic for a buy order
// if the rsi OR it is friday
if( (rsi_value < rsi_sell_level) || (fnCheckExit(close_day, close_hour) == true) )
{
// use the ticket info to close
// note: the price should be Bid for a Buy order
// using OrderLots()will close the entire order
OrderClose(OrderTicket(), OrderLots(), Bid, 3, Green);
}
}

if( OrderType() == OP_SELL )
{
// this is the explicit close logic for a sell order
// if the rsi OR it is friday
if( (rsi_value > rsi_buy_level) || (fnCheckExit(close_day, close_hour) == true) )
{
// use the ticket info to close
// note: the price should be Ask for a Sell order
// using OrderLots()will close the entire order
OrderClose(OrderTicket(), OrderLots(), Ask, 3, Green);
}
}
}
}

// my_trades should either be 1 or 0. if it is greater than zero, then we just exit
if( my_trades > 0 )
return(0);

// call the fnCheckEntry to see if we should open a buy
if(fnCheckEntry() == OP_BUY)
{
// call our user function with a SELL parameter
fnOpenTrade(Symbol(), OP_BUY);
// exit after trying to open a trade
return(0);
}

// call the fnCheckEntry to see if we should open a sell
if(fnCheckEntry() == OP_SELL)
{
// call our user function with a SELL parameter
fnOpenTrade(Symbol(), OP_SELL);
// exit after trying to open a trade
return(0);
}

return(0);
}

void fnOpenTrade(string symbol, int type)
{
// notice that the symbol is passed in as a parameter
// get the bid value for whatever symbol was sent in
double my_bid = MarketInfo(symbol, MODE_BID);
// get the ask value for whatever symbol was sent in
double my_ask = MarketInfo(symbol, MODE_ASK);
// get the point value for whatever symbol was sent in
double my_point = MarketInfo(symbol, MODE_POINT);

// now instead of using the Bid, Ask and Point values that give the value for the
// symbol that the EA is running, use our values from above

int status =
OrderSend( symbol, // the synbol for this chart
type, // a buy order
lots, // number of lots
my_bid, // use the ask price for a BUY
3, // allow the price up to move 3 points
my_bid + (stoploss*my_point), // stop
my_ask – (takeprofit*my_point), // limit
“My Simple EA”, // comment to see in Terminal
magic_number, // a unique # to id this trade
0, // expiration, doesn’t work
Red // a blue arrow
);

if( status < 0 )
Comment(“OrderSend Failed!! Error=”, GetLastError());
}

// This function returns true to indicate it’s time to close
bool fnCheckExit(int day, int hour)
{
// if today is Friday(5) AND the hour is at, or past, 2:00 PM
if( (DayOfWeek() == day) && (Hour() >= hour) )
return(true);

return(false);
}

int fnCheckEntry()
{

double dx_plus_now = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_PLUSDI, 0);
double dx_plus_before = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_PLUSDI, 1);
double dx_minus_now = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MINUSDI, 0);
double dx_minus_before = iADX(Symbol(), Period(), 14, PRICE_CLOSE, MODE_MINUSDI, 1);

if( (dx_plus_before < dx_minus_before) && (dx_plus_now > dx_minus_now) )
return(OP_BUY);

if( (dx_plus_before > dx_minus_before) && (dx_plus_now < dx_minus_now) )
return(OP_SELL);

return(-1);
}

Copy and paste this code into your MetaEditor and experiment with it.  In our next module, we are going to learn how to use “channels” in an Expert Advisor.