Strategy tester trades not closing the strategy tester's opened ACTIVE trades

 

Strategy tester trades not closing it's opened ACTIVE trades

First, I apologize of this has been touched on. I have spent literal days digging through the mql4/5 forums and there is soo much touching on the topic, but not addressing it exactly, or the proposed changes do not work.


Hello,

This topic has been opened many times all over the forums, but I cannot seem to either:

A: get this working based on all of the responses over the years, or

B: It's just not supported (which based on the documentation is not clear).


I want to stress, I am not trying to close broker account trades. I only want to handle the trades that were opened within the strategy tester itself. I have tried getting around this using a trailing method, but I am still struggling to find a method for this that works well.


The following code examples do not work, even though some people claim that they do. They do however work OUTSIDE of the strategy tester and in a live environment.

  for (int i=PositionsTotal()-1; i>=0 ; i--){
                              int ticket=PositionGetTicket(i);
                              m_trade.PositionClose(i);
                           }


void Close_all()
  {
   CTrade         m_trade; // Trades Info and Executions library
   COrderInfo     m_order; //Library for Orders information
   CPositionInfo  m_position; // Library for all position features and information
//--Đóng Positions
   for(int i = PositionsTotal() - 1; i >= 0; i--) // loop all Open Positions
      if(m_position.SelectByIndex(i))  // select a position
        {
         m_trade.PositionClose(m_position.Ticket()); // then close it --period
         Sleep(100); // Relax for 100 ms
        }
//--End  Positions

//-- Orders
   for(int i = OrdersTotal() - 1; i >= 0; i--) // loop all Orders
      if(m_order.SelectByIndex(i))  // select an order
        {
         m_trade.OrderDelete(m_order.Ticket()); // then delete it --period
         Sleep(100); // Relax for 100 ms
        }
//--End 
//-- Positions
   for(int i = PositionsTotal() - 1; i >= 0; i--) // loop all Open Positions
      if(m_position.SelectByIndex(i))  // select a position
        {
         m_trade.PositionClose(m_position.Ticket()); // then close it --period
         Sleep(100); // Relax for 100 ms
        }
//--End 
  }// End func Close_all


//+-------------------------------------------------------------------+
//| Close any pending orders                                          |
//+-------------------------------------------------------------------+
   void closePendingOrders(){
   
      int ord_total=OrdersTotal();
   
      if(ord_total > 0){
         for(int i=ord_total-1;i>=0;i--){
         
            ulong CPO_ticketNum=OrderGetTicket(i);
            if(OrderSelect(CPO_ticketNum) && OrderGetString(ORDER_SYMBOL)==Symbol()){
               CTrade *trade=new CTrade();
               trade.OrderDelete(CPO_ticketNum);
               delete trade;
            }
         }
      }
   return;
   }


Thank you for any knowledge you may pass my direction.

 

AFAIK the tester closes active trades automatically at the end of test. Please, provide logs/screenshots if it happens otherwise in your environment.

As for the codes, please provide more details on how exactly the codes do not work - I think you should provide more code context for others to understand when and how you call these functions.

 

This comment alone is what scared from from opening this topic to begin with.

https://www.mql5.com/en/forum/378112#comment_24767641

Vladimir Karputov  2021.09.22 09:42     EN

"I repeat once again: the strategy tester DOES NOT SEE the positions that are open on your account."


I've read this thread a couple times, and it appears to me that the person is trying to close active broker trades. Clearly, and it makes sense that, that the strategy tester cannot see any trades associated to any broker accounts.


I did run Vladamir's code within the Strategy tester and got this:

https://snipboard.io/dnfMJR.jpg

Image description


//+------------------------------------------------------------------+
//|                                      Check SYMBOL_ORDER_MODE.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//|                      https://www.mql5.com/en/users/barabashkakvn |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property link      "https://www.mql5.com/en/users/barabashkakvn"
#property version   "1.00"
//---
int symboll_order_types[7]= {SYMBOL_ORDER_MARKET,
                             SYMBOL_ORDER_LIMIT,
                             SYMBOL_ORDER_STOP,
                             SYMBOL_ORDER_STOP_LIMIT,
                             SYMBOL_ORDER_SL,
                             SYMBOL_ORDER_TP,
                             SYMBOL_ORDER_CLOSEBY
                            };
string symboll_order_description[7]= {"Market orders",
                                      "Limit orders",
                                      "Stop orders",
                                      "Stop-limit orders",
                                      "Stop Loss",
                                      "Take Profit",
                                      "Close By operations"
                                     };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   for(int i=0; i<7; i++)
     {
      if(IsOrderTypesAllowed(Symbol(),symboll_order_types[i]))
         Print(Symbol()," ",symboll_order_description[i]," allowed");
      else
         Print(Symbol()," ",symboll_order_description[i]," prohibited");
     }
  }
//+------------------------------------------------------------------+
//| Check if a order types is allowed                                |
//+------------------------------------------------------------------+
bool IsOrderTypesAllowed(string symbol,int order_type)
  {
//--- receive the value of the property describing allowed order types
   int symbol_order_mode=(int)SymbolInfoInteger(symbol,SYMBOL_ORDER_MODE);
//--- return 'true' if the order_type is allowed
   return((symbol_order_mode&order_type)==order_type);
  }
//+------------------------------------------------------------------+
Vladimir Karputov
Vladimir Karputov
  • 2024.07.08
  • www.mql5.com
Trader's profile
 
 for (int i=PositionsTotal()-1; i>=0 ; i--){
                              int ticket=PositionGetTicket(i);
                              m_trade.PositionClose(i);

What argument does PositionClose require? I doubt it is an index.

 
blackbic #:

This comment alone is what scared from from opening this topic to begin with.

I've read this thread a couple times, and it appears to me that the person is trying to close active broker trades. Clearly, and it makes sense that, that the strategy tester cannot see any trades associated to any broker accounts.


The tester is completely isolated from your actual account. As for the additional script - it appears irrelevant to your initially stated problem - please be more specific.

 
Stanislav Korotky #:

The tester is completely isolated from your actual account. As for the additional script - it appears irrelevant to your initially stated problem - please be more specific.


Hi Stanislav,

Thanks for your prompt reply.


We are looking to automatically close an active open trade if the market changes, not at the end of the test, but during the test. Just as if we were trading in real life.


The zig zag code is sending a 1 (buy signal) or 2 (sell signal) to the EA. The EA will place a trade based on the signal. If the signal is 0 (do nothing).


If we are in a buy movement, and the signal changes to a sell while an open trade is active, then we want to close the trade and open in the opposite direction. This close is not happening in the strategy tester only.


OK, you wanted meat. Here it is. I've simplified my code. Based on your responses, it's not a limitation with the strategy tester it appears.


Zig Zag Indicator code:

Zigzag code:

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//---- plot Zigzag
#property indicator_label1  "Zigzag"
#property indicator_type1   DRAW_SECTION
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      ExtDepth=12;
input int      ExtDeviation=5;
input int      ExtBackstep=3;
//--- indicator buffers
double         ZigzagBuffer[];      // main buffer
double         HighMapBuffer[];     // highs
double         LowMapBuffer[];      // lows
int            level=3;             // recounting depth
double         deviation;           // deviation in points
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);

//--- set short name and digits  
   PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")");
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- set empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- to use in cycle
   deviation=ExtDeviation*_Point;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|  searching index of the highest bar                              |
//+------------------------------------------------------------------+
int iHighest(const double &array[],
             int depth,
             int startPos)
  {
   int index=startPos;
//--- start index validation
   if(startPos<0)
     {
      Print("Invalid parameter in the function iHighest, startPos =",startPos);
      return 0;
     }
   int size=ArraySize(array);
//--- depth correction if need
   if(startPos-depth<0) depth=startPos;
   double max=array[startPos];
//--- start searching
   for(int i=startPos;i>startPos-depth;i--)
     {
      if(array[i]>max)
        {
         index=i;
         max=array[i];
        }
     }
//--- return index of the highest bar
   return(index);
  }
//+------------------------------------------------------------------+
//|  searching index of the lowest bar                               |
//+------------------------------------------------------------------+
int iLowest(const double &array[],
            int depth,
            int startPos)
  {
   int index=startPos;
//--- start index validation
   if(startPos<0)
     {
      Print("Invalid parameter in the function iLowest, startPos =",startPos);
      return 0;
     }
   int size=ArraySize(array);
//--- depth correction if need
   if(startPos-depth<0) depth=startPos;
   double min=array[startPos];
//--- start searching
   for(int i=startPos;i>startPos-depth;i--)
     {
      if(array[i]<min)
        {
         index=i;
         min=array[i];
        }
     }
//--- return index of the lowest bar
   return(index);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int i=0;
   int limit=0,counterZ=0,whatlookfor=0;
   int shift=0,back=0,lasthighpos=0,lastlowpos=0;
   double val=0,res=0;
   double curlow=0,curhigh=0,lasthigh=0,lastlow=0;
   int H=0, L=0, direction=0; 

//--- auxiliary enumeration
   enum looling_for
     {
      Pike=1,  // searching for next high
      Sill=-1  // searching for next low
     };
//--- initializing
   if(prev_calculated==0)
     {
      ArrayInitialize(ZigzagBuffer,0.0);
      ArrayInitialize(HighMapBuffer,0.0);
      ArrayInitialize(LowMapBuffer,0.0);
     }
//---
   if(rates_total<100) return(0);
//--- set start position for calculations
   if(prev_calculated==0) limit=ExtDepth;

//--- ZigZag was already counted before
   if(prev_calculated>0)
     {
      i=rates_total-1;
      //--- searching third extremum from the last uncompleted bar
      while(counterZ<level && i>rates_total-100)
        {
         res=ZigzagBuffer[i];
         if(res!=0) counterZ++;
         i--;
        }
      i++;
      limit=i;

      //--- what type of exremum we are going to find
      if(LowMapBuffer[i]!=0)
        {
         curlow=LowMapBuffer[i];
         whatlookfor=Pike;
        }
      else
        {
         curhigh=HighMapBuffer[i];
         whatlookfor=Sill;
        }
      //--- chipping
      for(i=limit+1;i<rates_total && !IsStopped();i++)
        {
         ZigzagBuffer[i]=0.0;
         LowMapBuffer[i]=0.0;
         HighMapBuffer[i]=0.0;
        }
     }

//--- searching High and Low
   for(shift=limit;shift<rates_total && !IsStopped();shift++)
     {
      val=low[iLowest(low,ExtDepth,shift)];
      if(val==lastlow){
         val=0.0;
         L++;
      }
      else
        {
         lastlow=val;
         if((low[shift]-val)>deviation){
            val=0.0;
            L++;
         }
         else
           {
            for(back=1;back<=ExtBackstep;back++)
              {
               res=LowMapBuffer[shift-back];
               if((res!=0) && (res>val)) LowMapBuffer[shift-back]=0.0;
              }
           }
        }
      if(low[shift]==val) LowMapBuffer[shift]=val; else LowMapBuffer[shift]=0.0;
      //--- high
      val=high[iHighest(high,ExtDepth,shift)];
      if(val==lasthigh) val=0.0;
      else
        {
         lasthigh=val;
         if((val-high[shift])>deviation){
            val=0.0;
            H++;
         }
         else
           {
            for(back=1;back<=ExtBackstep;back++)
              {
               res=HighMapBuffer[shift-back];
               if((res!=0) && (res<val)) {
                  HighMapBuffer[shift-back]=0.0;
                  H++;
               }
              }
           }
        }
      if(high[shift]==val) HighMapBuffer[shift]=val; else HighMapBuffer[shift]=0.0;
     }
         
     if (H > L){
        direction=1;
                GlobalVariableSet("loc",1); // BUY = 1
     } else if (H == L){
        direction=0;
                GlobalVariableSet("loc",0); // do nothing
     }else{
        direction=2;
                GlobalVariableSet("loc",2); // SELL = 2
     } 
         
         GlobalVariableSet("lasthigh",lasthigh);
         GlobalVariableSet("lastlow",lastlow);
         
         
//--- last preparation
   if(whatlookfor==0)// uncertain quantity
     {
      lastlow=0;
      lasthigh=0;
     }
   else
     {
      lastlow=curlow;
      lasthigh=curhigh;
     }

//--- final rejection
   for(shift=limit;shift<rates_total && !IsStopped();shift++)
     {
      res=0.0;
      switch(whatlookfor)
        {
         case 0: // search for peak or lawn
            if(lastlow==0 && lasthigh==0)
              {
               if(HighMapBuffer[shift]!=0)
                 {
                  lasthigh=high[shift];
                  lasthighpos=shift;
                  whatlookfor=Sill;
                  ZigzagBuffer[shift]=lasthigh;
                  res=1;
                 }
               if(LowMapBuffer[shift]!=0)
                 {
                  lastlow=low[shift];
                  lastlowpos=shift;
                  whatlookfor=Pike;
                  ZigzagBuffer[shift]=lastlow;
                  res=1;
                 }
              }
            break;
         case Pike: // search for peak
            if(LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)
              {
               ZigzagBuffer[lastlowpos]=0.0;
               lastlowpos=shift;
               lastlow=LowMapBuffer[shift];
               ZigzagBuffer[shift]=lastlow;
               res=1;
              }
            if(HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
              {
               lasthigh=HighMapBuffer[shift];
               lasthighpos=shift;
               ZigzagBuffer[shift]=lasthigh;
               whatlookfor=Sill;
               res=1;
              }
            break;
         case Sill: // search for lawn
            if(HighMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh && LowMapBuffer[shift]==0.0)
              {
               ZigzagBuffer[lasthighpos]=0.0;
               lasthighpos=shift;
               lasthigh=HighMapBuffer[shift];
               ZigzagBuffer[shift]=lasthigh;
              }
            if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
              {
               lastlow=LowMapBuffer[shift];
               lastlowpos=shift;
               ZigzagBuffer[shift]=lastlow;
               whatlookfor=Pike;
              }
            break;
         default: return(rates_total);
        }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


EA Code:

//+------------------------------------------------------------------+
//|                                                         test.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+--------------------------------------------+
//|  DEBUGS ENABLED                            |
//+--------------------------------------------+
input double volume=1;
input ulong m_magic = 154897;         // magic number

input string DEBUGS_NOT          =":::::::::::::::::::::::::::::::::::::::::::::::::::::"; //____DEBUGS____
input bool debugs_other = false; // Other Debugs

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>  

#property tester_indicator "\\Experts\Advisors\zigzag.ex5"
#property script_show_inputs

#resource "\\Experts\Advisors\zigzag.ex5"


int ActiveTrades, Total_Active_Trades=1;
double last_high,last_low;

int handle_iCustom;// variable for storing the handle of the iCustom indicator 

CPositionInfo  m_position;                   // trade position object
CTrade         m_trade;                      // trading object
CSymbolInfo    m_symbol;                     // symbol info object

   //+------------------------------------------------------------------+
   //| Expert initialization function                                   |
   //+------------------------------------------------------------------+
   int OnInit(){

      m_trade.SetExpertMagicNumber(m_magic);
      
      //--- create handle of the indicator iCustom
      handle_iCustom=iCustom(_Symbol,Period(),"::Experts\Advisors\zigzag.ex5");
      //--- if the handle is not created 
      
      if(handle_iCustom==INVALID_HANDLE){
         //--- tell about the failure and output the error code 
         PrintFormat("Failed to create handle of the iCustom indicator for the symbol %s/%s, error code %d",
                     _Symbol,
                     EnumToString(Period()),
                     GetLastError());
   
         //--- the indicator is stopped early 
         return(INIT_FAILED);
        }
   
      //--- create timer
      EventSetTimer(60);
   
   return(INIT_SUCCEEDED);
   }
   //+------------------------------------------------------------------+
   //| Expert deinitialization function                                 |
   //+------------------------------------------------------------------+
   void OnDeinit(const int reason){

      //--- destroy timer
      EventKillTimer();
   }
   //+------------------------------------------------------------------+
   //| Timer function                                                   |
   //+------------------------------------------------------------------+
   void OnTimer(){

      MqlTradeRequest request;
      MqlTradeResult result;

      MqlTradeCheckResult check;
   
      ZeroMemory(request);
      ZeroMemory(result);
      ZeroMemory(check);
       
      double current_ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

      last_high = GlobalVariableGet("lasthigh");
      last_low = GlobalVariableGet("lastlow");
      
      //---Get Number of active trades
      ActiveTrades = 0;
      Total_Active_Trades=0;

      for (int i=PositionsTotal()-1; i>=0; i--){
         string symbol = PositionGetSymbol(i);
      
         if(Symbol() == symbol){   
            ActiveTrades++;
         }
      }
      Total_Active_Trades=(ActiveTrades+OrdersTotal());
      
      
      if ( Total_Active_Trades > 0 ){
      
          if ( GlobalVariableGet("loc") == 1 && (current_ask < last_low) ){
            Close_all();
          }
          
          if ( GlobalVariableGet("loc") == 2 && (current_ask > last_high) ){
            Close_all();
          }
      }
          
      if ( Total_Active_Trades < 1 ){
      
         if ( GlobalVariableGet("loc") == 2 ){ 
         
            request.action = TRADE_ACTION_DEAL;
            request.type = ORDER_TYPE_SELL;
            request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
            request.magic = m_magic;            
            request.symbol = _Symbol;
            request.volume = volume;
            request.type_filling = ORDER_FILLING_FOK;
           
            request.sl = last_high;
            request.tp = (last_high - last_low)-last_low;   
            request.deviation = 20;
            
            OrderSend(request, result);
            
            if(result.retcode ==10009 || result.retcode == 10008){
                Alert("Order has been placed ",result.order);
            }else {
                string trade_entry_error;
                if (GetLastError() == 4701)trade_entry_error="Wrong account property ID";
                if (GetLastError() == 4751)trade_entry_error="Wrong trade property ID";
                if (GetLastError() == 4752)trade_entry_error="Trading by Expert Advisors prohibited";
                if (GetLastError() == 4753)trade_entry_error="Position not found";
                if (GetLastError() == 4754)trade_entry_error="Order not found";
                if (GetLastError() == 4755)trade_entry_error="Deal not found";
                if (GetLastError() == 4756)trade_entry_error="Trade request sending failed";
                if (GetLastError() == 4758)trade_entry_error="Failed to calculate profit or margin";
                Print(" The sell order could not be completed: ",trade_entry_error);
                ResetLastError();
            }
         }
         if ( GlobalVariableGet("loc") == 1 ){ 

            request.action = TRADE_ACTION_DEAL;
            request.type = ORDER_TYPE_BUY;
            request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
            request.magic = m_magic;          
            request.symbol = _Symbol;
            request.volume = volume;
            request.type_filling = ORDER_FILLING_FOK;
            
            request.sl = last_low;
            request.tp = (last_high - last_low)+last_high;                              
            request.deviation = 20;       
                                         
            OrderSend(request, result);               
            
            if(result.retcode ==10009 || result.retcode == 10008){
               Alert("Order has been placed ",result.order);
            }else {
               string trade_entry_error;
               if (GetLastError() == 4701)trade_entry_error="Wrong account property ID";
               if (GetLastError() == 4751)trade_entry_error="Wrong trade property ID";
               if (GetLastError() == 4752)trade_entry_error="Trading by Expert Advisors prohibited";
               if (GetLastError() == 4753)trade_entry_error="Position not found";
               if (GetLastError() == 4754)trade_entry_error="Order not found";
               if (GetLastError() == 4755)trade_entry_error="Deal not found";
               if (GetLastError() == 4756)trade_entry_error="Trade request sending failed";
               if (GetLastError() == 4758)trade_entry_error="Failed to calculate profit or margin";
               Print(" The sell order could not be completed: ",trade_entry_error);
               ResetLastError();
            }  
         } 
      }     
   }
//-------------------------------------------------------------------------
   void Close_all()
     {
      CTrade         m_trade; // Trades Info and Executions library
      COrderInfo     m_order; //Library for Orders information
      CPositionInfo  m_position; // Library for all position features and information
   //--Đóng Positions
      for(int i = PositionsTotal() - 1; i >= 0; i--) // loop all Open Positions
         if(m_position.SelectByIndex(i))  // select a position
           {
            m_trade.PositionClose(m_position.Ticket()); // then close it --period
            Sleep(100); // Relax for 100 ms
           }
   //--End  Positions
   
   //-- Orders
      for(int i = OrdersTotal() - 1; i >= 0; i--) // loop all Orders
         if(m_order.SelectByIndex(i))  // select an order
           {
            m_trade.OrderDelete(m_order.Ticket()); // then delete it --period
            Sleep(100); // Relax for 100 ms
           }
   //--End 
   //-- Positions
      for(int i = PositionsTotal() - 1; i >= 0; i--) // loop all Open Positions
         if(m_position.SelectByIndex(i))  // select a position
           {
            m_trade.PositionClose(m_position.Ticket()); // then close it --period
            Sleep(100); // Relax for 100 ms
           }
   //--End 
     }// End func Close_all
//-------------------------------------------------------------------------
 
William Roeder #:

What argument does PositionClose require? I doubt it is an index.


Hi William,

We get a zero in response to that request. It appears to me that it's trying to pull the value from an account, and not from the strategy tester itself.

 
blackbic #:


We are looking to automatically close an active open trade if the market changes, not at the end of the test, but during the test. Just as if we were trading in real life.

The zig zag code is sending a 1 (buy signal) or 2 (sell signal) to the EA. The EA will place a trade based on the signal. If the signal is 0 (do nothing).


I suggest you to start with a simple EA which just opens and closes trades without a signal. This way you'll check that your trading part of code works as expected.

If it succeeds (including closure), then you can move to a specific signals, such as ZigZag or others.

On the 1-st glance, your problem can be that you use global variables and do not syncing access to them, so EA just can't read what the indicator sets at correct moments. Hint: use GlobalVariableSetOnCondition. In the tester everything happens much faster than online, which is why synchronization issues may not produce visible effects online (for some time).

Also your indicator probably requires the #property tester_everytick_calculate to catch price movements during testing.

Documentation on MQL5: Global Variables of the Terminal / GlobalVariableSetOnCondition
Documentation on MQL5: Global Variables of the Terminal / GlobalVariableSetOnCondition
  • www.mql5.com
Sets the new value of the existing global variable if the current value equals to the third parameter check_value. If there is no global variable...
 
Stanislav Korotky #:
syncing access to them


Thank you Stanislav,

Can you please clarify what you mean "do not syncing access them"? Is there a known issue working with global variables in ST?


The ZigZag is setting every tick:

         GlobalVariableSet("lasthigh",lasthigh);
         GlobalVariableSet("lastlow",lastlow);


and the EA is reading every 60 seconds:

      last_high = GlobalVariableGet("lasthigh");
      last_low = GlobalVariableGet("lastlow");


We are getting the variables correctly if your Print them to the Journal.

 
blackbic #:


Thank you Stanislav,

Can you please clarify what you mean "do not syncing access them"? Is there a known issue working with global variables in ST?

The ZigZag is setting every tick:

and the EA is reading every 60 seconds:

We are getting the variables correctly if your Print them to the Journal.

Above I provided a link in my answer for syncing global variables (at writing).

If you see correct values both in indicator and EA, then check/debug the trading part of code as I suggested w/o a signal.

 
blackbic #:


Can you please clarify what you mean "do not syncing access them"? Is there a known issue working with global variables in ST?


MQL programs (indicator and EA) runs in separate threads, each of which can be paused and resumed by operating system behind the scenes at any microscopic moment. So you can set one variable but not another, and inbetween of this EA tries to read incomplete set of data.