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
"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
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+

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.
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.
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 //-------------------------------------------------------------------------
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.

- www.mql5.com
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.
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.
Can you please clarify what you mean "do not syncing access them"? Is there a known issue working with global variables in ST?

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
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.
Thank you for any knowledge you may pass my direction.