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.
 
									


