A Virtual Order Manager to track orders within the position-centric MetaTrader 5 environment

Paul | 13 May, 2010


1. Introduction

Arguably the biggest change in the transition from MetaTrader 4 to MetaTrader 5 is the management of open trades as positions. At any one time there can be one position only open for each symbol, and the size of this position adjusts up and down each time orders are processed by the broker. This aligns with the NFA 2-43(b) FIFO rule introduced in the US, and also fits with the mode of trading in many other entities such as futures, commodities and CFDs.

A clear example of the difference would be when two EAs running against the same symbol issue orders in opposite directions.  This can be a common situation with two EAs working in different timeframes, such as a scalper and a trend-follower.  In MetaTrader 4, the open trade list would show buy and sell open orders with zero margin used. In MetaTrader 5, no position would be open at all.

Looking in the EA code itself, functions such as the commonly used MQL4 OpenOrders() below, or similar variant, will not function as expected when migrated to MQL5.

int OpenOrders()  // MetaTrader 4 code to count total open orders for this EA
{
  int nOpenOrders=0;
  for (int i=OrdersTotal()-1; i>=0; i--)
  {
    OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
    if (OrderMagicNumber()==magic)
      if (OrderType()==OP_BUY || OrderType()==OP_SELL)
        if (OrderSymbol()==Symbol())
          nOpenOrders++;
  }
  return(nOpenOrders);
}

So the MetaTrader 5 position-centric environment presents unfamiliar challenges for the programmer used to the order processing approach used in MetaTrader 4. What were simple order management functions in MetaTrader 4 become more complex in MetaTrader 5 when multiple orders can get merged into the one position, such as multiple EAs trading the one symbol, or multiple orders from the one EA on a symbol.


2. Ways to work with positions in MetaTrader 5  

There are a number of ways to manage this position-centric environment in MetaTrader 5, depending on the complexity of trading strategies.

Firstly, note that MetaTrader 5’s handling of pending orders is similar to MetaTrader 4, so MQL5 code written for pending orders alone could be a relatively simple migration from MQL4 code.

2.1 Straightforward EA; one EA per symbol per account

The simplest approach is to limit trading on the one account to one straightforward EA per symbol.  “Straightforward EA” in this case means one which only issues a single order at a time, which is a common method but excludes strategies such as pyramiding and grid trading.  Straightforward EAs can be written in MQL5 in a similar way to MQL4, perhaps using the CTrade library wrapper provided in include\trade\trade.mqh.

2.2 Complex EA; one EA per symbol per account

For complex EAs, such as those which have a strategy such as pyramiding or grid trading which can require more than one open order for a symbol, some relatively simple order tracking code added to the EA may be all that is necessary to manage the strategy.  This will only be possible if the EA will never share positions with another EA trading the same symbol.

2.3 More than one EA of any type per symbol per account

This presents the most complex trading and coding requirement, and is the reason for the development of the Virtual Order Manager (VOM) library.  This library is intended to simplify greatly the development of robust EA code which is fully sociable with other EAs.

The rest of this article describes the Virtual Order Manager library in detail.


3. Design goals, benefits and disadvantages of the Virtual Order Manager 

The VOM has four main design goals:

  1. Sociability: the behaviour of EAs written correctly using the VOM trading functions will be isolated from other EA activity
  2. Robustness: elegant handling of abnormal events such as errors, breaks in client-server communication and incomplete order fills.
  3. Ease of use: provision of well documented and simple trading functions
  4. Ability to use in the Strategy Tester

These goals are implemented as follows:

The VOM approach allows an MQL5 EA programmer to:

It should also be noted that a side-effect of the VOM approach is that its virtual stoplosses, takeprofits and pending orders inherently have “stealth” behaviour, ie they cannot be seen at the broker server.  Hiding stoploss levels is seen by some as necessary to prevent the broker from being able to engage in stop-hunting.

The VOM also has disadvantages.  The amount of equity risk is increased due to the possibility of relying on the more distant protective server stop during an extended PC or internet link failure.  Also, slippage when hitting a virtual pending order, stoploss or takeprofit could be much higher than for its server-based equivalent during times of high volatility such as news events.  The impact of these disadvantages can be minimised if VOM EAs are traded from a high reliability virtual desktop with a short ping time to the broker’s server.


4. The VOM in practice – a simple EA

Before going further, it’s time to show how a VOM EA can be written.  We’ll write a simple MA cross EA, starting with the template EA provided in the distribution package.  We will use the Fractal Moving Average, which has the potential to reduce pointless trades during sideways markets, a notorious problem with MA cross strategies. It should be stressed that this EA has been provided as a simple example and is not recommended for live trading – the backtest is profitable but the low number of trades means that the result is not statistically significant.

The EA is stored in experts\Virtual Order Manager\VOM EAs.

//+------------------------------------------------------------------+
//|                                           FraMA Cross EA VOM.mq5 |
//+------------------------------------------------------------------+
#property copyright "Paul Hampton-Smith"
#property link      "http://paulsfxrandomwalk.blogspot.com"
#property version   "1.00"

// this is the only include required.  It points to the parent folder
#include "..\VirtualOrderManager.mqh"

input double   Lots=0.1;
input int      Fast_MA_Period=2;
input int      Slow_MA_Period=58;
/* 
Because the broker is 3/5 digit, stoplosses and takeprofits should be x10.  
It seems likely that all brokers offering MetaTrader 5 will be 3/5 digit brokers, 
but if this turns out to be incorrect it will not be a major task to add 
digit size detection. */
input int      Stop_Loss=5000;
input int      Take_Profit=0;
/*
We can also change the level of logging.  LOG_VERBOSE is the most prolific 
log level.  Once an EA has been fully debugged the level can be reduced to 
LOG_MAJOR.  Log files are written under the files\EAlogs folder and are 
automatically deleted after 30 days.  */
input ENUM_LOG_LEVEL Log_Level=LOG_VERBOSE;

// The following global variables will store the handles and values for the MAs 
double g_FastFrAMA[];
double g_SlowFrAMA[];
int g_hFastFrAMA;
int g_hSlowFrAMA;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   LogFile.LogLevel(Log_Level);

// Need to include this line in all EAs using CVirtualOrderManager  
   VOM.Initialise();
   Comment(VOM.m_OpenOrders.SummaryList());

   g_hFastFrAMA = iFrAMA(_Symbol,_Period,Fast_MA_Period,0,PRICE_CLOSE);
   g_hSlowFrAMA = iFrAMA(_Symbol,_Period,Slow_MA_Period,0,PRICE_CLOSE);
   ArraySetAsSeries(g_FastFrAMA,true);
   ArraySetAsSeries(g_SlowFrAMA,true);

   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// Need to include this line in all EAs using CVirtualOrderManager  
   VOM.OnTick();
   Comment(VOM.m_OpenOrders.SummaryList());

// We now obtain copies of the most recent two FrAMA values in the 
// g_FastFrAMA and  g_SlowFrAMA arrays.  
   if(CopyBuffer(g_hFastFrAMA,0,Shift,2,g_FastFrAMA)!=2) || 
      CopyBuffer(g_hSlowFrAMA,0,Shift,2,g_SlowFrAMA)!=2)
     {
      Print("Not enough history loaded");
      return;
     }

// And now we detect a cross of the fast FrAMA over the slow FrAMA,
// close any opposite orders and Buy a single new one
   if(g_FastFrAMA[0]>g_SlowFrAMA[0] && g_FastFrAMA[1]<=g_SlowFrAMA[1])
     {
      VOM.CloseAllOrders(_Symbol,VIRTUAL_ORDER_TYPE_SELL);
      if(VOM.OpenedOrdersInSameBar()<1 && VOM.OpenOrders()==0)
        {
         VOM.Buy(_Symbol,Lots,Stop_Loss,Take_Profit);
        }
     }

// Opposite for Sell
   if(g_FastFrAMA[0]<g_SlowFrAMA[0] && g_FastFrAMA[1]>=g_SlowFrAMA[1])
     {
      VOM.CloseAllOrders(_Symbol,VIRTUAL_ORDER_TYPE_BUY);
      if(VOM.OpenedOrdersInSameBar()<1 && VOM.OpenOrders()==0)
        {
         VOM.Sell(_Symbol,Lots,Stop_Loss,Take_Profit);
        }
     }
  }
//+------------------------------------------------------------------+

And now with the release of the Strategy Tester it can be backtested, see Figure 1 below:

 Figure 1. FrAMA Cross EA backtest

Figure 1. FrAMA Cross EA backtest

The logging section is shown at Figure 2:

 Figure 2. Strategy test log

Figure 2. Strategy test log

 

5. VOM structure

Figure 4 below shows how multiple VOM EAs are configured:

Figure 3. Multiple VOM EAs

Figure 3. Multiple VOM EAs

Then looking inside the VOM, the main components are shown at Figure 4 below:

Figure 4. VOM internal structure

Figure 4. VOM internal structure

 Elements of firgure 4 explained:

Expert Advisors that use the VOM interact with the library as shown in Figure 5 below:

 Figure 5. EA interaction with the VOM library

 Figure 5. EA interaction with the VOM library


6. More on the disaster protection stoploss

Virtual stops have been quite common amongst MetaTrader 4 EAs.  If a stoploss is maintained at the client end only, the exit level for a trade is invisible to the broker, a strategy often implemented in the belief that some brokers engage in stop hunting.  On their own, virtual stops greatly increase trade risk, since a broker-client connection must be always be in place for the stop to be actioned. 

The VOM controls this risk by maintaining a server-based stop at a configurable distance away from the tightest virtual stop.  This is termed a disaster protection stoploss (DPSL) because it will normally only be actioned if the broker-client connection is broken for some time, as would be the situation with an internet connection break or a PC failure.  As virtual orders are opened and closed, and converted to a position at the server, the maintenance of the DPSL at the correct level can be a little complex, as illustrated in the following sequence.

Virtual order
action
Open
price
Virtual SL Position
at server
Stoploss
at server
Comment
0.1 lots BUY #1 2.00000 1.99000 0.1 lots BUY 1.98500 DPSL is 50 pips below virtual SL #1
0.1 lots BUY #2 2.00000 1.99500 0.2 lots BUY 1.99000 Virtual order #2 has a tighter SL so DPSL
is tightened to 50 pips below virtual SL #2
Close #2     0.1 lots BUY 1.98500 Revert to looser DPSL
0.1 lots SELL #3 2.00000 2.00500 none none Virtual orders #1 and #3 have cancelled each
other out at the server
Close #1     0.1 lots SELL 2.01000 Virtual Order #3 remains open - DPSL is
now 50 pips above virtual SL #3

7. Testing the Virtual Order Manager

A project of this size takes time to test thoroughly, so I wrote the EA VirtualOrderManaerTester.mq5 to enable virtual orders to be created, modifed, deleted and closed easily with command buttons on the chart.  

Figure 6 below shows a virtual buy order at 0.1 lot in the M5 window and a virtual buy order of another 0.1 lot open in the H4 window against EURUSD (see comment lines), with the server status correctly showing one position at 0.2 lots bought. Because the overall position is long, the Distaster Protection Stoploss can been seen below the tighter 20.0 pip stop.

Figure 6. Two EAs agreeing on direction

Figure 6. Two EAs agreeing on direction

Figure 7 now shows the two test EAs with opposing virtual orders, and no position is open at the broker:

Figure 7. Two EAs with opposing virtual orders and no position is open at the broker

Figure 7. Two EAs with opposing virtual orders and no position is open at the broker


8. A very simple display of all VOM open orders

Each VOM EA can only see its own orders, so I have written a very simple EA which collates the open orders from all VOMs.  The display is very simple, and when time permits a much better version could be written, perhaps with command buttons to perform modify, delete or close actions as required on each order.  The EA is included in the distribution pack as VOM_OrderDisplay.mq5.


9. Conclusion

At the time of writing this article, the VOM code is in Beta, just like MetaTrader 5 itself, and time will tell if the VOM concept becomes popular or ends up being regarded as just an interesting piece of MQL5 programming.

Let's go back to the design goals in section 3 and see where we have arrived

  1. Sociability: the behaviour of EAs written correctly using the VOM trading functions will be isolated from other EA activity
    • Result - yes, the VOM approach achieved this goal
  2. Robustness: elegant handling of abnormal events such as errors, breaks in client-server communication and incomplete order fills.
    • Result - some robustness is evident but there could be improvement as real trading situations occur and can be analysed 
  3. Ease of use: provision of well documented and simple trading functions
    • Result - As will be seen in the distribution pack of files, a .chm help file is included
  4. Ability to use in the Strategy Tester
    • Result - initial tests in the recently released strategy tester indicate that the VOM does backtest correctly, although the VOM approach slows down the test considerably.  Some work to improve throughput is probably needed  

A number of future changes may be desirable

  • As with any complex software development, it is likely that there are bugs remaining in the code
  • With each MetaTrader 5 Beta build release there may be required VOM changes to maintain compatibility
  • VomGetLastError() and VomErrorDescription() functions
  • Ability to read configuration from a file
  • Trailing stops of various types


10. Files in the zipped distribution pack

The VOM package comes as a number of .mqh files which should be installed in an Experts\Virtual Order Manager folder,

  • ChartObjectsTradeLines.mqh - CEntryPriceLine, CStopLossLine, CTakeProfitLine
  • StringUtilities.mqh - global enum descriptors such as ErrorDescription()
  • Log.mqh - CLog
  • GlobalVirtualStopList.mqh - CGlobalVirtualStopList
  • SimpleChartObject.mqh - CButton, CLabel and CEdit
  • VirtualOrder.mqh - CVirtualOrder
  • GlobalVariable.mqh - CGlobalVariable
  • VirtualOrderArray.mqh - CVirtualOrderArray
  • VirtualOrderManager.mqh - CVirtualOrderManager
  • VirtualOrderManagerConfig.mqh - CConfig
  • VirtualOrderManagerEnums.mqh - the various enums defined for the VOM
  • VOM_manual.mqh - this page of the manual
  • VOM_doc.chm***

Five EA mq5 files are also included under Experts\Virtual Order Manager\VOM EAs:

  • VOM_template_EA.mq5 - clone this to make your own EAs, and store them in Experts\Virtual Order Manage\VOM EAs
  • VirtualOrderManagerTester.mq5
  • Support_Resistance_EA_VOM.mq5
  • FrAMA_Cross_EA_VOM.mq5
  • VOM_OrderDisplay.mq5 

***Note that the VOM_doc.chm file may need to be unlocked: