EA trade execution out of synch with custom indicator signal

 
Hi all!

I'm facing a problem with a simple EA based on a custom indicator (posted here by Kiko Segui). The idea is simply to enter/exit trades when the custom indicator crosses the zero line from below/above.
This indicator seem to be extremely powerful on most currencies!

The problem is that the EA executes the trades with a delay of 5 bars, although the indicator line itself is displayed correctly on its separate indicator window.

To illustrate the behaviour, here a screenshot of a typical situation:




Does anybody have an idea how this "mysterious" shift between crossing of zero-line of the indicator and the respective trade execution could be explained and hence what the solution would be?

I am aware of the problems which can arise e.g. from multiple null bar counts (like described in "MQL4: Multiple Null Bar Re-Сount in Some Indicators"), but this does not seem to be the problem in my case.

Here is the code of the simple skeleton EA:

//+------------------------------------------------------------------+
//|                                                       testEA.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/ru/"
 
extern double stop = 100;
double Lots = 0.1;
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
 
// Open LONG positions
int GoLong()
   {      
      int cnt, ticket, total = OrdersTotal();
      double Z = iCustom(Symbol(),PERIOD_M30,"FX_FISH_2MA",2,0);
      double Lots = 0.1;
      
      if(total < 1)
        {   
            ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,Ask-stop*Point,0,"Gekauft",123456,0,Green);
            if(ticket>0)
               {
                  if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                     {
                        Print("BUY Order# ", ticket, " at price : ",OrderOpenPrice());
                        Print("Value of Z0 is: ", Z);
                     }
               }
            else 
               {
                  Print("Error opening BUY order : ",GetLastError()); 
               }
            return(0);
       }   
   }
 
// Closing of all LONG positions   
int ExitLong()
   {
      int cnt, ticket, total = OrdersTotal();
      for(cnt=0; cnt<OrdersTotal(); cnt++)
         {      
            OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
            if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
               {
                  if(OrderType() == OP_BUY)   
                     {
                        OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position                          
                     }                           
               }
         }
   return(0);
   }     
 
//*****************************************************************************************************      
int start()
  {
   double Z;   
   Z = iCustom("GBPJPY",PERIOD_M30,"FX_FISH_2MA",2,0);
      
// Entry of position
        if( Z>0 ) // Open LONG position
            {               
               GoLong();
            }
// Exit of position
         if( Z<0 ) // Close LONG position
           {
              ExitLong();
           }
 
    return(0);
}
//*****************************************************************************************************


And here is the code of the custom indicator used to generate the entry/exit signals:


// FX_FISH_2MA
#property copyright "Copyright © 2005, Kiko Segui"
#property link      "webtecnic@terra.es"
 
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 SteelBlue
#property indicator_color2 Orange
#property indicator_color3 Black
#property indicator_color4 Blue
#property indicator_color5 Red
 
           
double buffer1[];
double buffer2[];
double buffer3[];
double MA1buffer[];
double MA2buffer[];
 
 
extern int period=20;
extern int price=0; // 0 or other = (H+L)/2
                    // 1 = Open
                    // 2 = Close
                    // 3 = High
                    // 4 = Low
                    // 5 = (H+L+C)/3
                    // 6 = (O+C+H+L)/4
                    // 7 = (O+C)/2
extern bool Mode_Fast= False;
extern bool Signals= false;
extern int MA1period=1, MA2period=1;
extern string TypeHelp = "SMA- 0, EMA - 1, SMMA - 2, LWMA- 3";
extern string TypeHelp2 = "John Hyden settings TypeMA1=0, TypeMA2=3";
extern int TypeMA1=0;
extern int TypeMA2=3;
      
int init()
  {
  SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID,1,SteelBlue);
  SetIndexBuffer(0,buffer1);
  SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,1,Orange);
  SetIndexBuffer(1,buffer2);
  SetIndexStyle(2,DRAW_LINE);
  SetIndexLabel(2,"line");
  SetIndexBuffer(2,buffer3);
  SetIndexStyle(3,DRAW_LINE);
  SetIndexLabel(3,"MA1 "+MA1period);
  SetIndexStyle(4,DRAW_LINE);
  SetIndexLabel(4,"MA2 "+MA2period);
  SetIndexBuffer(3,MA1buffer);
  SetIndexBuffer(4,MA2buffer);
  return(0);
  }
 
 
int deinit()
  {
  int i;
  double tmp;
  
  
  for (i=0;i<Bars;i++)
    {
    ObjectDelete("SELL SIGNAL: "+DoubleToStr(i,0));
    ObjectDelete("BUY SIGNAL: "+DoubleToStr(i,0));
    ObjectDelete("EXIT: "+DoubleToStr(i,0));
    }
  return(0);
  }
 
 
double Value=0,Value1=0,Value2=0,Fish=0,Fish1=0,Fish2=0;
 
int buy=0,sell=0;
 
int start()
  {
  int counted_bars=IndicatorCounted();
  int i;
  int barras;
  double _price;
  double tmp;
  
  double MinL=0;
  double MaxH=0;                    
  
  double Threshold=0; 
 
  if(counted_bars>0) counted_bars--;
 
  //barras = Bars;&#231;
  barras = Bars-counted_bars;
  if (Mode_Fast)
    barras = 100;
  i = 0;
  while(i<barras)
   {
   MaxH = High[Highest(NULL,0,MODE_HIGH,period,i)];
   MinL = Low[Lowest(NULL,0,MODE_LOW,period,i)];
  
   switch (price)
     {
     case 1: _price = Open[i]; break;
     case 2: _price = Close[i]; break;
     case 3: _price = High[i]; break;
     case 4: _price = Low[i]; break;
     case 5: _price = (High[i]+Low[i]+Close[i])/3; break;
     case 6: _price = (Open[i]+High[i]+Low[i]+Close[i])/4; break;
     case 7: _price = (Open[i]+Close[i])/2; break;
     default: _price = (High[i]+Low[i])/2; break;
     }
   
        
   Value = 0.33*2*((_price-MinL)/(MaxH-MinL)-0.5) + 0.67*Value1;     
   Value=MathMin(MathMax(Value,-0.999),0.999); 
   Fish = 0.5*MathLog((1+Value)/(1-Value))+0.5*Fish1;
   
   buffer1[i]= 0;
   buffer2[i]= 0;
   
   if ( (Fish<0) && (Fish1>0)) 
     {
     if (Signals)
       {
       ObjectCreate("EXIT: "+DoubleToStr(i,0),OBJ_TEXT,0,Time[i],_price);
       ObjectSetText("EXIT: "+DoubleToStr(i,0),"EXIT AT "+DoubleToStr(_price,4),7,"Arial",White);
       }
     buy = 0;
     }   
   if ((Fish>0) && (Fish1<0))
     {
     if (Signals)
       {
       ObjectCreate("EXIT: "+DoubleToStr(i,0),OBJ_TEXT,0,Time[i],_price);
       ObjectSetText("EXIT: "+DoubleToStr(i,0),"EXIT AT "+DoubleToStr(_price,4),7,"Arial",White);
       }
     sell = 0;
     }        
    
   if (Fish > 0)
     {
     buffer1[i] = Fish;
     buffer3[i]= Fish;
     }  
   if (Fish < 0)
     {
     buffer2[i] = Fish;  
     buffer3[i]= Fish;
     }
   if (Fish == 0)
     {
     buffer2[i] = 0;  
     buffer3[i]= 0;
     }
    
        
   tmp = i;
   if ((Fish<-Threshold) && 
       (Fish>Fish1) && 
       (Fish1<=Fish2))
     {     
     if (Signals)
       {
       ObjectCreate("SELL SIGNAL: "+DoubleToStr(i,0),OBJ_TEXT,0,Time[i],_price);
       ObjectSetText("SELL SIGNAL: "+DoubleToStr(i,0),"SELL AT "+DoubleToStr(_price,4),7,"Arial",Red);
       }
     sell = 1;
     }
 
  if ((Fish>Threshold) && 
       (Fish<Fish1) && 
       (Fish1>=Fish2))
    {
    if (Signals)
       {
       ObjectCreate("BUY SIGNAL: "+DoubleToStr(i,0),OBJ_TEXT,0,Time[i],_price);
       ObjectSetText("BUY SIGNAL: "+DoubleToStr(i,0),"BUY AT "+DoubleToStr(_price,4),7,"Arial",Lime);
       }
    buy=1;
    }
 
   Value1 = Value;
   Fish2 = Fish1;  
   Fish1 = Fish;
 
   i++;
   }
   
   for(i=0; i<barras; i++)
    MA1buffer[i]=iMAOnArray(buffer3,Bars,MA1period,0,TypeMA1,i);
   for(i=0; i<barras; i++)
    MA2buffer[i]=iMAOnArray(MA1buffer,Bars,MA2period,0,TypeMA2,i);
  return(0);
  }
//+------------------------------------------------------------------+

I know it is a quite simple question.... but I am really stuck at this point! Any help to resolve this issue is greatly appreciated!

Thank you very much,
Roland
 

hi,

i have the same problem

You have a solution for this problem ?


pascal.mochel@mochel.com


merci

 
I'm far from being an expert on MT4 but.... your condition to go long is Z>0 or short Z<0. The real condition must be for your EA : when Z[0]>0 and Z[1]<0 then go LONG.
Modif your EA to create Z0 and Z1, it should be ok. ;)



 
Hi,

I dug into this issue and there are several things that go wrong.

  1. You calculate your Z-value twice, one time in start() and one time in GoLong().
    However, you use slightly different parameters:
    Z = iCustom("GBPJPY",PERIOD_M30,"FX_FISH_2MA",2,0);
    double Z = iCustom(Symbol(),PERIOD_M30,"FX_FISH_2MA",2,0);
    I would suggest to always use iCustom(NULL, 0, ...) during development so that it uses the values from your current screen settings.
    That way you are more flexible.

  2. It is better still to calculate Z only once. You could have passed the Z-Value as a parameter to GoLong() or you could have made Z a static variable such that it is visible to all functions.
    static double Z;
  3. Your indicator has input paramters. In your call to iCustom() you left those out. I don't know whether MT4 takes the standard settings in that case, but your better of with providing the necessary parameters explicitly:
       Z = iCustom(NULL, 0, "FX_FISH_2MA", 20, 0, false, false, 1, 1, "", "", 0, 3, 2, 0);
  4. After I changed these things I ran the EA again and still observed unexpected behaviour. However, after I ran the backtest in visual mode I found out that your indicator is repainting the past! Go check this for yourself: run the EA in visual mode!
    This is the point I stopped my exploration, because I have a rule to stay away from "repainting" indicators, as they are pretty worthless for an EA.
    As a final result, you'll see the chart from the run in visual mode.




The final EA that I used for the test is given below.

Regards,

Max

//+------------------------------------------------------------------+
//|                                                   FX_Fish_EA.mq4 |
//|                      Copyright © 2008, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
 
extern double stop = 100;
double Lots = 0.1;
 
static double Z;
 
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
 
// Open LONG positions
int GoLong()
   {      
      int cnt, ticket, total = OrdersTotal();
//      double Z = iCustom(Symbol(),PERIOD_M30,"FX_FISH_2MA",2,0);
      double Lots = 0.1;
      
      if(total < 1)
        {   
            ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,Ask-stop*Point,0,"Gekauft",123456,0,Green);
            if(ticket>0)
               {
                  if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) 
                     {
                        Print("BUY Order# ", ticket, " at price : ",OrderOpenPrice());
                        Print("Value of Z0 is: ", Z);
                     }
               }
            else 
               {
                  Print("Error opening BUY order : ",GetLastError()); 
               }
            return(0);
       }   
   }
 
// Closing of all LONG positions   
int ExitLong()
   {
      int cnt, ticket, total = OrdersTotal();
      for(cnt=0; cnt<OrdersTotal(); cnt++)
         {      
            OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
            if(OrderType()<=OP_SELL && OrderSymbol()==Symbol())
               {
                  if(OrderType() == OP_BUY)   
                     {
                        OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position                          
                     }                           
               }
         }
   return(0);
   }     
 
//*****************************************************************************************************      
int start()
  {
//   double Z;   
//   Z = iCustom("GBPJPY", PERIOD_M30, "FX_FISH_2MA", 20, 0, false, false, 1, 1, "", "", 0, 3, 2, 0);
   Z = iCustom(NULL, 0, "FX_FISH_2MA", 20, 0, false, false, 1, 1, "", "", 0, 3, 2, 0);
      
// Entry of position
        if( Z>0 ) // Open LONG position
            {               
               GoLong();
            }
// Exit of position
         if( Z<0 ) // Close LONG position
           {
              ExitLong();
           }
 
    return(0);
}
//*****************************************************************************************************
 

i have a test. result is very Bad.

BstFisherAlSat
METALFX-Demo (Build 216)


Sembol GBPJPY (British Pound vs Japanese Yen)
Zaman aralığı 5 Dakika (D5) 2007.12.31 06:50 - 2008.05.06 23:55 (2007.01.01 - 2008.05.07)
Model Every tick (the most precise method based on all available least timeframes)
Parametreler stop=100;
Barlar denemede 25758 Tikler modellenmiş 1637727 Modelling quality 40.57%
Mismatched charts errors 0
Başlangıç depozitosu 10000.00
Toplam net kar -9812.96 Toplam kar 8583.49 Toplam zarar -18396.45
Profit factor 0.47 Expected payoff -8.38
Absolute drawdown 9812.96 En fazla düşüş (%) 9819.77 (98.13%) Relative drawdown 98.13% (9819.77)
Toplam işlem 1171 Short positions (won %) 0 (0.00%) Long positions (won %) 1171 (16.99%)
Profit trades (% of total) 199 (16.99%) Zararlı işlemler(% olarak) 972 (83.01%)
En büyük profit trade 309.25 loss trade -97.25
Ortalama profit trade 43.13 loss trade -18.93
Maximum consecutive wins (profit in money) 3 (80.72) consecutive losses (loss in money) 32 (-571.83)
Maximal consecutive profit (count of wins) 309.25 (1) consecutive loss (count of losses) -571.83 (32)
Ortalama consecutive wins 1 consecutive losses 6

 
Can you explain what "repainting" means?
 

Hi there


i am a programer

and i try to resolve this with a Kiko Segui indicator

the robot work well but, no profit, because in 4H have false signal, oscilation prices over zero down cero.


i try with combinations with filter (stochastics) and other to go out, and in general not work. This indicador is to trader manual,


Regard


MasterWhite

Reason: