StrategyTester - Trades have different Results on two PCs

 

Hallo everybody,

I have ran an EA on two different Computers. Both have the same Version of MT5 (3550) and both use the same Demo-Account. Also Both of them use the same created CustomSymbols with the same Tick-DataI extracted.

Still both of them have different Trade outcomes.

They both have the same ammount of trades and find the same entrance to the trades. But the outcome is diffrent even if the SL and TP I set for the trades  are the same (I have checked that with the Journal in the Visualisation Mode). I attach a screenshot what shows my problem. I circle one example but you can see several little differences within the screenshot.


For Structure: I Open two trades at the same time for the Symbol. One with a short TP one with a higher TP. If the first TP is taken  the other Trade moves its SL to BE and and keeps running from there until TP or SL is hit.

Can anyone tell what the problem here maybe? Is this problem Code related or is the Tick-Data corrupt or anything else?


I wish  all of you a great day!

Thomas

 
Thomas Behnke:

is the Tick-Data corrupt

double Sum = 0;

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
    Sum += Tick.ask - Tick.bid + 1;
}

void OnDeinit( const int )
{
  Print(Sum);
}
 

Thanks for the little code fxsaber.

I checked it and thats not the Problem.

 
Thomas Behnke #:

I checked it and thats not the Problem.

If the amounts match on both terminals, then the problem is in the code. Most likely uninitialized variables or array elements.

If there is a code to reproduce, it will be possible to accurately answer.

 

Hi fxsaber,


thanks again. Ich will post the Code here. I have erased everything that is not important for the trades. cause it is too long. hope it is enough. if not tell me and I attach the file with the complete code.

I try to trade multiple currencys on the daily timeframe. I test in in Strategy-Tester with OpenPriceOnly.

I know my code is not pretty and I didnt use functions. sorry for that :S

It isnt suppost to work as an EA in Live Trading. It only should give me correct data on the onTester-Function in Strategy-Tester (It only counts Wins and loses). But for that the Trades have to work....

Hope you still can read it/its still ok to understand.

have a great day!

//--- Include standard libraries
#include <Trade\Trade.mqh>
#include <SmoothAlgorithms.mqh> 
CTrade          trade;
//--- Number of symbols for each strategy
#define Strategy_A 27

string SymbolArray[]={"EURUSDmy","GBPUSDmy","USDCHFmy"
                     ,"USDJPYmy","USDCADmy","AUDUSDmy","EURGBPmy","GBPJPYmy",
                     "AUDJPYmy","CHFJPYmy","EURCADmy","EURNZDmy","NZDCADmy","NZDCHFmy","NZDJPYmy","EURJPYmy",
                     "AUDCADmy","AUDCHFmy","AUDNZDmy","CADCHFmy","CADJPYmy","EURAUDmy","GBPAUDmy","GBPCADmy",
                     "GBPCHFmy","GBPNZDmy","NZDUSDmy"};
                     //*/
input ENUM_TIMEFRAMES      Period_A0         = PERIOD_D1;
input ENUM_APPLIED_PRICE   InpAppliedPrice   =  PRICE_CLOSE;   // Applied price 

input group "Testeinstellungen - 3ATR (FC and SC)" 

input int               Inp_MinTrades                 = 500;                //Mindestanzahl an Trades
input double            Inp_MaxChalkAll               = 30.0;               //Maximaler Anteil Chalk Ups
input double            Inp_Min3ATR_TPRate            = 45.0;               //Minimale Anteil an 3ATR Wins nach 1ATRTP
input double            Inp_MinTPSLWinRate            = 65.0;               //Minimale WinRate (nur TP und SL ohne ChalkUps)
input double            Inp_MinWinRateAll             = 50.0;               //Minimale WinRate (alle Trades)

input group "Auswahl der Indikatorart und Buffer"
input bool     TwoLineCrossIndi2Direction             = true;                          //TLC with Two Direktion

input group "Buffer"
input bool     TwoBufferIndi                          =true;
input int      Buffer1Value                           = 0;
input int      Buffer2Value                           = 2;

input group "1. Confi" 

input int      Short=4;
input int      Media=8;
input int      Longa=95;

input group "Position Size Calculations"
      input int               InpATRperiod=14;           // ATR Periods
      input double            InpRiskPC=1.0;             // Risk Size %
      input double            InpSLfactor=1.5;           // Stop Loss as a factor of ATR
      input double            InpTPfactor=3.0;           // Second TP-Point (3ATR)
      input double            Inp1ATRfactor=1.0;         // First TP- Point (1ATR)        
     

//------------- Set variables of strategy A -----
//--- Arrays for external parameters
string            mySymbolPair[Strategy_A];
bool              myIsTrade_A[Strategy_A];
int               myPosTotalBreak[Strategy_A];
int               myPosModiValue [Strategy_A];
double            Points[Strategy_A];
int               myPosAnzahlValue[Strategy_A];

//--- Indicator handle Array und Variablen für CI1
int          FirstConfiDefinition[Strategy_A];

double          myFirstConfiBuffer1Array[];
double          myFirstConfiBuffer2Array[];
double          myFirstConfiBuffer3Array[];

double FirstConfi1Value;
double FirstConfi1Vergl;
double FirstConfi2Value;
double FirstConfi2Vergl;

//--- PositionSize Verarbeitung
int ATRDefinition[Strategy_A];
double myATRValueArray[];

bool IsNewCandle[Strategy_A];
static datetime TimeLastTickProcessed[Strategy_A]; 

//---===================== The OnInit function =======================================================
int OnInit()
  {   
//--- Copy external variables to arrays
   for(int i=0; i<Strategy_A; i++)
   {mySymbolPair[i]     =SymbolArray[i];
   myPosModiValue[i]    =0;
   myPosAnzahlValue[i]  =0; 
   IsNewCandle[i]       = false;
   TimeLastTickProcessed[i] =iTime(mySymbolPair[i],Period_A0,0); 
   }
    
  // Set the Calculation for the Symbol Points for the SL/TP Calculator
  for(int i=0; i<Strategy_A; i++)
  {Points[i] =  SymbolInfoDouble(mySymbolPair[i],SYMBOL_POINT);
  
  int Digits = int(SymbolInfoInteger(mySymbolPair[i],SYMBOL_DIGITS));
  if((SymbolInfoInteger(mySymbolPair[i],SYMBOL_DIGITS) == 3) || (SymbolInfoInteger(mySymbolPair[i],SYMBOL_DIGITS) == 5))
   {
    Points[i]*=10;
   } 
   }

   //--- Set indicator handles
   for(int i=0; i<Strategy_A; i++)
     {
      if(myIsTrade_A[i]==false) continue;

      FirstConfiDefinition[i] =iCustom(mySymbolPair[i],Period_A0,"Downloads\\Confirmation Indi\\Two Lines Cross\\d-index",
                                 Short,Media,Longa); 

      ATRDefinition[i]=iATR(mySymbolPair[i],Period_A0,InpATRperiod);
     }

// Set Values for GlobalVariables
   FirstConfi1Value= 0;
   FirstConfi1Vergl= 0;
   FirstConfi2Value= 0;
   FirstConfi2Vergl= 0;
  
   return(INIT_SUCCEEDED);
  }

//-===================== The OnTimer function ======================================================
void OnTick()
{

//--- Check if the terminal is connected to the trade server
if(TerminalInfoInteger(TERMINAL_CONNECTED)==false) return;

//--- Check for New Candle
for(int A=0; A<Strategy_A; A++)
{
           
   IsNewCandle[A] = false;
   if(TimeLastTickProcessed[A] != iTime(mySymbolPair[A],Period_A0,0))
     {
       IsNewCandle[A] = true;
       TimeLastTickProcessed[A]=iTime(mySymbolPair[A],Period_A0,0);
     }
               
 if(IsNewCandle[A]==true)
   {
   
               //--------------------------------------------------Werte der Indikatoren berechnen------------------------------------------------
                 
                 if(TwoBufferIndi == true)
                  {
                  ArraySetAsSeries(myFirstConfiBuffer1Array,true);
                  ArraySetAsSeries(myFirstConfiBuffer2Array,true);
                  CopyBuffer(FirstConfiDefinition[A],Buffer1Value,0,3,myFirstConfiBuffer1Array);
                  CopyBuffer(FirstConfiDefinition[A],Buffer2Value,0,3,myFirstConfiBuffer2Array);
                  FirstConfi1Value = NormalizeDouble(myFirstConfiBuffer1Array[1],10);
                  FirstConfi1Vergl = NormalizeDouble(myFirstConfiBuffer1Array[2],10);
                  FirstConfi2Value = NormalizeDouble(myFirstConfiBuffer2Array[1],10);
                  FirstConfi2Vergl = NormalizeDouble(myFirstConfiBuffer2Array[2],10);
                  }

               //--------------------------------------------------Ablauf der Positionen für TS,Exit------------------------------------------------    
                //---Look for First TP and Move Second positon to Break Even
                  if(PositionsTotal()>=1 && myPosModiValue[A]==0)            
                     {   
                      myPosAnzahlValue[A]=0;                        
                      for(int i =0;i <= PositionsTotal();i++)   //i-- bedeutet i= i-1  
                        {
                           ulong ticket = PositionGetTicket(i);
                           if(PositionSelectByTicket(ticket))
                              {
                               string symbol = PositionGetString(POSITION_SYMBOL);
                               string PositionComment = PositionGetString(POSITION_COMMENT);
                                 if (symbol == mySymbolPair [A])
                                 {
                                     myPosAnzahlValue[A]++;                               
                                 }
                          
                               }  
                         }
                            if (myPosAnzahlValue[A] == 1) 
                             {
                             for(int i =0;i <= PositionsTotal();i++)   //i-- bedeutet i= i-1  
                             {
                               ulong ticket = PositionGetTicket(i);
                                 if(PositionSelectByTicket(ticket))
                                     {
                                       string symbolFullTP = PositionGetString(POSITION_SYMBOL);
                                        string PositionCommentFullTP = PositionGetString(POSITION_COMMENT);
                                          double PositionOpenPriceFullTP=PositionGetDouble(POSITION_PRICE_OPEN);
                                          double PositionFullTPPrice=PositionGetDouble(POSITION_TP);
                        
                                          if(symbolFullTP==mySymbolPair[A] && PositionCommentFullTP=="FullTP")
                                                {
                                                trade.PositionModify(ticket,PositionOpenPriceFullTP,PositionFullTPPrice);
                                                myPosModiValue[A]=1;
                                                }
                                      }  
                              } 
                              }                      
                        
                     }
        
               //---Check if Positons have to be closed
                    if(PositionsTotal()>=1)
                    {
                    for(int i = PositionsTotal()-1; i>=0; i--)   //i-- bedeutet i= i-1  
                         {
                           ulong ticket = PositionGetTicket(i);
                           if(PositionSelectByTicket(ticket))
                            {
                            long type = PositionGetInteger(POSITION_TYPE);
                            string symbol = PositionGetString(POSITION_SYMBOL);
                            if(TwoLineCrossIndi2Direction == true)
                             {
                               if (symbol == mySymbolPair [A] && type == POSITION_TYPE_BUY &&
                                      FirstConfi1Value<FirstConfi2Value
                                       )
                                       {                     
                                       trade.PositionClose(ticket);
                                       myPosTotalBreak[A] = 0;
                                       Print (mySymbolPair[A]," :Position durch Exit-LONG-Fast gescchlossen. ", myPosTotalBreak[A]);
                                       }
                               if (symbol == mySymbolPair[A] && type == POSITION_TYPE_SELL &&
                                       FirstConfi1Value>FirstConfi2Value
                                       )
                                       {                                                            
                                       trade.PositionClose(ticket);
                                       myPosTotalBreak[A] = 0;
                                       Print (mySymbolPair[A]," :Position durch Exit-SHORT-Fast gescchlossen. ", myPosTotalBreak[A]);
                                       }
                              }            
                           }
                         }
                             
                     }
                     
                //--- Check if one Position for the Symbol is given if yes dont do anything else
                        if (PositionsTotal()>0)
                           {
                           int cntMyPos=PositionsTotal();
                           for(int ti=cntMyPos-1; ti>=0; ti--)
                           {
                           // skip if there is a position for the current symbol
                           if(PositionGetSymbol(ti) == mySymbolPair[A] )
                              {
                              myPosTotalBreak[A] = 1;
                              break;
                              }
                           else {
                                  myPosTotalBreak[A] = 0;
                                }
                           }
                           }
                           else {
                                 myPosTotalBreak[A] = 0;
                                 }
                           
               //--- Calculate SL and TP Values and Check for opening a Position (if no position is open)          
               if (myPosTotalBreak[A]==0)
                  {          
                        double ask = SymbolInfoDouble(mySymbolPair[A], SYMBOL_ASK);
                        double bid = SymbolInfoDouble(mySymbolPair[A], SYMBOL_BID); 
                        myPosModiValue[A]=0;
                        myPosAnzahlValue[A]=0;
                        
                        //Set Arrays straid
                        ArraySetAsSeries(myATRValueArray,true);  
                        CopyBuffer(ATRDefinition[A],0,0,3,myATRValueArray);
                        double ATRValue = NormalizeDouble(myATRValueArray[1],int(SymbolInfoInteger(mySymbolPair[A],SYMBOL_DIGITS)));
                        double ATRPoints = ATRValue / SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);                         //Get the ATR in points to calc SL and TP
                        // Print("ATRPoints: ", ATRPoints);
                        
                        double ATRPointslotSize = (ATRPoints/10);                     //Risk in Account Currency
                        double slpoints=(ATRPointslotSize*InpSLfactor);                     //Risk in Counter Currency
                        double PipsToRisk = slpoints; 
                        double freeMargin = AccountInfoDouble(ACCOUNT_EQUITY); 
                        double PipValue = (((SymbolInfoDouble(mySymbolPair[A], SYMBOL_TRADE_TICK_VALUE))*Points[A])/(SymbolInfoDouble(mySymbolPair[A],SYMBOL_TRADE_TICK_SIZE)));                               //Risk in currency per point
                        //Print("PipValue: ",PipValue);
                        double lotSize = (InpRiskPC/100) * freeMargin / (PipValue * PipsToRisk);
                        //Print ("LotSize is: "+ (string)NormalizeDouble(lotSize,2));
                        double askPoint = SymbolInfoDouble(mySymbolPair[A], SYMBOL_ASK)/SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                        double bidPoint = SymbolInfoDouble(mySymbolPair[A], SYMBOL_BID)/SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                     
                        double buySLPoints = -1*ATRPoints*InpSLfactor;
                        double buySLPrice = (askPoint + buySLPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                        double buyTPPoints = ATRPoints * InpTPfactor;
                        double buyTPPrice = (askPoint + buyTPPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                        double buy1ATRPoints = ATRPoints * Inp1ATRfactor;
                        double buy1ATRPrice = (askPoint + buy1ATRPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                        
                        double sellSLPoints = ATRPoints*InpSLfactor;
                        double sellSLPrice = (bidPoint + sellSLPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);
                        double sellTPPoints = -1*ATRPoints*InpTPfactor;
                        double sellTPPrice = (bidPoint + sellTPPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);          
                        double sell1ATRPoints = -1*ATRPoints*Inp1ATRfactor;
                        double sell1ATRPrice = (bidPoint + sell1ATRPoints)*SymbolInfoDouble(mySymbolPair[A],SYMBOL_POINT);            
                                  
                                 
                         double PositionLotsHalf = (NormalizeDouble(lotSize,2) - MathMod( NormalizeDouble(lotSize,2), 2*SymbolInfoDouble(mySymbolPair[A], SYMBOL_VOLUME_STEP )))/2; 
                        //Print("LotSizeHalf is: " + (string)PositionLotsHalf);      
                        if (PositionLotsHalf  < 0.01) {PositionLotsHalf = 0.01;}
                  
                           //Open Trade Conditions
                              if(TwoLineCrossIndi2Direction == true) 
                                    {
                                    if(FirstConfi1Value>FirstConfi2Value && FirstConfi1Vergl<FirstConfi2Vergl)                         
                                       {
                                           trade.PositionOpen(mySymbolPair[A],ORDER_TYPE_BUY,NormalizeDouble((PositionLotsHalf),2),ask,buySLPrice,buyTPPrice,"FullTP");
                                           trade.PositionOpen(mySymbolPair[A],ORDER_TYPE_BUY,NormalizeDouble((PositionLotsHalf),2),ask,buySLPrice,buy1ATRPrice,"ATR1TP");
                                       }
                              
                                    if (FirstConfi1Value<FirstConfi2Value && FirstConfi1Vergl>FirstConfi2Vergl)
                                          {
                                          trade.PositionOpen(mySymbolPair[A],ORDER_TYPE_SELL,NormalizeDouble((PositionLotsHalf),2),bid,sellSLPrice,sellTPPrice,"FullTP");
                                          trade.PositionOpen(mySymbolPair[A],ORDER_TYPE_SELL,NormalizeDouble((PositionLotsHalf),2),bid,sellSLPrice,sell1ATRPrice,"ATR1TP");               
                                          }
                                    }                                           
                  }

}  //Ends is NewCandle
}  //End For (all Symbols)
}  //Ends OnTick


//-===================== The OnDeinit function ============================
void OnDeinit(const int reason)
 
  {
//--- Delete indicator handles
   for(int i=0; i<Strategy_A; i++)
     {
      IndicatorRelease(FirstConfiDefinition[i]);
      IndicatorRelease(ATRDefinition[i]);      
     }
        
  }  

//+-----------------------------------------+
//| END OF PROGRAM                          |
//+-----------------------------------------+
 

Some posts that do not make sense have been deleted. Replies have also been deleted.

Please note that this is an English language forum so post in English only.

 
Thanks a lot
 
Thomas Behnke #:

I try to trade multiple currencys on the daily timeframe. I test in in Strategy-Tester with OpenPriceOnly.

I will not undertake to analyze the behavior of the tester on several trading symbols.

 
Thomas Behnke #: Hi fxsaber, thanks again. Ich will post the Code here. I have erased everything that is not important for the trades. cause it is too long. hope it is enough. if not tell me and I attach the file with the complete code. I try to trade multiple currencys on the daily timeframe. I test in in Strategy-Tester with OpenPriceOnly. I know my code is not pretty and I didnt use functions. sorry for that :S It isnt suppost to work as an EA in Live Trading. It only should give me correct data on the onTester-Function in Strategy-Tester (It only counts Wins and loses). But for that the Trades have to work.... Hope you still can read it/its still ok to understand.

have a great day!

I don't think that many users will be willing to undertake testing and debugging your code for you for free, because it could end up taking many hours if not longer and your code is not well structured.

You should consider doing this kind thing on your own, either by using the MetaEditor debugger or by using "Print()" to output to the log.

This is part of what a developer does on a daily basis, but it all begins by writing clean and properly structured code.

So, start by improving your code quality to make it easier for you to debug it.

 

Hi fxsaber and Hi Fernando,


thanks for your answers, I will try to figure it out on my own. Thanks for your help anyway!

Can you mybe give me a hint how to give it a better strutcture? like using more functions and not writing all in the OnTick function or am I doing something very wrong on one point?

If not its fine. I know my code is messy. I try to improve it everytime I work with it^^

Have a great day!

Thomas

Reason: