Any questions from newcomers on MQL4 and MQL5, help and discussion on algorithms and codes - page 493

 
Roman Sharanov:
Could you please advise whether the function of closing all orders opened by the EA by the symbol is implemented correctly?

The architecture itself is correct. The errors are in the lack of checks and the use of some functions:

bool OrderCloseAll()
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
         if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)
            continue;

         if(OrderSymbol() !=Symbol() || OrderMagicNumber() != Magic)
            continue;
         
         if (!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage, clrWhite))
            return false;
   }

   return true;
}

  1. The first iteration in your case will fail - the order with the index OrdersTotal() does not exist.
  2. There is no check for the result of the OrderSelect function.
  3. There is no check for the result of function OrderClose. If the order closing fails, we can't stay in the same function, since we have to find out why the closing was unsuccessful. To do this, we have to leave the function with the result false, and then decide what to do next.
  4. We can't use one and the same closing price for all orders. First, orders may be of different types and, second, the price is likely to have changed over the time of executing previous orders (at closing). We can use an MT4 feature to avoid guessing what price to use: the OrderClosePrice() value of a market order prior to its closing is the Bid or Ask price depending on the order type.
 
Ihor Herasko:

The architecture itself is correct. The errors are in the lack of checks and the use of some functions:

  1. The first iteration in your case will fail - the order with the index OrdersTotal() does not exist.
  2. There is no check for the result of the OrderSelect function.
  3. There is no check for the result of function OrderClose. If the order closing fails, we can't stay in the same function, since we have to find out why the closing was unsuccessful. To do this, we have to leave the function with the result false, and then decide what to do next.
  4. We can't use one and the same closing price for all orders. First, the orders can be of different types and, second, the price is likely to have changed during the execution of previous orders (at closing). To avoid guessing which price to use, we can use an MT4 feature: the OrderClosePrice() value of a market order prior to its closing is the Bid or Ask price depending on the order type.

Thank you, the main problem was probably just using the same price

 

From OrderSelect help " When orders are sequentially selected using SELECT_BY_POS parameter, the information is given in the order in which it came from the trade server. No sorting of the order list obtained is guaranteed".

If we think that this phrase was inserted in the help for nothing, we are OK. If we think that it was there for a reason, we should not change this list during the loop's run through the list of orders. How the orders will be ordered after the deletion of one of them on the server and the arrival of a new, current list with a smaller OrdersTotal, is unknown. It is more reliable, without deleting, to run through the same unchanged copy of the list and collect (in an array) all of the ticket numbers of the trades to be deleted. Then forget about that list and delete the trades, selecting them by ticket.

One would like to believe, of course, that the orderliness in the modifiable list is preserved, if only for this case of removing several orders from the end of an unordered list, but the developers are against it... Now it works, and if new build comes out - "we warned".

 
Vladimir:

From OrderSelect help " When orders are sequentially selected using SELECT_BY_POS parameter, the information is given in the order in which it came from the trade server. No sorting of the order list obtained is guaranteed".

If we think that this phrase was inserted in the help for nothing, we are OK. If we think that it was there for a reason, we should not change this list during the loop's run through the list of orders. How the orders will be ordered after the deletion of one of them on the server and the arrival of a new, current list with a smaller OrdersTotal, is unknown. It is more reliable, without deleting, to run through the same unchanged copy of the list and collect (in an array) all of the ticket numbers of the trades to be deleted. Then forget about that list and delete the trades, selecting them by ticket.

One would like to believe, of course, that the orderliness in the modifiable list is preserved, if only for this case of removing several orders from the end of an unordered list, but the developers are against it... Now it works, and if new build comes out - "we warned".

Such "America" has been open for about three hundred years :)

 
Artyom Trishkin:

This kind of "America" has been open for like three hundred years :)

I don't think the people asking questions here on behalf of newcomers have already discovered it themselves. That's why I'm writing it. Not for the moderators, but for the questioners. Look at the name of the thread.

P.S. I looked up where this interest came from. Turns out it's from the https://www.mql5.com/ru/forum/215783/page8 branch "Organising the Order Cycle". As it turns out, in October 2017, those three hundred years aren't over yet, there's still novelty.

Организация цикла перебора ордеров
Организация цикла перебора ордеров
  • 2017.09.16
  • www.mql5.com
