MetaTrader MQL Course. Module 7: User Functions in MQL

User Functions in MQL

In the last module we added an explicit close to our Expert Advisor using the MQL OrderClose function.  If you’d like to review that module, click here: Closing a Trade Using OrderClose.

In this module I am going to introduce something very powerful.  It’s available in almost all modern MQL programming languages – not just MQL. I am talking about user-created functions.

We have introduced many MQL functions throughout this course and we’ve seen how useful they can be.  Did you know you can create your own functions?  It’s actually very easy to do in MQL. A typical function has a return value, a name and some parameters.  This is an example of a simple “Add” function.  It takes two parameters, adds them, and returns the result.

Simple MQL Add Function:

int Add(int a, int b)
{
int total;
total = a+b;
return(total);
}

A function does not have to have a return value – in that case the return value is declared as “void”. It does not need parameters either – in that case it’s empty between the parenthesis.

The beauty of a function is that it allows you to reuse your code.  This makes your programs easier to read (and create).

For our Expert Advisor, I am going to create a function for opening a trade. It will take one parameter: the type of trade to open, OP_BUY or OP_SELL.

This is the MQL code for the function “fnOpenTrade”.

void fnOpenTrade(int type)
{
int status =
OrderSend( Symbol(), // the synbol for this chart
type, // a buy order
lots, // number of lots
Bid, // use the ask price for a BUY
3, // allow the price up to move 3 points
Bid + (stoploss*Point), // stop
Ask – (takeprofit*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 is the MQL code for our complete Expert Advisor using the “fnOpenTrade” function.

// 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;

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(rsi_value < rsi_sell_level)
{
// 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(rsi_value > rsi_buy_level)
{
// 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);

// if the rsi_value is larger than rsi_buy_level, we open a buy
if(rsi_value > rsi_buy_level)
{
// call our user function with a SELL parameter
fnOpenTrade(OP_BUY);
// exit after trying to open a trade
return(0);
}

// if the rsi_value is larger than rsi_buy_level, we open a buy
if(rsi_value < rsi_sell_level)
{
// call our user function with a SELL parameter
fnOpenTrade(OP_SELL);
// exit after trying to open a trade
return(0);
}

return(0);
}

void fnOpenTrade(int type)
{
int status =
OrderSend( Symbol(), // the synbol for this chart
type, // a buy order
lots, // number of lots
Bid, // use the ask price for a BUY
3, // allow the price up to move 3 points
Bid + (stoploss*Point), // stop
Ask – (takeprofit*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());
}

 Copy and paste this code into your MetaEditor and experiment with it.

We are going to keep adding user functions in the next few modules and really step up the power of our EA!