Циклы и закрытие или удаление заказов - страница 5

 
Eleni Anna Branou:

Пожалуйста, используйте кнопку </>, чтобы вставить свой код.


Мои извинения... Вот в правильном формате...

OrdersTotal() не корректно...

Я был удивлен тем, что циклическая последовательность кода, использующая OrdersTotal(), не дает правильных результатов (наблюдалось у двух разных брокеров).

Я использую MT4 версии 1090 на рабочем столе Linux Ubuntu-MATE 16.04, под управлением WINE 3.0.

Вот что я использовал...

Вот в чем дело:

for(int cc = 0; cc < OrdersTotal(); cc++)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);

Я заметил у двух разных брокеров, что значение OrdersTotal() не всегда совпадает с тем, что отображается на вкладке 'Trade' брокера MT4. Сначала я подумал, что это брокер заставляет OrdersTotal() работать неправильно. Когда я заметил у второго брокера, я начал задаваться вопросом, есть ли у MT4 внутренняя "проблема", или мой код был неправильным, или это проблема с правильной синхронизацией MT4 с сервером....?

Прочитав эту ветку форума, я задался вопросом, не получу ли я лучшие результаты, изменив цикл for...loop на следующий:

for(int cc = OrdersTotal() - 1; cc >= 0; cc--)
{
      if (!OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) continue;
      if (OrderSymbol() != Symbol() ) continue;
      if (OrderType() > 1) continue;    //--ignore pending trades

      OpenTradecnt++;    //--counts up for every live position of that symbol that exists
      Print("count of the open trades of this symbol is: ", OpenTradecnt);
ИЛИ, существует ли флаг или строка кода, которая обеспечит правильную синхронизацию OrdersTotal() во время события OnTick()?

Любое разъяснение по этому поводу было бы очень полезным и будет высоко оценено!

 
Simon Gniadkowski:

Это одна из самых распространенных ошибок, которые я вижу, возможно, отчасти из-за такого мусора, как Expert Advisor Builder. Поэтому я решил, что пришло время создать тему, посвященную этому вопросу, чтобы на нее можно было ссылаться в будущем.

Проблема

Давайте рассмотрим простой пример: нам нужна функция для закрытия всех открытых ордеров нашего советника, примеров много, но давайте создадим один с нуля.

Нам нужен цикл, потому что мы хотим закрыть все наши ордера для определенного советника, внутри этого цикла у нас будет код для выбора ордера, код для проверки правильности символа и магического номера и, наконец, код для закрытия ордера:

Этот код плох. . . НЕ ИСПОЛЬЗУЙТЕ ЕГО. . . Я объясню почему в следующем разделе ... .

Объяснение

Давайте проработаем приведенный выше код... строка за строкой, ордер за ордером...

Предположим, у нас есть следующие ордера, которые мы хотим закрыть, все они имеют тот же магический номер и символ, что и наш советник, поэтому мы хотим, чтобы наш код закрыл их все:

Позиция Номер билета
0111
1222
2 333
3444
4555

Первый проход по циклу:

начальное значение PositionIndex равно 0, поэтому выбирается заказ на позиции 0, билет номер 111, этот заказ успешно удаляется, а остальные заказы меняют позицию следующим образом:

Позиция Номер билета
0222
1 333
2444
3555

2-й проход по циклу:

теперь значение PositionIndex равно 1, поэтому выбирается ордер на позиции 1, билет номер 333, этот ордер успешно удаляется, а остальные ордера меняют позицию следующим образом:

Позиция Номер билета
0222
1 444
2555

3-й проход по циклу:

теперь значение PositionIndex равно 2, поэтому выбирается ордер на позиции 2, билет номер 555, этот ордер успешно удаляется, а остальные ордера меняют позицию следующим образом:

Позиция Номер билета
0222
1 444

4-й проход по циклу:

теперь значение PositionIndex равно 3 OrderSelect() пытается выбрать ордер на позиции 3 и терпит неудачу, continue переносит выполнение кода на следующее значение в цикле. ...


Пятый и последний запуск цикла:

теперь значение PositionIndex равно 4 OrderSelect() пытается выбрать ордер в позиции 4 и не удается, continue переводит выполнение кода на следующее значение в цикле ... цикл завершен.


Теперь у нас осталось 2 заказа, билеты 222 и 444, которые должны были быть закрыты, но не были... Далее, как решить эту проблему.

Решение

Следующий код является правильным подходом при закрытии открытых ордеров или удалении отложенных ордеров. ...

Ключевое отличие заключается в том, что цикл уменьшает значение от ( TotalNumberOfOrders - 1 ) до 0

.

Давайте еще раз проработаем приведенный выше код ... строка за строкой, ордер за ордером ...

У нас те же заказы, что и раньше:

Позиция Номер билета
0111
1222
2333
3444
4555

1-й проход по циклу:

начальное значение PositionIndex равно TotalNumberOfOrders - 1, что равно 5 - 1 = 4, поэтому выбирается заказ на позиции 4, номер билета 555, этот заказ успешно удаляется, а остальные заказы меняют позицию следующим образом:

Позиция Номер билета
0111
1222
2333
3444

2-й проход по циклу:

теперь значение PositionIndex равно 3, поэтому выбирается ордер на позиции 3, билет номер 444, этот ордер успешно удаляется, а остальные ордера меняют позицию следующим образом:

Позиция Номер билета
0111
1222
2333

3-й проход по циклу:

теперь значение PositionIndex равно 2, поэтому выбирается ордер на позиции 2, билет номер 333, этот ордер успешно удаляется, а остальные ордера меняют позицию следующим образом:

Позиция Номер билета
0111
1222

4-й проход по циклу:

теперь значение PositionIndex равно 1 , поэтому выбирается ордер на позиции 1, билет номер 222, этот ордер успешно удаляется, а остальные ордера меняют позицию следующим образом:

Позиция Номер билета
0111

5-й и последний проход по циклу:

теперь значение PositionIndex равно 0 поэтому выбирается заказ на позиции 0, билет номер 111, этот заказ успешно удаляется, значение 0 - последнее допустимое значение для цикла ... цикл завершен.

Мы успешно удалили все совпадающие ордера...

Ссылка на эту тему: Циклы и закрытие или удаление ордеров

Спасибо большое! Это очень понятное объяснение
 
Здравствуйте кодеры,
Я просмотрел эту тему, читая о выборе ордеров s. Действительно, у меня есть код, где я считаю, что сделал все правильно, но выбор не работает для меня, поскольку я не могу прочитать OpenPriceвыбранного ордера. Все остальное работает нормально, только эта часть кода. Я не уверен, почему.
Во всем коде есть 4 секции, где мне нужно вызвать OrderOpenPrice сразу после отправки ордера... OrderSend работает хорошо, OrderSelect не дает мне нужных результатов. Обратитесь к 1 секции кода, если вы можете помочь.
Спасибо.
 if(Protection_Step_One==1)
        {
        while(Protective_Order<0)
          {
          RefreshRates();
          Protective_Order=OrderSend(Symbol(),OP_SELL,Protective_Lots,NormalizeDouble(MarketInfo(Symbol(),MODE_BID),MarketInfo(Symbol(),MODE_DIGITS)),3,0,0,"Intermediary",MN_Sell_Intermediary_Protection,0,Cyan);
          }
  //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Addition for Clamp       
          for (int i=OrdersTotal()-1; i>=0; i--)
            {if(OrderSelect(i,SELECT_BY_POS, MODE_TRADES)==true)
               {if (OrderMagicNumber()==MN_Sell_Intermediary_Protection)
                  { RefreshRates();
                  Intermediary_OpenPrice_Sell= OrderOpenPrice();
                  }
                }
             }   
               //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>..
        if(Protective_Order!=-1)
          { 
          Protection_Step_One=0;
          RealTime_Drawing=2;
          Protective_Mode_Activated=1;
          Protective_Order=-2;
          Defcon=2;

 

Спасибо, дорогойСимон Гнядковски,

Ваш пост действительно сэкономил мое время.

 
Gelson Kasonia:
void OnStart()
{
     int Protective_Order=OrderSend(_Symbol,ORDER_TYPE_BUY,0.01,Ask,3,0,0,"Intermediary");
     if(Protective_Order<0)
          return;
     if(!OrderSelect(Protective_Order,SELECT_BY_TICKET, MODE_TRADES))
          return;
     Print(Protective_Order, " OrderOpenPrice: ", OrderOpenPrice());
}
 

Вот код, который я предлагаю для закрытия рыночных ордеров

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersBackward()
  {
   for(int i=OrdersTotal()-1; i>=0 && !IsStopped(); i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(!OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))

            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
        }
     }
  }

И я предполагаю, что это правильный способ, если используется цикл форвард фор (для соответствия правилам FIFO американских брокеров)

int MagicNo=1234;
int Slippage=10;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseOrdersForward()
  {
   for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         Print("Order Select failed, order index: ",i," Error: ",GetLastError());
         continue;
        }

      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNo && OrderType()<=OP_SELL)
        {
         if(OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),Slippage))
           {
            i--;
           }
         else
           {
            Print("Order Close failed, order ticket: ",OrderTicket()," Error: ",GetLastError());
           }
        }
     }
  }

В прямом цикле,

  1. Функция OrderTotal() используется внутри цикла for для обновления оставшегося количества открытых ордеров с каждой итерацией цикла, чтобы избежать выхода индекса из диапазона массива.
  2. Индекс i уменьшается с каждым закрытым ордером, чтобы избежать пропуска некоторых ордеров.
 
amrali: Индекс i уменьшается с каждым закрытым ордером, чтобы избежать пропуска некоторых ордеров.
При наличии множества ордеров (один советник на нескольких графиках, несколько советников, ручная торговля), пока вы ждете завершения текущей операции (закрытие, удаление, изменение), может произойти любое количество других операций над другими ордерами, которые могут одновременно изменить индексацию позиции:
  1. Для не FIFO (американские брокеры)(или советник открывает только один ордер на символ) вы можете просто вести обратный отс чет в цикле позиции, и вы не пропустите ордера. Возьмите за привычку всегда отсчитывать время.
    Циклы и закрытие или удаление ордеров - Форум по программированию на MQL4
    Для FIFO (американские брокеры), если вы (потенциально) обрабатываете несколько ордеров на символ, вы должны найти самый ранний ордер, закрыть его и при успешной операции переработать все оставшиеся позиции.
    Закрытие ордеров по правилам FIFO - Тестер стратегий - Форум по программированию на MQL4 - Страница 2 #16

  2. и проверить OrderSelect на случай, если более ранние позиции были удалены.
    Что такое возвращаемые значения функции? Как их использовать? - Форум по программированию на MQL4
    Распространенные ошибки в MQL4-программах и как их избежать - Статьи по MQL4
  3. и если вы (потенциально) обрабатываете несколько ордеров, необходимо вызыватьRefreshRates() после вызова сервера, если вы хотите использовать, при следующем ордере / вызове сервера, предопределенные переменные(Bid/Ask) или (быть независимым от направления и использовать) OrderClosePrice().
 

Вы поймете, как сильно мне это помогло. Не только с кодом, над которым я работал, но и с моим пониманием в целом. Теперь он работает идеально, и у меня есть понимание, как реализовать его по-другому.

Очень признателен за эту информацию.

Причина обращения: