🚀 AI One-Click Generation of mql4 Strategy Code

Mql4 Guide: Modifying Stop Loss/Take Profit and Closing Trades

mql4 | Published on: 2025/11/26
The following content is generated by EasyQuant .

Problem Description

How do I change the stop-loss of an existing trade or close it out completely?

Solution

To manage existing trades in MQL4, you primarily use two functions: OrderModify() to change parameters like Stop Loss (SL) or Take Profit (TP), and OrderClose() to exit a market position.

Here is a detailed guide and the necessary code to perform both actions safely.

1. Modifying the Stop Loss

To change the Stop Loss, you must select the order using OrderSelect(), retrieve its current parameters (Open Price and Take Profit), and then pass the new Stop Loss value to OrderModify().

Key Considerations:

  • Normalization: Prices must be normalized to the chart's digits using NormalizeDouble() to avoid Error 129 (Invalid Price).
  • Freeze Level: Ensure the new SL is not too close to the current price (inside the FreezeLevel).
//+------------------------------------------------------------------+
//| Function to Modify Stop Loss of a specific ticket                |
//+------------------------------------------------------------------+
void ModifyTradeSL(int ticket, double newStopLoss)
{
   // 1. Select the order by ticket number
   if(OrderSelect(ticket, SELECT_BY_TICKET))
   {
      // 2. Normalize the new Stop Loss price to match server digits
      double normalizedSL = NormalizeDouble(newStopLoss, Digits);
      
      // 3. Retrieve existing parameters that we do not want to change
      double openPrice = OrderOpenPrice();
      double takeProfit = OrderTakeProfit();
      datetime expiration = OrderExpiration(); // Only relevant for pending orders
      
      // 4. Send the modification request
      // Note: We pass the existing openPrice and takeProfit to keep them unchanged
      bool res = OrderModify(ticket, openPrice, normalizedSL, takeProfit, expiration, clrBlue);
      
      if(!res)
      {
         Print("Error modifying order #", ticket, ". Error code: ", GetLastError());
      }
      else
      {
         Print("Order #", ticket, " Stop Loss modified successfully to ", normalizedSL);
      }
   }
   else
   {
      Print("Failed to select order #", ticket, ". Error code: ", GetLastError());
   }
}

2. Closing a Trade

To close a trade, you use OrderClose(). You must determine the correct closing price based on the order type:

  • Buy Orders (OP_BUY): Close at Bid price.
  • Sell Orders (OP_SELL): Close at Ask price.
//+------------------------------------------------------------------+
//| Function to Close a specific ticket completely                   |
//+------------------------------------------------------------------+
void CloseTrade(int ticket, int slippage = 3)
{
   // 1. Select the order
   if(OrderSelect(ticket, SELECT_BY_TICKET))
   {
      // 2. Check if the order is actually open (Market order)
      // Pending orders (OP_BUYLIMIT, etc.) use OrderDelete(), not OrderClose()
      int type = OrderType();
      
      if(type > 1) // 0=OP_BUY, 1=OP_SELL. Anything higher is a pending order.
      {
         Print("Order #", ticket, " is a pending order. Use OrderDelete instead.");
         return;
      }

      // 3. Determine the correct closing price and color
      double closePrice = 0.0;
      color arrowColor = clrNONE;
      
      RefreshRates(); // Ensure we have the latest Bid/Ask
      
      if(type == OP_BUY)
      {
         closePrice = Bid;
         arrowColor = clrRed;
      }
      else if(type == OP_SELL)
      {
         closePrice = Ask;
         arrowColor = clrBlue;
      }

      // 4. Send the close request
      // We use OrderLots() to close the entire volume. 
      bool res = OrderClose(ticket, OrderLots(), closePrice, slippage, arrowColor);
      
      if(!res)
      {
         Print("Error closing order #", ticket, ". Error code: ", GetLastError());
      }
      else
      {
         Print("Order #", ticket, " closed successfully.");
      }
   }
   else
   {
      Print("Failed to select order #", ticket, ". Error code: ", GetLastError());
   }
}

3. Implementation Example

Here is how you would use these functions inside an Expert Advisor (e.g., in the OnTick function). This example loops through open orders, finds a Buy order, moves the SL to Break Even, and then closes it.

void OnTick()
{
   // Loop through all open orders
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // Filter by Symbol and Magic Number (optional but recommended)
         if(OrderSymbol() == Symbol())
         {
            int ticket = OrderTicket();
            double openPrice = OrderOpenPrice();
            double currentSL = OrderStopLoss();
            
            // --- EXAMPLE 1: MODIFY SL ---
            // If it's a BUY order and price moved 50 points in profit, move SL to Break Even
            if(OrderType() == OP_BUY)
            {
               if(Bid > openPrice + 50 * Point && currentSL < openPrice)
               {
                  // Move SL to Open Price
                  ModifyTradeSL(ticket, openPrice);
               }
            }

            // --- EXAMPLE 2: CLOSE TRADE ---
            // If it's a SELL order and price moved 100 points against us (emergency close)
            if(OrderType() == OP_SELL)
            {
               if(Ask > openPrice + 100 * Point)
               {
                  CloseTrade(ticket);
               }
            }
         }
      }
   }
}

Q&A: Common Issues with Order Management

Q: Why do I get Error 130 (ERR_INVALID_STOPS) when modifying Stop Loss?
A: This usually happens if the new Stop Loss is too close to the current market price. You must check the MODE_STOPLEVEL using MarketInfo(Symbol(), MODE_STOPLEVEL). The new SL must be at least that many points away from the current Bid/Ask.

Q: Can I close only half of my trade?
A: Yes. In the OrderClose() function, instead of passing OrderLots(), you can pass a specific volume (e.g., 0.5). This is called a partial close. The remaining volume will stay open with a new ticket number.

Q: Do I need to use OrderModify for Pending Orders?
A: Yes, OrderModify is used to change the Open Price, Stop Loss, Take Profit, or Expiration of pending orders. However, to remove a pending order entirely, you must use OrderDelete(), not OrderClose().

Q: Why is RefreshRates() important before closing?
A: MQL4 stores a local copy of prices. If your code executes complex logic that takes time, the prices (Bid/Ask) might become stale. Calling RefreshRates() updates these variables to the very latest server prices, reducing the chance of "Off Quotes" or slippage errors.