Частичное закрытие ордера

 

Сделал блок, в котором происходит частичное закрытие позции, при достижении ценой определённого уровня: 

   for (int i=0; i<OrdersTotal(); i++) 

   {

      if (OrderSelect(i, SELECT_BY_POS))

      {

            if (OrderType()==1)

            { 

                     Lot_61_8 = OrderLots()*Lot_Percent_61_8/100;if(Lot_61_8>OrderLots()||Lot_61_8<0.01){Lot_61_8 = OrderLots();if(Lot_61_8>100)Lot_61_8=100;}

                     Lot_61_8 = (NormalizeLot(Lot_61_8, False)); 

                     Ask_Value_61_8=OrderOpenPrice()-(61.8*OrderOpenPrice())/10000;                         

                           if (Lot_61_8>0)

                           error=OrderClose(OrderTicket(), Lot_61_8, MarketInfo(Symbol(), MODE_BID), 20, CLR_NONE);

             }  

}

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

Как сделать так, что бы этот закрытие произошло единожды и больше не отрабатывалось для данного ордера ?  

 
Sergey Lapshov:

Сделал блок, в котором происходит частичное закрытие позции, при достижении ценой определённого уровня: 

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

Как сделать так, что бы этот закрытие произошло единожды и больше не отрабатывалось для данного ордера ?  

rf как то так, переменную flag необходимо сбрасывать при открытии этого ордера

//+------------------------------------------------------------------+
//|                                                         тест.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

bool flag=true;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   for(int i=0; i<OrdersTotal(); i++)

     {

      if(OrderSelect(i,SELECT_BY_POS))

        {

         if(OrderType()==1)

           {

            Lot_61_8=OrderLots()*Lot_Percent_61_8/100;if(Lot_61_8>OrderLots() || Lot_61_8<0.01){Lot_61_8=OrderLots();if(Lot_61_8>100)Lot_61_8=100;}

            Lot_61_8=(NormalizeLot(Lot_61_8,False));

            Ask_Value_61_8=OrderOpenPrice()-(61.8*OrderOpenPrice())/10000;

            if(Lot_61_8>0 && flag)
              {
               error=OrderClose(OrderTicket(),Lot_61_8,MarketInfo(Symbol(),MODE_BID),20,CLR_NONE);
               if(error)flag=false;
               else PrintFormat("Ошибка № %d закрытия ордера. Тикет: %d",GetLastError(),OrderTicket());

              }

           }

        }

     }
  }
//+------------------------------------------------------------------+
 
Sergey Gritsay:

rf как то так, переменную flag необходимо сбрасывать при открытии этого ордера

почему-то получается так:

 

 

 
Sergey Lapshov:

Сделал блок, в котором происходит частичное закрытие позции, при достижении ценой определённого уровня: 

   for (int i=0; i<OrdersTotal(); i++) 

   {

      if (OrderSelect(i, SELECT_BY_POS))

      {

            if (OrderType()==1)

            { 

                     Lot_61_8 = OrderLots()*Lot_Percent_61_8/100;if(Lot_61_8>OrderLots()||Lot_61_8<0.01){Lot_61_8 = OrderLots();if(Lot_61_8>100)Lot_61_8=100;}

                     Lot_61_8 = (NormalizeLot(Lot_61_8, False)); 

                     Ask_Value_61_8=OrderOpenPrice()-(61.8*OrderOpenPrice())/10000;                         

                           if (Lot_61_8>0)

                           error=OrderClose(OrderTicket(), Lot_61_8, MarketInfo(Symbol(), MODE_BID), 20, CLR_NONE);

             }  

}

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

Как сделать так, что бы этот закрытие произошло единожды и больше не отрабатывалось для данного ордера ?  

Прежде, чем закрывать, проверьте объём закрываемого ордера как вариант. Но это если лоты фиксированные, либо если лоты не фиксированные, то сверяйте объём закрываемого ордера с текущим актуальным лотом советника - в переменной храниться должен.
 
Sergey Lapshov:

Сделал блок, в котором происходит частичное закрытие позции, при достижении ценой определённого уровня: 

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

Как сделать так, что бы этот закрытие произошло единожды и больше не отрабатывалось для данного ордера ?  

Ну и... ?

Какая логика, такой и код, так и будет работать.

....

У каждого ордера есть номер - тикет. Тикет ордера при частичном закрытии поменяется. Так что запоминать нужно будет только при удачном частичном закрытии.

Если error>0, то это и будет номером ордера, т.е. тикетом

error=OrderClose(OrderTicket(), Lot_61_8, MarketInfo(Symbol(), MODE_BID), 20, CLR_NONE);
 

for (int i=0; i<OrdersTotal(); i++) 

с конца начни перебор 

 

с флажками это примитив. проверьте в истории по комментарию ордера какая часть уже закрыта.

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

 

Написал такую функцию, на ECN работает без проблем. Пользуйтесь на здоровье)

 

input int     tr = 250;                 // Distance to close
input int     mn = 16384;               // Magic number
input color   CloseColor = clrLime;     // Close color
input color   StopColor = clrTomato;    // Stop color
// ========================================================================================================
// = Функция частичного закрытия позиции                                                    (c) Kino 2016 =
// =                                                                                                      =
// = По достижении определенного уровня закрывается половина позиции и подтягивается стоп в безубыток.    =
// = По достижении следующего уровня опять половина и подтяжка стопа. И т.д. пока не закроется вся поза.  =
// = tr  расстояние закрытия в пунтах позиции                                                             =                           
// ========================================================================================================

bool ClosePartPosition (int tr)
{
double ml = MarketInfo(Symbol(),MODE_LOTSTEP);
double close_lot;
int cnt = OrdersTotal();

   for (int i=cnt-1; i>=0; i--)
   {
   
   if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
   //Опционально
   if (OrderSymbol() != Symbol()) continue;
   //Опционально
   if (OrderMagicNumber() != mn) continue;
   
   close_lot=NormalizeDouble(OrderLots()/2,2);
   if (close_lot<ml) close_lot=ml;
   
   if (OrderType()==OP_BUY)
      {
      if (OrderStopLoss()==0 || OrderStopLoss() < OrderOpenPrice())
         {
         if ((MarketInfo(OrderSymbol(),MODE_BID) - (OrderOpenPrice() + (OrderCommission()*MarketInfo(OrderSymbol(),MODE_POINT)) + (OrderSwap()*MarketInfo(OrderSymbol(),MODE_POINT)))) > (tr*MarketInfo(OrderSymbol(),MODE_POINT)))
            {
            Print(Symbol()," ClosePartPosition. Move stop and close half");
            bool ModifyBuy_1 = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble((MarketInfo(OrderSymbol(),MODE_BID) - tr*MarketInfo(OrderSymbol(),MODE_POINT)),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),OrderTakeProfit(),0,StopColor);
               if(!ModifyBuy_1)
               Print(Symbol()," ClosePartPosition. OrderModify Buy fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderModify Buy successfully");

            bool CloseBuy_1 = OrderClose (OrderTicket(),close_lot,MarketInfo(OrderSymbol(),MODE_BID),Slippage,CloseColor);
               if(!CloseBuy_1)
               Print(Symbol()," ClosePartPosition. OrderClose Buy fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderClose Buy successfully");
            }
         }
      else
         {
         if ((MarketInfo(OrderSymbol(),MODE_BID) - OrderStopLoss()) > (tr*MarketInfo(OrderSymbol(),MODE_POINT)*2))
            {
            Print(Symbol()," ClosePartPosition. Move stop and close half");
            bool ModifyBuy_2 = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble((MarketInfo(OrderSymbol(),MODE_BID) - tr*MarketInfo(OrderSymbol(),MODE_POINT)),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),OrderTakeProfit(),0,StopColor);
               if(!ModifyBuy_2)
               Print(Symbol()," ClosePartPosition. OrderModify Buy fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderModify Buy successfully");
            
            bool CloseBuy_2 = OrderClose (OrderTicket(),close_lot,MarketInfo(OrderSymbol(),MODE_BID),Slippage,CloseColor);
               if(!CloseBuy_2)
               Print(Symbol()," ClosePartPosition. OrderClose Buy fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderClose Buy successfully");
            }
         }
      }
   if (OrderType()==OP_SELL)
      {
      if (OrderStopLoss()==0 || OrderStopLoss() > OrderOpenPrice())
         {
         if (((OrderOpenPrice() - (OrderCommission()*MarketInfo(OrderSymbol(),MODE_POINT)) - (OrderSwap()*MarketInfo(OrderSymbol(),MODE_POINT))) - MarketInfo(OrderSymbol(),MODE_ASK) ) > (tr*MarketInfo(OrderSymbol(),MODE_POINT)))
            {
            Print(Symbol()," ClosePartPosition. Move stop and close half");
            bool ModifySell_1 = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble((MarketInfo(OrderSymbol(),MODE_ASK) + tr*MarketInfo(OrderSymbol(),MODE_POINT)),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),OrderTakeProfit(),0,StopColor);
               if(!ModifySell_1)
               Print(Symbol()," ClosePartPosition. OrderModify Sell fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderModify Sell successfully");
            
            bool CloseSell_1 = OrderClose (OrderTicket(),close_lot,MarketInfo(OrderSymbol(),MODE_ASK),Slippage,CloseColor);
               if(!CloseSell_1)
               Print(Symbol()," ClosePartPosition. OrderClose Sell fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderClose Sell successfully");
            }
         }
      else
         {
         if (OrderStopLoss()-MarketInfo(OrderSymbol(),MODE_ASK)>tr*MarketInfo(OrderSymbol(),MODE_POINT)*2)
            {
            Print(Symbol()," ClosePartPosition. Move stop and close half");
            bool ModifySell_2 = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble((MarketInfo(OrderSymbol(),MODE_ASK) + tr*MarketInfo(OrderSymbol(),MODE_POINT)),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),OrderTakeProfit(),0,StopColor);
               if(!ModifySell_2)
               Print(Symbol()," ClosePartPosition. OrderModify Sell fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderModify Sell successfully");
            
            bool CloseSell_2 = OrderClose (OrderTicket(),close_lot,MarketInfo(OrderSymbol(),MODE_ASK),Slippage,CloseColor);
               if(!CloseSell_2)
               Print(Symbol()," ClosePartPosition. OrderClose Sell fail #",GetLastError());
               else
               Print(Symbol()," ClosePartPosition. OrderClose Sell successfully");
            }
         }
      }
   
   
   }
return (True); 
}
//End
 
Посмотрите чем отличается комментарий свежего ордера и частичного закрытого. По комментарию можно отличить частично закрытый ордер.
 
Dmitry Fedoseev:
Посмотрите чем отличается комментарий свежего ордера и частичного закрытого. По комментарию можно отличить частично закрытый ордер.
А если частично закрытый закрылся ещё раз?
 
Vasyl Nosal:
А если частично закрытый закрылся ещё раз?

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

Можно не ходить по всей цепочке, а создать глобальные переменные привязанные к тикету и перебрасывать данные только с предыдущего ордера. 

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