Saturday 9 February 2013

How To Write a Close All Script in MQL4? (3 of 4)

Magic Numbers
You may not be familiar with the concept of a magic number as it is used in MT4. Magic Numbers are actually a very important concept to understand because Magic Numbers are found in many different types of MQL4 code, and can be integrated into a Close All routine simply. A Magic Number is a number used by an MT4 indicator, MT4 expert advisor or MT4 script to differentiate that MT4 expert advisor, MT4 indicator or MT4 script from one another being run on the same account. Perhaps the most useful way to think about a Magic Number is in terms of an MT4 expert advisor. If you are running multiple MT4 expert advisors or systems on a single account. If you want to keep track of the orders from a single strategy and differentiate them from another strategy running on the same account for the purposes of opening and closing orders (trades), and perhaps even on the same symbol, you could use a Magic Number.  The OrderSend() function is defined as follows:

int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)
Note the parameter "int magic = 0" which refers to a Magic Number that may be entered when an order is created. This same Magic Number may be referenced when closing an order. If you are running two different MT4 expert advisors on a single symbol, you could specify two different Magic Numbers in the OrderSend() function of each MT4 expert advisor, to ensure that each could handle its close order routine separately. Without using a unique Magic Number for each MT4 expert advisor, either Expert could close orders opened by a different MT4 expert advisor. This is usually not the intent of an MT4 expert advisor though in some cases it is desirable to close orders created by a different MT4 expert advisor.
The close all routine can be ammended to specify that only a given Magic Number is closed out with this routine. This can be accomplished as follows:
int Slippage = 5;
int MagicNumber = 321;
for (int i = OrdersTotal(); i >=0; i--) {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderType() == OP_BUY && Symbol() == OrderSymbol() 
     && MagicNumber == OrderMagicNumber()) {
        bool closed = OrderClose( OrderTicket(), OrderLots(), Bid, Slippage, White);
    }
    if (OrderType() == OP_SELL && Symbol() == OrderSymbol()
     && MagicNumber == OrderMagicNumber()) {
        bool closed = OrderClose( OrderTicket(), OrderLots(), Ask, Slippage, White);
    }
}
Finally, MQL4 code can be added that ensures that the trade context is ready, and that the most recent prices are available. The MQL4 code has been placed in a function called CloseThis, because the routine just closes a single symbol's trades with the given Magic Number.

void CloseThis(int Slippage, int MagicNumber) {
for (int i = OrdersTotal(); i >=0; i--) {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    while(IsTradeContextBusy()) Sleep(100);
    RefreshRates();
    if (OrderType() == OP_BUY && Symbol() == OrderSymbol() 
     && MagicNumber == OrderMagicNumber()) {
        bool closed = OrderClose( OrderTicket(), OrderLots(), Bid, Slippage, White);
    }
    if (OrderType() == OP_SELL && Symbol() == OrderSymbol()
     && MagicNumber == OrderMagicNumber()) {
        bool closed = OrderClose( OrderTicket(), OrderLots(), Ask, Slippage, White);
    }
}
}
The IsTradeContextBusy() function returns a boolean TRUE just as one would expect when some other EA is tying up the trade thread, and false when trading is available. Alternatively the function IsTradeAllowed() may be used as this function not only checks that the Trade context isn't busy, but also checks that trading is allowed for the expert.

The Sleep() function simply waits a given number of milliseconds before resuming with the next line of MQL4 code.

The RefreshRates() function forces the current prices to be updated. If you are sending orders and getting errors 135 (ERR_PRICE_CHANGED) or 138 (ERR_REQUOTE) you should use the RefreshRates() function to force new prices to update to your trade variables. It is a good practice to attempt to refresh rates during a close loop as closing orders may take time, during which time prices may shift causing errors.

The CloseThis() function may be called from any other MT4 function simply as follows for slippage of 7 pips and a magic number of zero:
CloseThis(7,0); 

Turn the CloseThis() routine into a CloseAll() routine by eliminating the symbol restriction and by using the MarketInfo() function to retrieve bid and ask prices from other symbols.

No comments:

Post a Comment