Очень нужна ваша помощь в написании функции

 
В советнике одновременно открывается два ордера (в одном направлении, buy ) с одинаковым стоп-лоссом и разными тейк-профитами. Для первого ордера тейк-профит N пунктов, для вторго 2*N.
Нужно перенести стоп-лосс для второго ордера, если первый закрылся с прибылью по тейк-профиту. Да, и второй надо закрывать после переноса стоп-лосс если выполнились условия, если нет, то он или по стоп-лосс или по тейк-профик закрывается. 
Все это вроде бы не сложно сделать если открыты только эти два ордера. Но проблема в том, что могут открыться дополнительно еще 2 ордера этого же советника, которые надо так же сопровождать, как и первые 2.

Долго я думал, и написал функцию, на тестере работает, но сегодня понял, что протупил, потому что решил, что цена (или к примеру время) открытия двух ордеров будит одинаковым.

 

 

void OrdersModify(int magic)
{
   string sumbol = Symbol();
   double orderOpenPrice;
   double orderStopLoss;
   for (int i=0; i<OrdersHistoryTotal(); i++) 
   {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if(OrderMagicNumber()!= magic || OrderSymbol()!= sumbol) continue;
      if(OrderProfit() > 0) // первый ордер закрылся с профитом
      {
         orderOpenPrice = NormalizeDouble(OrderOpenPrice(), Digits);
 
         for(int j=0; j<OrdersTotal(); j++)
         {
            if(!OrderSelect(j,SELECT_BY_POS,MODE_TRADES)) continue;
            if(OrderMagicNumber()!= magic || OrderSymbol()!= sumbol) continue;
            if(orderOpenPrice == NormalizeDouble(OrderOpenPrice(), Digits)) // второй ордер открыт !!! Но это условие не сработает, так как
                                                                            // цены открытия будут не много разные
 
            {
               orderOpenPrice = NormalizeDouble(OrderOpenPrice(), Digits);
               orderStopLoss = NormalizeDouble(OrderStopLoss(), Digits);
               if(orderOpenPrice != orderStopLoss) // второй ордер еще не модифицированный (стоп-лосс не перемещен)
               {
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,Aqua);
               }
               else{
                  // если ордер был модифицированный проверяю условия закрытия 
                  if(условия)
                  {
                     if(OrderType()==OP_BUY)
                     {
                        OrderClose(OrderTicket(),lot,Bid,3,clrBlue);
                     }
                     if(OrderType()==OP_SELL)
                     {
                        OrderClose(OrderTicket(),lot,Ask,3,clrBlue);
                     }
                  }
               }
            }
         } 
      }
      orderOpenPrice = 0;
   }
}
 

При открытии ордеров надо их помечать, что они относятся к одной паре.

После открытия первого ордера известен его тикет, допустим 12345, создаем глобальную переменную с именем _12345_set2=1.

Для открытия второго ордера отдельный цикл. Перебираем ордера, если у ордера есть глобальная переменная ..._set2, значит открываем второй ордер, а эту глобальную переменную удаляем.

После открытия второго ордера у нас известны оба тикета, допустим второй тикет 67890. Теперь создаем две глобальных переменных:  _12345_pair_of=67890 и _67890_pair_of=12345. После этого, зная тикет одного ордера, всегда под рукой тикет второго ордера.  

---

К глобальным переменным еще желательно добавить префиксы, чтобы отделить переменные создаваемые при работе в тестере от переменных создаваемых при работе на счете. В лучшем случае перфикс состоит из имени советника, символа, магика и буквы "t" если работа в тестере 

 
traderEvgen:
В советнике одновременно открывается два ордера (в одном направлении, buy ) с одинаковым стоп-лоссом и разными тейк-профитами. Для первого ордера тейк-профит N пунктов, для вторго 2*N.
Нужно перенести стоп-лосс для второго ордера, если первый закрылся с прибылью по тейк-профиту. Да, и второй надо закрывать после переноса стоп-лосс если выполнились условия, если нет, то он или по стоп-лосс или по тейк-профик закрывается. 
Все это вроде бы не сложно сделать если открыты только эти два ордера. Но проблема в том, что могут открыться дополнительно еще 2 ордера этого же советника, которые надо так же сопровождать, как и первые 2.

Долго я думал, и написал функцию, на тестере работает, но сегодня понял, что протупил, потому что решил, что цена (или к примеру время) открытия двух ордеров будит одинаковым.

 

 

В данном случае, действительно алгоритм немного сложноватый получиться, как вариант ограничить новое открытие ордеров пока не отработают уже открытые, или же воспользоваться ООП и написать слежение в виде объекта класса, и при открытии новой пары ордеров создавать новый объект, а как только отработают объект удаляется. Благо теперь в четверке тоже можно писать код с помощью ООП.
 
Dmitry Fedoseev:

При открытии ордеров надо их помечать, что они относятся к одной паре.

После открытия первого ордера известен его тикет, допустим 12345, создаем глобальную переменную с именем _12345_set2=1.

Для открытия второго ордера отдельный цикл. Перебираем ордера, если у ордера есть глобальная переменная ..._set2, значит открываем второй ордер, а эту глобальную переменную удаляем.

После открытия второго ордера у нас известны оба тикета, допустим второй тикет 67890. Теперь создаем две глобальных переменных:  _12345_pair_of=67890 и _67890_pair_of=12345. После этого, зная тикет одного ордера, всегда под рукой тикет второго ордера.  

---

К глобальным переменным еще желательно добавить префиксы, чтобы отделить переменные создаваемые при работе в тестере от переменных создаваемых при работе на счете. В лучшем случае перфикс состоит из имени советника, символа, магика и буквы "t" если работа в тестере 

не совсем понял... как узнать какой тикет относиться к первому ордеру, какой к второму ?
 
traderEvgen:
не совсем понял... как узнать какой тикет относиться к первому ордеру, какой к второму ?
а как вы открываете эти два ордера?
 
Sergey Gritsay:
а как вы открываете эти два ордера?
void OrderSendX(int cmd, double price, double stoploss, double takeprofit1, double takeprofit2)
{
   int count = 0;
   ticket1 = -1;
   ticket2 = -1;
   while(true)
   {
      if(ticket1 == -1 )
         ticket1 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit1, "Order_1", magicNumber, 0, Red);
      if(ticket2 == -1 )
         ticket2 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit2, "Order_2", magicNumber, 0, Green);
      
      if(ticket1==-1 || ticket2==-1)
      {  
         count++;
         Sleep(2000);
         RefreshRates();
      }

      if ((ticket1!=-1 && ticket2!=-1) || count>5) return;
   }
   return;
}
 
traderEvgen:
void OrderSendX(int cmd, double price, double stoploss, double takeprofit1, double takeprofit2)
{
   int count = 0;
   ticket1 = -1;
   ticket2 = -1;
   while(true)
   {
      if(ticket1 == -1 )
         ticket1 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit1, "Order_1", magicNumber, 0, Red);
      if(ticket2 == -1 )
         ticket2 = OrderSend(Symbol(), cmd, lot, price, 3, stoploss, takeprofit2, "Order_2", magicNumber, 0, Green);
      
      if(ticket1==-1 || ticket2==-1)
      {  
         count++;
         Sleep(2000);
         RefreshRates();
      }

      if ((ticket1!=-1 && ticket2!=-1) || count>5) return;
   }
   return;
}
вынесите эти переменные на глобальный уровень
   ticket1 = -1;
   ticket2 = -1;
 и далее анализируйте их уже по тикетам с помощью функции
OrderSelect(tiket,SELECT_BY_TICKET)
 и вставляем код с помощью кнопочки SRC  вменю сообщения
 
Sergey Gritsay:
вынесите эти переменные на глобальный уровень  и далее анализируйте их уже по тикетам с помощью функции  и вставляем код с помощью кнопочки SRC  вменю сообщения
не поможет, потому что когда будет дополнительный вход, они изменятся 
 
traderEvgen:
не совсем понял... как узнать какой тикет относиться к первому ордеру, какой к второму ?

Добавьте ее одну глобалку, например _12345_is1=1 (создавать после открытия первого ордера)

Или  _12345_num=1, _67890_num=2

 
Sergey Gritsay:
В данном случае, действительно алгоритм немного сложноватый получиться, как вариант ограничить новое открытие ордеров пока не отработают уже открытые, или же воспользоваться ООП и написать слежение в виде объекта класса, и при открытии новой пары ордеров создавать новый объект, а как только отработают объект удаляется. Благо теперь в четверке тоже можно писать код с помощью ООП.

Возможно Ваш вариант подойдет. Можно при открытие новой пари создавать объект класса и вызывать метод, который будет открывать эти позиции, в класе можно сделать две переменные с тикетами ордеров. Потом этот объект заносить в список, и при модификации брать цикл по списку и оттуда уже получать тикеты разных пар сделок 

 
traderEvgen:

Возможно Ваш вариант подойдет. Можно при открытие новой пари создавать объект класса и вызывать метод, который будет открывать эти позиции, в класе можно сделать две переменные с тикетами ордеров. Потом этот объект заносить в список, и при модификации брать цикл по списку и оттуда уже получать тикеты разных пар сделок 

Или это тоже не вариант ?

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