Русский 中文 Español Deutsch 日本語 Português
Testing and Optimization of Expert Advisors

Testing and Optimization of Expert Advisors

MetaTrader 4Tester | 27 November 2013, 14:21
46 378 13
Michael
Michael

Introduction

The article provides a detailed description of the process of testing and optimizing Expert Advisors in the MetaTrader 4 Strategy Tester. The importance of such information and the need for this publication cannot be underestimated. A lot of users who only get started with the MetaTrader 4 trading platform have a very vague idea of what and how needs to be done when working with Expert Advisors.

Almost every day (quite literally) the forum gets filled with beginning users' questions on how to install an Expert Advisor in the terminal, how to get started with an Expert Advisor, what is optimization and how it can be performed in the MetaTrader 4 Strategy Tester, what is forward testing, etc.

The proposed article gives simple and clear answers to all of these questions and provides a slightly more professional approach to handling these issues using a specific example. As the article unfolds, you can find links to the relevant articles and pages of the MQL4.community website for further, more detailed familiarization with testing and optimization processes.


Testing and Optimization of Expert Advisors

Let's consider the very first steps that you need to take when working with an Expert Advisor. For illustrative purposes, we will take a simple Expert Advisor - the Moving Average Expert Advisor we modified. In contrast to the original version built in the MetaTrader 4 trading platform, our version implements position opening when one Moving Average line is crossed by the price and position closing when there is a reverse crossing of the other Moving Average line by the price, but with a different period. Our version has also been enhanced with a function for opening positions under Market Execution conditions as this program modification has been in great demand lately. The code of the Expert Advisor is provided below:

//+------------------------------------------------------------------+
//|                                      Moving Average_Мodified.mq4 |
//|                      Copyright © 2013, MetaQuotes Software Corp. |
//|                                      Modified by BARS            |
//+------------------------------------------------------------------+
#define MAGICMA  20050610
//-----------------------------------------
extern int     StopLoss           = 500;
extern int     TakeProfit         = 500;
extern double  Lots               = 0.1;
extern double  MaximumRisk        = 0.02;
extern double  DecreaseFactor     = 3;
extern int     MovingPeriod_Open  = 12;
extern int     MovingPeriod_Close = 21;
extern int     MovingShift        = 1;
extern color   BuyColor           = clrCornflowerBlue;
extern color   SellColor          = clrSalmon;
//---
double SL=0,TP=0;
//-- Include modules --
#include <stderror.mqh>
#include <stdlib.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void start()
  {
//--- If there are more than 100 bars in the chart and the trade flow is free
   if(Bars<100 || IsTradeAllowed()==false)
      return;
//--- If the calculated lot size is in line with the current deposit amount
   if(CalculateCurrentOrders(Symbol())==0)
      CheckForOpen();   // start working
   else
      CheckForClose();  // otherwise, close positions
  }
//+------------------------------------------------------------------+
//| Determines open positions                                        |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
   for(int i=0; i<OrdersTotal(); i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
         break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
        {
         if(OrderType()==OP_BUY) buys++;
         if(OrderType()==OP_SELL) sells++;
        }
     }
//---- return orders volume
   if(buys>0)
      return(buys);
   else
      return(-sells);
  }
//+------------------------------------------------------------------+
//| Calculates the optimum lot size                                  |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal(); // history orders total
   int    losses=0;              // number of loss orders without a break
//---- select lot size
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//---- calcuulate number of loss orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
           {
            Print("Error in history!");
            break;
           }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL)
            continue;
         //----
         if(OrderProfit()>0)
            break;
         if(OrderProfit()<0)
            losses++;
        }
      if(losses>1)
         lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//---- return lot size
   if(lot<0.1)
      lot=0.1;
   return(lot);
  }
//+------------------------------------------------------------------+
//| Position opening function                                        |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
   double ma;
   int    res;
//---- go trading only for first tiks of new bar
   if(Volume[0]>1)
      return;
//---- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod_Open,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//---- sell conditions
   if(Open[1]>ma && Close[1]<ma)
     {
      if(StopLoss>0)
         SL=Bid+Point*StopLoss;
      if(TakeProfit>0)
         TP=Bid-Point*TakeProfit;
      res=WHCOrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,SL,TP,"Moving Average",MAGICMA,0,SellColor);
      if(res<0)
        {
         Print("Error when opening a SELL order #",GetLastError());
         Sleep(10000);
         return;
        }
     }
//---- buy conditions
   if(Open[1]<ma && Close[1]>ma)
     {
      SL=0;TP=0;
      if(StopLoss>0)
         SL=Ask-Point*StopLoss;
      if(TakeProfit>0)
         TP=Ask+Point*TakeProfit;
      res=WHCOrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,SL,TP,"Moving Average",MAGICMA,0,BuyColor);
      if(res<0)
        {
         Print("Error when opening a BUY order #",GetLastError());
         Sleep(10000);
         return;
        }
     }
//----
  }
//+------------------------------------------------------------------+
//| Position closing function                                        |
//+------------------------------------------------------------------+
void CheckForClose()
  {
   double ma;
//---- go trading only for first tiks of new bar
//(start working at the first tick of the new bar)
   if(Volume[0]>1) return;
//---- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod_Close,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//----
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
      //---- check order type 
      if(OrderType()==OP_BUY)
        {
         if(Open[1]>ma && Close[1]<ma)
            OrderClose(OrderTicket(),OrderLots(),Bid,3,BuyColor);     break;
        }
      if(OrderType()==OP_SELL)
        {
         if(Open[1]<ma && Close[1]>ma)
            OrderClose(OrderTicket(),OrderLots(),Ask,3,SellColor);     break;
        }
     }
  }
//+-------------------------------------------------------------------+
//| Opens positions in Market Execution mode                          |
//+-------------------------------------------------------------------+
int WHCOrderSend(string    symbol,
                 int       cmd,
                 double    volume,
                 double    price,
                 int       slippage,
                 double    stoploss,
                 double    takeprofit,
                 string    comment,
                 int       magic,
                 datetime  expiration,
                 color     arrow_color)
  {
   int ticket=OrderSend(symbol,cmd,volume,price,slippage,0,0,comment,magic,expiration,arrow_color);
   int check=-1;
   if(ticket>0 && (stoploss!=0 || takeprofit!=0))
     {
      if(!OrderModify(ticket,price,stoploss,takeprofit,expiration,arrow_color))
        {
         check=GetLastError();
         if(check!=ERR_NO_MQLERROR)
            Print("OrderModify error: ",ErrorDescription(check));
        }
     }
   else
     {
      check=GetLastError();
      if(check!=ERR_NO_ERROR)
         Print("OrderSend error: ",ErrorDescription(check));
     }
   return(ticket);
  }
//+------------------------------------------------------------------+

Download the attached file of the Moving Average_Мodify Expert Advisor. The downloaded file must be placed in the \MQL4\experts\ folder of the MetaTrader 4 trading terminal. For example, if you have the terminal installed under C:\Program Files\MetaTrader 4\, you will need to place the Expert Advisor in C:\Program Files\MetaTrader 4\MQL4\experts\. After that start (restart) the terminal.

The file of the Expert Advisor - Moving Average_Мodify - should appear on the left, in the Navigator window->Expert Advisors.

Start the Strategy Tester from the menu (Ctrl+R) of the MetaTrader 4 trading terminal. Further steps will be as follows (see the screenshot below):


  • From the "Expert Advisor" drop-down list select our expert Moving_Average_Мodify.
  • From the "Symbol" list select the currency pair for our tests, e.g. EURUSD.
  • From the "Period" list select the timeframe, such as H1.
  • Check "Use date" and set the time interval to be used in testing and optimization, e.g. from August 1, 2008 to May 1, 2009. The reason why we need to select May 1 instead of the current date will become clear to you in a while.
  • From the "Model" list select the "Open prices only" mode.

We should say a few words about this mode. When working in this mode, the signals for opening and closing positions are only received at the opening of the next new bar. This is the market entry mode provided for in the operation algorithm of our Expert Advisor! More information on modeling modes can be found in the article entitled "Strategy Tester: Modes of Modeling during Testing".

Let's proceed to testing. For now, we will be using the default parameters in the Expert Advisor settings. Click "Start" in the lower right corner of the Strategy Tester and prepare to view the test results once the progress bar reaches the end. To view the results, open the "Report" tab of the Strategy Tester. Alternatively, you can open the balance chart of the test pass - the "Graph" tab (see the screenshot above).

Sadly, the results are quite distressing. Our initial deposit is steadily tending to zero... We can view the generalized statistics of this test pass in the "Report" tab. Novice users may find it useful to familiarize themselves with the article "What the Numbers in the Expert Testing Report Mean".


Conclusion: Our Expert Advisor cannot make profit trading the specified symbol and time frame with the parameters set in the Expert Advisor settings by default. We should find such parameter values that will allow the Expert Advisor to be profitable!

In other words, "optimization means finding such parameters for the selected trading system that would allow us to obtain the best results" (see the How Not to Fall into Optimization Traps? article).

In the optimization mode, the Expert Advisor is repeatedly run with different external variables that vary according to the scheme we set in the Expert Advisor Settings: start value-step-stop value. The MetaTrader 4 Strategy Tester allows you to optimize multiple parameters simultaneously. Now, we need to set the optimization parameters. To do this, click on the "Expert properties" button (the upper right button) and open the "Inputs" tab:


On the left, check the boxes of the parameters we are going to optimize and set their start and stop values, as well as the step in the "Start", "Stop" and "Step" columns, respectively. The screenshot shows which parameters we are going to optimize (find):

  • StopLoss - Stop Loss (start=400 points, step=10 points, stop=1500 points).
  • TakeProfit - Take Profit.
  • MovingPeriod_Open - MA period for position opening.
  • MovingPeriod_Close - MA period for position closing.

The start and stop values for optimization are set based on common sense. For EURUSD Н1, it appears to be quite reasonable to set the values as shown in the screenshot above. Please keep in mind that in this case we have five-digit quotes in MetaTrader 4.

The optimization in the "Open prices only" mode is very fast. So we can afford to optimize all four selected parameters at the same time. Close the "Expert properties" window by clicking "OK" and in the Strategy Tester check the "Optimization" box on the right. Then click "Start" in the lower right corner of the Strategy Tester. The optimization is now in progress.

You can visually monitor the process using the Strategy Tester's tabs "Optimization Results" and "Optimization Graph". If green areas are displayed instead of the optimization chart, we recommend that you uncheck the "Two-dimensional surface - Space" option in the appearing window.

Upon completion of the optimization (when the progress bar reaches the end), open the Strategy Tester's tab "Optimization results" and resize it by dragging its upper border up. After that, click on the second column, "Profit", to arrange the pass results in descending order. We will be able to see the following:


As the screenshot suggests, some combinations of Expert Advisor parameters result in the maximum profit of $4,658. However, do not be in a hurry to set these parameters in our Expert Advisor. Given the profit value, the drawdown is too big! For a start, we should use the results to choose the most suitable combination of maximum profit and reasonable drawdown. That is why we will take pass 2406 with the profit value of $2,715 and the minimal relative drawdown of 19,83%.

Right-click on this line. A window will open where you should click on "Set input parameters". When this happens, the selected parameters are automatically set in the Expert Advisor. Click on the "Start" button in the lower right corner of the Strategy Tester. Following the completion of the test (pass), open the "Report" tab to check out the test results.

  • Initial deposit 1,000.00
  • Total net profit 2,705.40
  • Gross profit 7,520.57
  • Gross loss -4,815.17
  • Profit factor 1.56
  • Expected payoff 15.37
  • Maximal drawdown 413.08 (11.48%)
  • Relative drawdown 19.88% (399.50)
  • Total trades 176
  • Short positions (won %) 80 (41.25%)
  • Long positions (won %) 96 (32.29%)
  • Largest profit trade 142.10
  • Largest loss trade -87.10
  • Average profit trade 117.51
  • Average loss trade -42.99
  • Maximum consecutive wins (profit in money) 4 (567.62)
  • Maximum consecutive losses (loss in money) 8 (-310.27)
  • StopLoss=870; TakeProfit=1420; Lots=0.1; MaximumRisk=0.02; DecreaseFactor=3; MovingPeriod_Open=37; MovingPeriod_Close=54; MovingShift=1;


How stable are these results? Will the Expert Advisor trade in real time with the same results as it showed when run in the Strategy Tester? These questions can to some extent be answered during the so-called forward test!

Let me remind you that we have set the testing and optimization period from August 1, 2008 to May 1, 2009. We deliberately avoided optimization over the interval from August 2008 to the current date, training the Expert Advisor over the time interval specified. Now, it is time to take an "exam" and see what the Expert Advisor is capable of.

That is, to test it with the same parameters outside the optimization period - from May 2 to June 8, 2009! It is customary to call such test run a "forward test", as opposed to the previous one - back test.

Forward test results allow us to more confidently and objectively evaluate the prospects of real time trading for our Expert Advisor. I will not keep you waiting any longer and finally run a forward test as described above. To do this, we need to set the time interval in the Strategy Tester from May 2, 2009 to present (June 8) and click "Start"! Here are the results:

  • Initial deposit 1,000.00
  • Total net profit 348.44
  • Gross profit 1,049.34
  • Gross loss -700.90
  • Profit factor 1.50
  • Expected payoff 8.93
  • Maximal drawdown 287.60 (20.82%)
  • Relative drawdown 20.82% (287.60)
  • Total trades 39
  • Short positions (won %) 22 (59.09%)
  • Long positions (won %) 17 (70.59%)
  • Largest profit trade 42.00
  • Largest loss trade -89.00
  • Average profit trade 41.97
  • Average loss trade -50.06
  • Maximum consecutive wins (profit in money) 6 (251.90)
  • Maximum consecutive losses (loss in money) 3 (-267.00)


What a surprising result! This is very rare at the first run and is completely unexpected. The forward test has showed a quite good profit, however not without the drawdown. Ideally, the losing trades that resulted in the highest drawdown values should be checked in the chart using the Strategy Tester's visualization mode Any reader of this article can repeat the steps described above (in MetaTrader 4 Alpari) and see for themselves that all the results displayed are completely fair. On a side note, a similar forward test with more profitable optimization parameters and greater drawdown (3,061 and 771.95) produced much worse results.

But do not get your hopes up just yet. A more objective evaluation of performance of the Expert Advisor requires a series of such forward tests to be run over historical data. A good and clear description of all the necessary steps and the general assessment of results is provided in the articles of the series entitled "Expert Advisors Based on Popular Trading Systems and Alchemy of Trading Robot Optimization".

Here, we aim at familiarizing the readers with the first basic steps for working with Expert Advisors. Let's go back to the high drawdown value we saw when running the forward test. The chart suggests that the drawdown occurred after May 18, 2009 - trades 18 to 20. We will try to monitor the situation in the Strategy Tester's visualization mode. and change the mode in the "Model" field to "Every tick" for clarity. The visualization mode allows us to control the time speed (i.e. quote feed rate). Set the date from May 18, 2009 and click "Start".

This is what we can see at the loss making part of the historical data:

The significant drawdown was caused by three consecutive losing SELL trades. They were not in the direction of the trend, immediately exposing the main drawback of our Expert Advisor: its operation algorithm is too primitive. We need to at least add a basic trend filter and/or separate the entry mechanism for long and short trades in a more or less the same manner as suggested in the article "Non-standard Automated Trading". However these issues fall beyond the scope of this article.


Conclusion

We have described the basic working practices for testing and optimizing Expert Advisors in the Strategy Tester. To gain greater understanding and further experience with such tests, you can check the "How To Implement Your Own Optimization Criteria" and "Out-of-sample Optimization and Testing" articles.

In conclusion, let's consider some of the most frequently asked questions that new users usually have when testing EAs.

1. What causes difference in results of the same tests at different Dealing Centers?

The difference in test results at different Dealing Centers is caused by quote differences. Each broker has its own sources of quote feeds. This gives rise to differences in price, which is then reflected in test results.

2. Why do the same tests run at the same Dealing Center produce different results?

Different results obtained at the same Dealing Center may be caused by several reasons, the most common one being:
Floating spread - it has a quite strong impact on the results, especially when testing on lower time frames and using the EVERY TICK mode. The MetaTrader 4 Strategy Tester stores the last spread value. The spread might change in the next run and the test result will consequently be different.

3. What causes difference in results when testing in the "every tick" and "open prices only" mode?

The thing is that if the Expert Advisor works based on ticks, it gets and analyzes data on every tick, whereas it gets data and sends signals only at the new bar when working based on open prices, with all the consequences that come with it... Conclusion: It is essential to determine how the Expert Advisor operates and start the Strategy Tester in the appropriate mode.

4. Why are there no positions opened by the Expert Advisor?

First, you should open the Strategy Tester Journal. It will display a possible error code. The code interpretation can be found in the Error Codes section.

Hopefully, this article has answered many questions of the beginning users of the MetaTrader 4 trading platform. The novice users have an opportunity to gain a tiny bit of experience by going through (repeating) the steps described above on their own and getting the essential skill for future experiments!

The article was prepared using the materials referenced in the text, as well as the information from the How to run an Expert Advisor? webpage of I.Kim's website.

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/1385

Attached files |
Last comments | Go to discussion (13)
Fernando Carreiro
Fernando Carreiro | 31 Aug 2017 at 16:05
kalle1925: Could anyone explain for me why when I test an EA, every time I test, MT4 just gives me errors for buy/sell orders and nothing happens. This means that no profit no loss happens and the report of equity shows a horizental line!!

Since you did not list the errors, or show the log entries or provided code, we can only guess the nature of the problem.

However, if it gives errors then obviously something is wrong with either the EAs being tested or the history data been corrupted, or maybe ...

We can only guess with the lack of details you provided!

Philipp Gleichmar
Philipp Gleichmar | 3 Nov 2017 at 12:51

Hello, 


what is the meaning/difference of the 4 coloumns "Value", "Start", "Step" and "Stop" in the Expert properties?



Greetings, Philipp

Akinola Sodiq
Akinola Sodiq | 1 May 2020 at 18:58
Akinola Sodiq Olawale:
Can it work on phones (android)
19scottishboy62
19scottishboy62 | 12 Oct 2022 at 06:03

Hi, I'm new to MT5 . I'm looking for someone to write code for my trading methodology.

Not sure where to start ??

Thanks 


Dave 

Fernando Carreiro
Fernando Carreiro | 12 Oct 2022 at 11:31
19scottishboy62 #: Hi, I'm new to MT5 . I'm looking for someone to write code for my trading methodology. Not sure where to start ??

Use the Freelance section if you need someone to code for you.

Video tutorial: MetaTrader Signals Service Video tutorial: MetaTrader Signals Service
In just 15 minutes, this video tutorial explains what MetaTrader Signals Service is, and demonstrates in great detail how to subscribe to trade signals and how to become a signal provider in our service. By watching this tutorial, you will be able to subscribe to any trading signal, or publish and promote your own signals in our service.
Lite_EXPERT2.mqh: Expert Advisor Implementation Examples Lite_EXPERT2.mqh: Expert Advisor Implementation Examples
In this article, the author continues to familiarize the readers with the Lite_EXPERT2.mqh functions using real Expert Advisor implementation examples. The article deals with the idea of using floating pending orders and pending orders that vary dynamically from deal to deal which are determined based on Average True Range (ATR) indicator values.
Creating a Multi-Currency Multi-System Expert Advisor Creating a Multi-Currency Multi-System Expert Advisor
The article introduces a structure for an Expert Advisor that trades multiple symbols and uses several trading systems simultaneously. If you already identified the optimal input parameters for all your EAs and got good backtesting results for each of them separately, ask yourself what results you would get if testing all EAs simultaneously, with all your strategies put together.
Advanced Analysis of a Trading Account Advanced Analysis of a Trading Account
The article deals with the automatic system for analyzing any trading account in MetaTrader 4 terminal. Technical aspects of a generated report and interpretation of the obtained results are considered. Conclusions on improving trading factors are drawn after the detailed review of the report. MQLab™ Graphic Report script is used for analysis.