invalid ticket when try to modify order ticket

 
Hi all, when I'm trying to modify my order an error message popped up and tells me about order modify error 4108. I search the web for the error but everything seems revolve in looping while my code doesn't use any looping. Anyone knows where the problem is?
void OnTick(){
   
   double   EMA1 = iCustom(NULL,_Period,"ema",9,0,0);
   double   EMA2 = iCustom(NULL,_Period,"ema",21,0,0);
   //double EMA3 = iCustom(NULL,0,"ema",55,0,0);
   
   double   MACD = iMACD(NULL,_Period,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
   double   rsiValue = iRSI(NULL,_Period,rsiPeriod,PRICE_CLOSE,0);
   
   
   if(!CheckIfOpenOrdersByMagicNumber(magicNumber)){ 
      //long position
      if(   EMA1 > EMA2    &&          //INDICATOR 1
            Open[0] > EMA1 &&          //condition not to buy again after price hit the stop loss
            MACD > 0       &&          //INDICATOR 2
            rsiValue < rsiLowerLevel){ //INDICATOR 3
            
         Print("Condition met, sending buy order");
         Print("Entry price = " + Ask);
         
         double stopLossPrice = Ask - 100*Point;         
         Print("Stop loss price = " + stopLossPrice);   
           
         double takeProfitPrice = Ask + 400*Point;   
         Print("Take profit price = " + takeProfitPrice);
                 
         double lotSize = OptimalLotSize(riskPerTrade,Ask,stopLossPrice);
         Alert("Lot size buy: " + lotSize);
         
         double minimumLotSize = MarketInfo(Symbol(),MODE_LOTSTEP);
         if(lotSize < minimumLotSize){
            Alert("lot size minimum unmet");
         }
                  
         orderID = OrderSend(NULL,OP_BUYLIMIT,lotSize,Ask,1,stopLossPrice,takeProfitPrice,NULL,magicNumber);
         
         if (orderID < 0){
            Print("Order send error, error code: " + GetLastError());
         }        
      //short position      
      }else if(   EMA1 < EMA2 &&             //INDICATOR 1
                  Open[0] < EMA1 &&          //condition not to sell again after price hit the stop loss
                  MACD < 0 &&                //INDICATOR 2
                  rsiValue > rsiUpperLevel){ //INDICATOR 3
                  
         Print("Condition met, sending short order");
         Print("Entry price = " + Bid);
         
         double stopLossPrice = Bid + 100*Point;
         Print("Stop loss price = " + stopLossPrice);
         
         double takeProfitPrice = Bid - 400*Point;        
         Print("Take profit price = " + takeProfitPrice);
                     
         double lotSize = OptimalLotSize(riskPerTrade,Bid,stopLossPrice);
         Alert("Lot size sell: " + lotSize);
         
         double minimumLotSize = MarketInfo(Symbol(),MODE_LOTSTEP);
         if(lotSize < minimumLotSize){
            Alert("lot size minimum unmet");
         }
                  
         orderID = OrderSend(NULL,OP_SELLLIMIT,lotSize,Bid,1,stopLossPrice,takeProfitPrice,NULL,magicNumber);   
           
         if (orderID < 0){
            Print("Order send error, error code: " + GetLastError());
         }
         
        
      }else{ //else if you have open order, modify if needed
         if(OrderSelect(orderID,SELECT_BY_TICKET) == true){
            int orderType = OrderType(); //short = 1, long = 0              
            double optimalTakeProfit;
            if(orderType == 0){
               optimalTakeProfit = NormalizeDouble(Ask + 800*Point,Digits);
            }else{
               optimalTakeProfit = NormalizeDouble(Bid - 800*Point,Digits);
            }
            
            double TP = OrderTakeProfit();
            
            double TPdistance = MathAbs(TP - optimalTakeProfit);//syntax for modify TP if the change is more than 1 pip            
            if(TP !=optimalTakeProfit && TPdistance > 0.00005){ 
               bool Ans = OrderModify(orderID,OrderOpenPrice(),OrderStopLoss(),optimalTakeProfit,0);
               if(Ans == true){
                  Print("Order modify: ", orderID);
                  return;
               }else{
                  Print("Unable to modify open order: ", orderID);
               }
            }
         }   
      }   
   }
  }
 
  1.          if(OrderSelect(orderID,SELECT_BY_TICKET) == true){
    You selected the ticket. You don't check if it has already closed or not.

  2. 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 to recover, or persistent storage (GV+flush or files) of ticket numbers required.

  3.             if(orderType == 0){
                   optimalTakeProfit = NormalizeDouble(Ask + 800*Point,Digits);
                }else{
                   optimalTakeProfit = NormalizeDouble(Bid - 800*Point,Digits);
    You buy at the Ask and sell at the Bid.
    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using the 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 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 spread widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY (OANDA) shows average spread = 26 points, but average maximum spread = 134.

  4.         orderID = OrderSend(NULL,OP_BUYLIMIT,lotSize,Ask,1,stopLossPrice,takeProfitPrice,NULL,magicNumber);
    
    You can't open a pending order at the market.
 

Thanks for the reply @William Roeder, from my understanding your suggestion is like this:

You selected the ticket. You don't check if it has already closed or not.

1. Before I run the order select I should check the order id if it's closed or not, is that correct?


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 to recover, or persistent storage (GV+flush or files) of ticket numbers required.

2. It is better to use at least a loop or persistent storage to avoid problem like you mention above?



You buy at the Ask and sell at the Bid.

  1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using the 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 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 spread widen considerably at end of day (5 PM ET) ± 30 minutes. My GBPJPY (OANDA) shows average spread = 26 points, but average maximum spread = 134.

3. that TP and SL is figurative model. I'm going to use the TP using an indicator but I'm still far from fix that.


You can't open a pending order at the market.

4. I can't use the Ask as the entry price if I using OP_BUYLIMIT?

Sorry for asking to much, I'm still new with mql4.

Reason: