MQL4 vs MQL5 head to head

 

I wrote a speed test program for MQL4

extern int stops = 250;

double lots= 0.0;
bool buy=true;

int init(){
   lots = MarketInfo(Symbol(), MODE_MINLOT );
}

int start(){
   static datetime lastTime=0;
   
   if( lastTime== Time[0] )
      return( 0 );
   
   if( OrdersTotal()>0 ){  // since this is a speed test program for the strategy tester, only this EA creates trades 
      if( OrderSelect(0,SELECT_BY_POS) ){
         if( !OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10 ))
            Print("Failed to close ticket " + OrderTicket() + " : Error=" + GetLastError() );
      }
      return( 0 );      // on the next tick, if there are no open orders, we open a new trade 
   }
      
   if( buy ){
      double LONGtakeProfit = NormalizeDouble( Ask + stops*Point, Digits ); 
      double LONGstopLoss  =  NormalizeDouble( Ask - stops*Point, Digits ); 
      OrderSend( Symbol(), OP_BUY, lots, Ask, 10, LONGstopLoss, LONGtakeProfit );
   }
   else{
      double SHORTtakeProfit = NormalizeDouble( Bid - stops*Point, Digits );
      double SHORTstopLoss  =  NormalizeDouble( Bid + stops*Point, Digits );
      OrderSend( Symbol(), OP_SELL, lots, Bid, 10, SHORTstopLoss, SHORTtakeProfit );
   }
   
   if( OrdersTotal()>0 ){   // the order placement was successful so we can do nothing for the  rest of this bar
      buy = !buy; // so next bar we trade in the opposite direction 
      lastTime= Time[0];
   }

   return(0);
}

It's very simple, just alternately placing buy and sell orders at the start of a new bar. I strategy tested this on EURUSD H1 over all of 2011, using every tick. This produced 6204 trades and took 57 seconds.

This is my first attempt at MQL5 and the idea is that it should be functionally equivalent to the MQL4 code above.

// MQL5 code

input int stops = 250;

double lots= 0.0;
bool buy=true;

//+-------------------------------------------------------------------------------------------+
int OnInit(){
    lots = SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
    return(0);
}
//+-------------------------------------------------------------------------------------------+
void OnDeinit(const int reason){ 
}
//+-------------------------------------------------------------------------------------------+
void OnTick(){
    
    static datetime lastBar=0;
    
    datetime thisBar= (datetime)SeriesInfoInteger(_Symbol,_Period,SERIES_LASTBAR_DATE);
    
    if( lastBar==thisBar )
        return;

    MqlTradeResult  result={0};
    MqlTradeRequest request={0};

    MqlTick lastTick;
    SymbolInfoTick(_Symbol,lastTick);
    
    request.action=TRADE_ACTION_DEAL;
    request.symbol= _Symbol;
    request.volume= lots;  
            
    if( PositionsTotal()>0 ){
        if( PositionSelect(_Symbol) ){
            if( PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY ){
                request.type= ORDER_TYPE_SELL;
            }
            else{
                request.type= ORDER_TYPE_BUY;
            }
            
            OrderSend(request,result);
            if( result.retcode != TRADE_RETCODE_DONE && result.retcode !=TRADE_RETCODE_PLACED )
                Print("Close order failed: "  + IntegerToString(result.retcode));
        }
        
        return;
    }
   

            
    if( buy ){
        request.sl=    NormalizeDouble( lastTick.ask - stops*_Point, _Digits );
        request.tp=    NormalizeDouble( lastTick.ask + stops*_Point, _Digits );
        request.type = ORDER_TYPE_BUY;
    }
    else{
        request.sl=    NormalizeDouble( lastTick.bid + stops*_Point, _Digits );
        request.tp=    NormalizeDouble( lastTick.bid - stops*_Point, _Digits );
        request.type = ORDER_TYPE_SELL;
    }           

    OrderSend(request,result);
    if( result.retcode == TRADE_RETCODE_DONE || result.retcode ==TRADE_RETCODE_PLACED ){
        buy = !buy;
        lastBar= thisBar;  // if the trade is not successful then we try again on the next tick
    }
    else{
        if( buy)
            Print("BUY order failed: "  + IntegerToString(result.retcode));
        else
            Print("SELL order failed: " + IntegerToString(result.retcode));
    }
    
    return;
}

The MQL5 code produced 6176 trades but took 4 minutes 15 seconds. Are there errors in my MQL5 code that make it slow?

I noticed that at the end of the MQL5 run a chart popped up with all the trades shown. That looks computationally expensive. I did not have Visualization checked. Is it possible to stop this chart being created (to speed up the back testing )?

MQL4 has a symbol properties box so I can easily read off the spread of the pair I am using. Is this feature available in the MQL5 version somewhere else?

Documentation on MQL5: Standard Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
Standard Constants, Enumerations and Structures / Environment State / Symbol Properties - Documentation on MQL5
 
dabbler:

The MQL5 code produced 6176 trades but took 4 minutes 15 seconds. Are there errors in my MQL5 code that make it slow?

You have forgotten to setup the correct prices in MQL5 example.

Check my versions, please:

  • source code attached
  • server: MetaQuotes-Demo (access.metatrader5.com:443 & demo.metaquotes.net:443)
  • symbol: EURUSD, H1, 2011.01.01 - 2011.10.01, All ticks
  • balance: 1 000 000 USD
  • system: i7-2600, Windows 7 x64
Language
Price Ticks
Trades
Net Profit, USD
Time, sec
MQL5
15 515 315
4 660
-728
16
MQL4
12 520 048
4 659
-10 019
6


MQL5:



MQL4:




Files:
 
dabbler:

MQL4 has a symbol properties box so I can easily read off the spread of the pair I am using. Is this feature available in the MQL5 version somewhere else?


 
Renat:


Excellent. Thanks very much :-)
 
Renat:

You have forgotten to setup the correct prices in MQL5 example.

Check my versions, please:

  • source code attached
  • server: MetaQuotes-Demo (access.metatrader5.com:443 & demo.metaquotes.net:443)
  • symbol: EURUSD, H1, 2011.01.01 - 2011.10.01, All ticks
  • balance: 1 000 000 USD
  • system: i7-2600, Windows 7 x64
Language
Price Ticks
Trades
Net Profit, USD
Time, sec
MQL5
15 515 315
4 660
-728
16
MQL4
12 520 048
4 659
-10 019
6



Thank you for your very comprehensive answer. I did not actually forget to setup the prices on the orders. I followed my (understanding of) the help file instruction 

The Trade Request Structure (MqlTradeRequest)

Price, reaching which the order must be executed. Market orders of symbols, whose execution type is "Market Execution" (SYMBOL_TRADE_EXECUTION_MARKET), of TRADE_ACTION_DEAL type, do not require specification of price.

Your computer is so fast I'm just drooling on my keyboard :-)

BUT I notice that even with your better code and multi-threaded machine, the MQL5 is 2.6x slower!


 

I just tried the DealSpeed code on MQL5. This time it took 5 mins 24 seconds :-(

Admittedly I had Firefox open (to compare settings) and the MQL5 MetaEditor was also open, but neither was doing anything actively.

I still get the graphical plot of the trades window appearing at the end of the run.

I didn't mention my machine spec and version info. I am running MQL5 build 619.

My machine is a dual core AMD Athlon 64 X2 4200+ 2.20GHz with 4GB of RAM

Documentation on MQL5: Standard Constants, Enumerations and Structures / Indicator Constants / Drawing Styles
  • www.mql5.com
Standard Constants, Enumerations and Structures / Indicator Constants / Drawing Styles - Documentation on MQL5
 

Though I'm grateful that someone from MetaQuotes participate in this topic, I was expecting that Renat would explain to us why this speed gap exist, and not just showing his backtesting result.

Based what I read here (or in MetaEditor's MQL5 Reference/Timeseries and Indicator Access/Organizing Data Access), I can only guess that this slow speed due to nonavailability H1 data on MT5 and/or/so that MT5 was also busy creating that H1 data based on M1 data.

In MT4 we have only 9 timeframes, but each timeframe has it's own .hst data. So when we open a chart - any of that 9 timeframes - that chart will be quickly displayed in MT4 - sort of. When the first time I open Monthly chart EURUSD on MT5, and I set  "Max bars in chart" to "Unlimited", it took like forever for that bars to came. The chart was shown, but the bars was came one by one !!!!, starting from the newest to the oldest.

After some learning, MT5 only stored 1 minute data (not 9 timeframes data like MT4) in .hcc format - and it stored lots of them, perhaps to support Monthly timeframe. When some MQL5/MT5 programs needs a data - including even 1 minute data - only then MT5 create an intermediate cache data for that timeframe/need in form of .hc format.

I guess, what happened to dabbler and Renat backtesting speed was that MT5 was busy creating the .hc file for 1 hour data. So even if this speed test was performed on 1 minute data, I'm guessing that MT4 will still more faster than MT5, and now I wonder if this backtesting involving multiple timeframes data.  :( 

Like I said, I can only guess. And Renat or MetaQuotes should explain this better.

I prefer accuracy (thanks dabbler for correcting my english :) ), and I don't like - or should I say : trust - backtesting, I prefer forward running either forward test on demo or live. I just hope that this "MT5 creating intermediate data" does not slow down any forward running.

*** 

When, I read this topics, I decided I'm not even going to participate. All I know dabbler is using XP but I didn't know the specs (you don't mind do you, me telling whole world that you have XP). I bet Renat has lower specs for MT5 testing, he just won't tell us that. I don't think my backtesting even match dabbler's and much worry that he probably will show his yellow 'dabbler-inside' smiley face again. I'm only running Visa HB SP2 with dual core pentium T4200 2GHz and 2GB RAM. When I opened that Monthly EURUSD, it filled up my RAM quickly, so no thanks.

And it's a laptop :)

 
You know, you could also pointed out to here (here) :|
Reason: