OrderClose error 138 for takePartialProfits function

 
Hi all,

I’m testing this function to close an order partially, unfortunately it returns this error "OrderClose error 138" and I can not quite understand the reason.

Thanks to anyone who wants to help


#property copyright ""
#property link      ""
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int count = 0;
int ticket = -1;

int OnInit(){

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

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick(){

   if(count == 0){
      ticket = OrderSend(Symbol(),OP_BUY,1,Ask,0,Bid-600*Point,Ask + 600*Point,"test",0,0,clrAliceBlue);
      if(ticket < 0) Print("Error");
      count++;
   }


   if(count == 1){
      takePartialProfits(ticket,0.5,0.5); //----------> OrderClose error 138
   }
   
}

void takePartialProfits(int ticketIns,double percRangeIns,double percProfitIns){
   
   if(!OrderSelect(ticketIns,SELECT_BY_TICKET)) Print("Error");
   
   
   double profitRange = 0;
   if(OrderType() == OP_BUY){
      profitRange = OrderTakeProfit() - OrderOpenPrice();
   }
   if(OrderType() == OP_SELL){
      profitRange = OrderOpenPrice() - OrderTakeProfit();
   }
   
   
   if(Ask > OrderOpenPrice()+profitRange*percRangeIns && OP_BUY){
      if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Bid,0,clrAliceBlue));
      else count++;
   }
   
   if(Bid< OrderOpenPrice()-profitRange*percProfitIns && OP_SELL){
      if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Ask,0,clrAntiqueWhite));
      else count++;
   }

}
 
  1. Marco De Angelis: it returns this error "OrderClose error 138" and I can not quite understand the reason.
    if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Ask,0,clrAntiqueWhite));

    You can't just use OrderLots()/2 because that is not a multiple of LotStep, and you can't close or have remaining less than MinLot.

    You also must check if you have already done it, to avoid repeated closing. Alternatives:

    • Move SL to Break Even+1 before the partial close. That way, you know that you already did it.
    • Set a flag in persistent storage (files, global variables w/flush)
    • Open two orders initially, and close one (manually or by TP.)

  2. ticket = OrderSend(Symbol(),OP_BUY,1,Ask,0,Bid-600*Point,Ask + 600*Point,"test",0,0,clrAliceBlue);

    You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)

      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
      My GBPJPY shows average spread = 26 points, average maximum spread = 134.
      My EURCHF shows average spread = 18 points, average maximum spread = 106.
      (your broker will be similar).
                Is it reasonable to have such a huge spreads (20 PIP spreads) in EURCHF? - General - MQL5 programming forum (2022)

 

Thank you for the tips William, I really apreciated your help.

The error "OrderClose error 138"  has been fixed by adding spread.

For the minimum number of lots I placed the condition "OrderLots > 0.01"

For multiple closures I noticed that it does not happen, in any case where would you suggest to insert a flag?

You think my code is correct now?


#property copyright ""
#property link      ""
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int count = 0;
int ticket = -1;

int OnInit(){

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

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick(){

   if(count == 0){
      ticket = OrderSend(Symbol(),OP_BUY,1,Ask,0,Bid-600*Point,Ask + 600*Point,"test",0,0,clrAliceBlue);
      if(ticket < 0) Print("Error");
      count++;
   }


   if(count == 1){
      takePartialProfits(ticket,0.5,0.5);
   }
   
}

void takePartialProfits(int ticketIns,double percRangeIns,double percProfitIns){
   
   if(!OrderSelect(ticketIns,SELECT_BY_TICKET));
   
   int slippage = 0;
   double price = 0.0;
   
   double profitRange = 0;
   if(OrderType() == OP_BUY){
      profitRange = OrderTakeProfit() - OrderOpenPrice();
   }
   if(OrderType() == OP_SELL){
      profitRange = OrderOpenPrice() - OrderTakeProfit();
   }
   
   if(OrderType() == OP_BUY){
      if(Ask > OrderOpenPrice()+profitRange*percRangeIns && OrderLots() > 0.01){
         price = Bid;
         slippage = int(NormalizeDouble(fabs(price - OrderOpenPrice()) / _Point, 0));
         if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Bid,slippage,clrAliceBlue));
         else count++;
      }
   }
   
   if(OrderType() == OP_SELL){
      if(Bid < OrderOpenPrice() - profitRange*percProfitIns && OrderLots() > 0.01){
         price = Ask;
         slippage = int(NormalizeDouble(fabs(price + OrderOpenPrice()) / _Point, 0));
         if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Ask,slippage,clrAntiqueWhite));
         else count++;
      }
   }
}
 
Marco De Angelis #:Thank you for the tips William, I really apreciated your help. You think my code is correct now?
  1. #1.2 not handled.

  2.       if(ticket < 0) Print("Error");
          count++;

    Increment count when nothing has been opened.

  3. EAs must be coded to recover. If the power fails, OS crashes, terminal or chart is accidentally closed, on the next tick, any static/global ticket variables (and your count) will have been lost. You will have an open order but don't know it, so the EA will never try to close it, trail SL, etc. How are you going to recover?

    Use a OrderSelect / Position select loop on the first tick, or persistent storage (GV+flush or files) of ticket numbers required.

  4. void takePartialProfits(int ticketIns,double percRangeIns,double percProfitIns){
       
       if(!OrderSelect(ticketIns,SELECT_BY_TICKET));

    You select by ticket. What if it fails?

  5. What if the order has closed?
 

Thanks again William, with your suggestion I think I have solved by adding a global variable.

#property copyright ""
#property link      ""
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

datetime PartialTPCheck = GlobalVariableSet("PartialTakeProfit", 0.0);
int ticket = -1;

int OnInit(){

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

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick(){

   if(OrdersTotal() == 0){
      ticket = OrderSend(Symbol(),OP_SELL,1,Bid,0,Ask + 1000*Point,Bid - 1000*Point,"prova profitti parziali",0,0,clrAliceBlue);
      //ticket = OrderSend(Symbol(),OP_BUY,1,Ask,0,Bid - 1000*Point,Ask + 1000*Point,"prova profitti parziali",0,0,clrAliceBlue);
      GlobalVariableSet("PartialTakeProfit", 0.0);
   }

   if(OrdersTotal() == 1){
      takePartialProfits(ticket,0.5,0.5);
   }
}


void takePartialProfits(int ticketIns,double percRangeIns,double percProfitIns){
   
   double PartialTP = GlobalVariableGet("PartialTakeProfit");
   
   if(!OrderSelect(ticketIns,SELECT_BY_TICKET)) Print("Error code #" + IntegerToString(GetLastError()) + " inside function @" + __FUNCTION__);
   
   int slippage = 0;
   double price = 0.0; 
   double profitRange = 0;
   
   if(OrderType() == OP_BUY){
      profitRange = OrderTakeProfit() - OrderOpenPrice();
   }
   if(OrderType() == OP_SELL){
      profitRange = OrderOpenPrice() - OrderTakeProfit();
   }
   
   if(OrderType() == OP_BUY && PartialTP == 0.0){
      if(Ask > OrderOpenPrice()+profitRange*percRangeIns && OrderLots() > 0.01){
         price = Bid;
         slippage = int(NormalizeDouble(fabs(price - OrderOpenPrice()) / _Point, 0));
         if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Bid,slippage,clrAliceBlue)) Print("Error code #" + IntegerToString(GetLastError()) + " inside function @" + __FUNCTION__);
         GlobalVariableSet("PartialTakeProfit", 1.0);
      }
   }
   
   if(OrderType() == OP_SELL  && PartialTP == 0.0){
      if(Bid < OrderOpenPrice() - profitRange*percProfitIns && OrderLots() > 0.01){
         price = Ask;
         slippage = int(NormalizeDouble(fabs(price + OrderOpenPrice()) / _Point, 0));
         if(!OrderClose(ticketIns,OrderLots()*percProfitIns,Ask,slippage,clrAntiqueWhite)) Print("Error code #" + IntegerToString(GetLastError()) + " inside function @" + __FUNCTION__);
         GlobalVariableSet("PartialTakeProfit", 1.0);
      }
   }
}


For this problem:

  1. EAs must be coded to recover. If the power fails, OS crashes, terminal or chart is accidentally closed, on the next tick, any static/global ticket variables will have been lost. You will have an open order but don't know it, so the EA will never try to close it, trail SL, etc. How are you going to recover?

    Use a OrderSelect / Position select loop on the first tick, or persistent storage (GV+flush or files) of ticket numbers required.


You’re absolutely right, it’s something I never thought about. I never used this backup strategy to recover open orders, wouldn’t you have a small script to show me the "best practices" to do this? This would be much appreciated.

order accounting
order accounting
  • 2013.06.22
  • www.mql5.com
Dears how to get the total of orders by orderType and OrderSymbol. and is there a way to know if the order close or not (orderClose event) any help...