OrderClose закрывает ордер OP_SELL выше и OP_BUY ниже OrderOpened?

Я пытаюсь создать динамический Take Profit программно. Для этого я использую OrderClose(), чтобы закрыть ордер, когда разница в пипсах готова. Проблема в том, что он закрывается выше OP_SELL и ниже OP_BUY, и я не знаю, почему это происходит.

как я мог это исправить?

Попытка

void executeTakeProfit(int mn, double points){   
  double _diffPips = 0;


  if(OrdersTotal() > 0){
      RefreshRates();

      for(int x = 0; x < OrdersTotal(); x++){
         if(OrderSelect(x, SELECT_BY_POS, MODE_TRADES)){
            if(OrderMagicNumber() == mn && OrderSymbol() == Symbol()){


               if(OrderType() == OP_BUY){
                  if(Ask > OrderOpenPrice()){
                     _diffPips = NormalizeDouble((Ask - OrderOpenPrice()) / Point, Digits);
                     if(_diffPips >= points){
                        if(!OrderClose(OrderTicket(), OrderLots(), Bid, 0, clrNONE)){
                           Comment("Error Take Profit - Buy");
                        }   
                     }
                  }
               }//buy

               if(OrderType() == OP_SELL){
                  if(Bid < OrderOpenPrice()){
                     _diffPips = NormalizeDouble((OrderOpenPrice() - Bid) / Point, Digits);                     
                     if(_diffPips >= points){
                        if(!OrderClose(OrderTicket(), OrderLots(), Ask, 0, clrNONE)){
                           Comment("Error Take Profit - Sell");
                        }               
                     }
                  }
               }//sell



            }//magic



         }//select
      }//for




  }


}//execute take profit

введите здесь описание изображения


person FernandoPaiva    schedule 11.01.2020    source источник


Ответы (1)


При входе в рынок можно купить (открыть OP_BUY) по Ask, продать по Bid. При выходе операция обратная: если у вас есть сделка на покупку, вы можете закрыть ее продажей (то есть исполнение должно производиться по цене Bid, на продажу - по цене Ask). Чтобы пропустить эту раздражающую логику, вы можете использовать OrderClosePrice() все время.

So,

for(int x = OrdersTotal()-1; x>=0; x--){
     if(!OrderSelect(x, SELECT_BY_POS, MODE_TRADES)) continue;
     if(OrderMagicNumber() != mn || OrderSymbol() != _Symbol)continue;
     RefreshRates();
     if(OrderType()==OP_BUY){
        if(OrderClosePrice()-OrderOpenPrice()>_Point/2.) {
          if(NormalizeDouble((OrderClosePrice()-OrderOpenPrice())/_Point,_Digits)>=points)//points is an external parameter here, that actually means ticks not points
            {
             TradeClose(OrderTicket());
            }
        }
     }//and same for sell, but of course it's easier to have same logic for buy and sell
 }


void TradeClose(const int ticketId){
   if(!OrderSelect(ticketId,SELECT_BY_TICKET))return;
   RefreshRates();
   //better to make several attempts to close the ticketId
   if(!OrderClose(ticketId, OrderLots(), OrderClosePrice()))
       Comment();
}
person Daniel Kniaz    schedule 11.01.2020
comment
для OP_SELL это OrderOpenPrice()-OrderClosePrice() < _Point / 2 ? - person FernandoPaiva; 12.01.2020
comment
да. Но, как я уже говорил, гораздо лучше иметь одинаковую логику как для длинного, так и для короткого кода (чтобы поддерживать код только в одном месте. Для этого int dir=OrderType()%2==OP_BUY?1:-1 и dir*(OrderClosePrice()-OrderOpenPrice()) используются в другом месте). - person Daniel Kniaz; 12.01.2020
comment
Еще одна вещь, которую нужно добавить к ответу, лучше использовать цикл с уменьшением for вместо цикла с увеличением, потому что значение OrdersTotal() уменьшается при закрытии ордера. - person TheLastStark; 13.01.2020
comment
@TheLastStark, я согласен с вами и обновил ответ с учетом вашего (ценного) вклада. - person Daniel Kniaz; 13.01.2020