MQL4 и MetaTrader 4: Организация цикла перебора ордеров
 
Vladimir:

I don't think the people asking questions here on behalf of newcomers have already discovered it themselves. That's why I'm writing it. Not for the moderators, but for the questioners. Look at the name of the thread.

P.S. I looked where this interest comes from. Turns out it's from the https://www.mql5.com/ru/forum/215783/page8 branch "Organising the order cycle". As it turns out, in October 2017 those three hundred years are not over yet, there is still novelty.

Wrong again :) Three hundred years started back at mql4.com - there was a time when it was actively discussed there. And there were even those moments that are described by you in "Now it works, and a new build will come out - "we warned". Only without warnings, and so several times - it depends, it doesn't depend on sorting...

And, yes, there is a special thread for such answers:

Особенности языка mql4, тонкости и приёмы работы
Особенности языка mql4, тонкости и приёмы работы
  • 2017.02.24
  • www.mql5.com
В данной теме будут обсуждаться недокументированные приёмы работы с языком mql4, примеры решения тех, или иных задач...
 
Vladimir:

From OrderSelect help " When orders are sequentially selected using SELECT_BY_POS parameter, the information is given in the order in which it came from the trade server. No sorting of the order list obtained is guaranteed".

If we think that this phrase was inserted in the help for nothing, we are OK. If we think that it was there for a reason, we should not change this list during the loop's run through the list of orders. How the orders will be ordered after the deletion of one of them on the server and the arrival of a new, current list with a smaller OrdersTotal, is unknown. It is more reliable, without deleting, to run through the same unchanged copy of the list and collect (in an array) all of the ticket numbers of the trades to be deleted. Then forget about that list and delete the trades, selecting them by ticket.

I would like, of course, to believe that the ordering in the modifiable list is preserved at least for this case of deleting several orders from the end of an unordered list, but the developers are against it... Now it works, and if a new build comes out, "we warned you".

As a good idea (considering that there can be several Expert Advisors + trader working on the account in parallel), you can't perform trades in a loop at all. The necessary order is received, the operation is executed, the entire OnTick() is executed again (not necessarily with arrival of a new tick). And so on, until all necessary operations are executed.

Thus, forming an array to delete orders is equivalent to deleting orders in the loop.

 

There is a "Stop" button, how do I change its text to "Start" once pressed?

bool stop;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//Closed at Profit
   ObjectCreate(0,"Stop",OBJ_BUTTON,0,0,0);
   ObjectSetInteger(0,"Stop",OBJPROP_XDISTANCE,10);
   ObjectSetInteger(0,"Stop",OBJPROP_YDISTANCE,105);
   ObjectSetInteger(0,"Stop",OBJPROP_XSIZE,100);
   ObjectSetInteger(0,"Stop",OBJPROP_YSIZE,25);

   ObjectSetString(0,"Stop",OBJPROP_TEXT,"Stop");

   ObjectSetInteger(0,"Stop",OBJPROP_COLOR,White);
   ObjectSetInteger(0,"Stop",OBJPROP_BGCOLOR,Green);
   ObjectSetInteger(0,"Stop",OBJPROP_BORDER_COLOR,Green);
   ObjectSetInteger(0,"Stop",OBJPROP_BORDER_TYPE,BORDER_FLAT);
   ObjectSetInteger(0,"Stop",OBJPROP_HIDDEN,true);
   ObjectSetInteger(0,"Stop",OBJPROP_STATE,false);
   ObjectSetInteger(0,"Stop",OBJPROP_FONTSIZE,12);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
if(sparam=="Stop")
     {
      ObjectSetInteger(0,"Stop",OBJPROP_STATE,false);
      CloseAtProfit();
      stop=true;
     }
     }
 
lil_lil: There is a "Stop" button, how do I change its text to "Start" once pressed?

See my expert example

Files:
ToFile.mq4  11 kb
 
STARIJ:

Look at my Expert Advisor example

Thank you, just what I needed.

Might be helpful to know, there is an error in missing positions--- ToFile EURUSD,H1: zero divide in 'ToFile.mq4' (62,39)

/*62*/  Строка=DoubleToStr(AccountEquity()/AccountMargin()*100,2)+"%"; // Уровень=Средства/Залог
The text does not change in the tester, there is no such option?
Reason: