Великий и ужасный МТ4 навсегда (или как грамотно выработать стратегию перехода) - страница 14

 
Ihor Herasko:

Да, и я о том же. Получается, что скрипт успевает закрыть одну из позиций, когда их на самом деле две, но PositionsTotal() возвращает 1. А потом, после закрытия, выполняется условие окончания цикла, т. е. PositionsTotal() возвращает 2.

Можно вставить распечатки, чтобы полностью увидеть, что происходит.

 
fxsaber:

Можно вставить распечатки, чтобы полностью увидеть, что происходит.

Да, чтобы подтвердить правильность рассуждений:

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
    {
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
      Print("Закрытие, т. к. PositionsTotal() равно 1");
    }
    else if (!OrdersTotal())
    {
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
      
Print("Открытие. PositionsTotal: ", PositionsTotal()); 
    }
    
  Print("Выход. PostionsTotal: ", PositionsTotal());
}

Результат:

2021.05.05 10:11:43.393 Test (EURUSD,M1)        Открытие. PositionsTotal: 0
2021.05.05 10:11:43.488 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:43.535 Test (EURUSD,M1)        CTrade::OrderSend: market sell 0.01 position #2249868517 EURUSD [position closed]
2021.05.05 10:11:43.535 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:43.615 Test (EURUSD,M1)        Открытие. PositionsTotal: 0
2021.05.05 10:11:43.697 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:43.777 Test (EURUSD,M1)        Открытие. PositionsTotal: 0
2021.05.05 10:11:43.859 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:43.941 Test (EURUSD,M1)        Открытие. PositionsTotal: 0
2021.05.05 10:11:44.023 Test (EURUSD,M1)        Открытие. PositionsTotal: 1
2021.05.05 10:11:44.101 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:44.101 Test (EURUSD,M1)        Выход. PostionsTotal: 2

На самом же деле позиция осталась одна висеть.

P. S. Подправил пост, т. к. из-за копипаста не то вставил в код.
 
Ihor Herasko:

На самом же деле позиция осталась одна висеть.

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

Важно еще распечатывать OrdersTotal.
 
fxsaber:

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

Вы про эти две записи?

2021.05.05 10:11:44.101 Test (EURUSD,M1)        Закрытие, т. к. PositionsTotal() равно 1
2021.05.05 10:11:44.101 Test (EURUSD,M1)        Выход. PostionsTotal: 2

Здесь, думаю, все правильно в плане очередности. Позиций на самом деле две, но PositionsTotal() еще не получила обновление. Поэтому возвращает 1 и позиция закрывается. А после выполнения торговой операции происходит ее обновление на состояние, которое соответствует тому состоянию, которое было до выполнения торговой операции. Вот и получаем 2.

 
fxsaber:

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

Решение найдено.

И какое решение?

А в чем сложность была найти стабиль воспроизводящий код? Одно действие - открытие или закрытие, и в следующее с принятием решения на основании количеств позиций в рынке или в истории.
 
Ihor Herasko:

Вы про эти две записи?

Нет, последняя запись торговой активности во втором логе.

 
fxsaber:

Важно еще распечатывать OrdersTotal.

Добавил принтов. Теперь остается две позиции, как и ожидалось:

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
    {
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
      Print("Закрытие, т. к. PositionsTotal() равно 1");
    }
    else if (!OrdersTotal())
    {
      printf("Перед открытием. PositionsTotal: %d, OrdersTotal: %d", PositionsTotal(), OrdersTotal());
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
      printf("После открытия. PositionsTotal: %d, OrdersTotal: %d", PositionsTotal(), OrdersTotal());
    }
    
  Print("Выход. PostionsTotal: ", PositionsTotal());
}

Результат:

2021.05.05 10:22:50.583 Test (EURUSD,M1)        Перед открытием. PositionsTotal: 0, OrdersTotal: 0
2021.05.05 10:22:50.663 Test (EURUSD,M1)        После открытия. PositionsTotal: 0, OrdersTotal: 1
2021.05.05 10:22:50.679 Test (EURUSD,M1)        Перед открытием. PositionsTotal: 0, OrdersTotal: 0
2021.05.05 10:22:50.757 Test (EURUSD,M1)        После открытия. PositionsTotal: 2, OrdersTotal: 0
2021.05.05 10:22:50.757 Test (EURUSD,M1)        Выход. PostionsTotal: 2
 
Dmitry Fedoseev:

И какое решение?

А в чем сложность была найти стабиль воспроизводящий код? Одно действие - открытие или закрытие, и в следующее с принятием решения на основании количеств позиций в рынке или в истории.

Сложности не было, написал сходу.

 

Вот так вообще без остановки открывает позиции 

#include <Trade\Trade.mqh>
CTrade Trade;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int total=PositionsTotal();
   int Ordertotal=OrdersTotal();
   while(!IsStopped() && (total <= 1))  // Закончим, когда появится более одной позиции.
      if(total == 1)
         Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
      else
         if(!Ordertotal)
            Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
  }
//+------------------------------------------------------------------+

Снимок

 
SanAlex:

Вот так вообще без остановки открывает позиции 

Ну а кто будет total обновлять? ))