Выбрать последние 2 ордера и закрыть один из них

 

Добрый день. Сначала показалась задача простой, но код отказывается слушаться.

Имеются 2 открытые ордера. Если у одного из них сработал трейлинг-стоп, то 2-й (у которого он не сработал) нужно закрыть.

if (OrdersTotal() > 1)
{
   for (int i = 0; i < 2; i ++)
   {
      OrderSelect (OrdersTotal()-i, SELECT_BY_POS);
      
      // Если у ордера сработал трейлинг-стоп
      
      if (OrderStopLoss() > 0)
      {
         for (int j = 0; j < 2; j ++)
         {
            // Выбираем ордер без стоп-уровня
            
            if (i != j)
            {
               OrderSelect (OrdersTotal()-j, SELECT_BY_POS);
               
               // Закрытие Buy
               
               if (OrderType() == OP_BUY)
                  OrderClose (OrderTicket(), OrderLots(), Bid, 3*Order_Point);
               
               // Закрываем Sell
               
               if (OrderType() == OP_SELL)
                  OrderClose (OrderTicket(), OrderLots(), Ask, 3*Order_Point);
               
               break;
            }
         }
      }
   }
}

По логике: если открыты 2 ордера, ищем тот, у которого выставлен стоп, находим, дальше ищем тот, у которого он не выставлен, закрываем ордер без стопа. 

В чем причина не работы кода? Получаю ошибку 4051.

Спасибо. 

 
OrderClose (OrderTicket(), OrderLots(), Bid, 3*Order_Point);
 
tara:
   OrderSelect (OrdersTotal()-i, SELECT_BY_POS);
Мне кажется, что выбирают то, чего нет. При этом не проверяют.
 

Не понимаю как исправить.

Условие выполнится, если есть 2 открытых ордера.
Пойдет дальше, если у одного из выбранных ордеров выставлен стоп-лос.
Закроется 2-й ордер, который не имеет стоп-уровня. Всегда есть только 1 ордер со стоп-уровнем.

OrderSelect (OrdersTotal()-i, SELECT_BY_POS);

Попадет [2, 1] при проходе по первому циклу.
Например, один из них будет [1], тогда в следующем цикле будем игнорировать [1], а возьмет только [2]. И закроет ордер [2] (со своим уникальным тикетом).
Другого не должно попасть.

OrderClose (OrderTicket(), OrderLots(), Bid, 3*Order_Point);

Что-то не так здесь?
Тикет ведь получится функцией? Если берем последние 2 открытых ордера, тикеты могут быть (14, 15), например.

Не понимаю что здесь не так :).

 
lelectrohardl:

Не понимаю как исправить.

Условие выполнится, если есть 2 открытых ордера.
Пойдет дальше, если у одного из выбранных ордеров выставлен стоп-лос.
Закроется 2-й ордер, который не имеет стоп-уровня. Всегда есть только 1 ордер со стоп-уровнем.

Попадет [2, 1] при проходе по первому циклу.
Например, один из них будет [1], тогда в следующем цикле будем игнорировать [1], а возьмет только [2]. И закроет ордер [2] (со своим уникальным тикетом).
Другого не должно попасть.

Что-то не так здесь?
Тикет ведь получится функцией? Если берем последние 2 открытых ордера, тикеты могут быть (14, 15), например.

Не понимаю что здесь не так :).


Можно просто убрать фактический параметр Slippage
 
tara:

Можно просто убрать фактический параметр Slippage


Убрал. Получаю: 'OrderClose' - wrong parameters count. Брокер - Альпари.

 

У меня все работает, если выбираю  SELECT_BY_TICKET. Но когда создаются следующие 2 ордера - все перестает работать.
Возможно причина в номерах тикетах, но OrderTicket() должна брать уникальный номер тикета (из моего последнего ордера), даже если уже 100 закрытых ордеров в истории.


Пишет, что не правильный тикет у функции закрытия ордера. 

 

Значит, Сергей прав. Закрываем несуществующую позицию. 

Но, я бы все-таки сделал проскальзывание целочисленным, без умножения на размер пункта.  

 
lelectrohardl:

Не понимаю как исправить.

Условие выполнится, если есть 2 открытых ордера.
Пойдет дальше, если у одного из выбранных ордеров выставлен стоп-лос.
Закроется 2-й ордер, который не имеет стоп-уровня. Всегда есть только 1 ордер со стоп-уровнем.

Попадет [2, 1] при проходе по первому циклу.
Например, один из них будет [1], тогда в следующем цикле будем игнорировать [1], а возьмет только [2]. И закроет ордер [2] (со своим уникальным тикетом).
Другого не должно попасть.

Что-то не так здесь?
Тикет ведь получится функцией? Если берем последние 2 открытых ордера, тикеты могут быть (14, 15), например.

Не понимаю что здесь не так :).

Давайте поставим задачу. Если в рынке есть ордер, у которого установлен стоп-лосс, то все остальные ордера закрываем. Частный случай - ордеров всего два.

Первый цикл: проверяем, есть ли ордер, у которого установлен стоп-лосс.

Во втором, если такой есть, то, закрываем все без стопов. 

int i;
bool SnopExists = false;
for ( i = OrdersTotal() - 1;  i  >= 0; i -- ) // поиск стопа
{
   if ( OrderSelect( i, SelectByPos )
       if (OrderStopLoss() > 0) // у ордера установлен трал
      {
           SnopExists  = true;
           break;
      }
}
// если есть стоп, то закрываем все ордерв без стопов
if ( SnopExists )
   for ( i = OrdersTotal() - 1;  i  >= 0; i -- ) // поиск стопа
      if ( OrderSelect( i, SelectByPos )
      {
          if (OrderStopLoss() == 0) // у ордера нет стопа, закрываем
         {
            .... // здесь вы знаете, что писать
         }
       }

 Как-то, так. Пишите проще. Пусть много строк, молоток самый безотказный инструмент.

 
tara:

Значит, Сергей прав. Закрываем несуществующую позицию. 

Но, я бы все-таки сделал проскальзывание целочисленным, без умножения на размер пункта.  


Это 3 на 10 умножается, если брокер 5-значный. Там по коду проверка.
 
ERR_INVALID_FUNCTION_PARAMETER_VALUE4051Недопустимое значение параметра функции
 
Mislaid:

Давайте поставим задачу. Если в рынке есть ордер, у которого установлен стоп-лосс, то все остальные ордера закрываем. Частный случай - ордеров всего два.

Первый цикл: проверяем, есть ли ордер, у которого установлен стоп-лосс.

Во втором, если такой есть, то, закрываем все без стопов. 

 Как-то, так. Пишите проще. Пусть много строк, молоток самый безотказный инструмент.


Большое спасибо. Заработало.

Действительно, не выполнялось из-за проверки на количество открытых ордера. То есть один ордер закрылся по предварительно выставленному стопу и проверка не выполнялась, т.к. Ордеров !>1.

Жаль метод не сработал :(. Была идея сделать робота, который будет со спрэдом и трейлинг-стопом играться.

 

Всем всем спасибо еще раз :). Мы тут с другом системы роботов продумываем, кто тоже в теме, пишите мне, сделаю робота, поделюсь/приму идеи: lElectroHardl (Skype).