🚀 AI One-Click Generation of mql4 Strategy Code

Efficiently Close Hedged Trades in Mql4 Using the OrderCloseBy() Function

mql4 | Published on: 2025/12/2
The following content is generated by EasyQuant .

Problem Description

How can I close a buy order and a sell order on the same symbol against each other?

Solution

To close a Buy order and a Sell order on the same symbol against each other in MQL4, you must use the OrderCloseBy() function.

This method is superior to closing orders individually because it saves one spread. When you close two hedged positions individually, you pay the spread on both transactions. When you use OrderCloseBy, the volume of the two orders is matched, and you only pay the spread on the remaining volume (if any).

MQL4 Script to Close Hedge Positions

Here is a complete, robust script that finds the first available Buy order and the first available Sell order for the current symbol and closes them against each other.

//+------------------------------------------------------------------+
//|                                            CloseByHedge.mq4      |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property script_show_inputs

//--- Input Parameters
input int MagicNumber = 0; // 0 for manual trades, specific ID for EA trades

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   int buyTicket = 0;
   int sellTicket = 0;
   
   //--- Iterate through open orders to find a matching pair
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // Select the order by position
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         // Filter by Symbol and Magic Number
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         {
            // Identify Buy Order
            if(OrderType() == OP_BUY && buyTicket == 0)
            {
               buyTicket = OrderTicket();
            }
            
            // Identify Sell Order
            if(OrderType() == OP_SELL && sellTicket == 0)
            {
               sellTicket = OrderTicket();
            }
         }
      }
      
      // If we have found both tickets, we can stop searching
      if(buyTicket > 0 && sellTicket > 0) break;
   }

   //--- Execute CloseBy if both tickets were found
   if(buyTicket > 0 && sellTicket > 0)
   {
      ResetLastError();
      
      // The OrderCloseBy function closes one order by another
      // Parameters: Ticket1, Ticket2, Color
      bool result = OrderCloseBy(buyTicket, sellTicket, clrBlue);
      
      if(result)
      {
         Print("Successfully closed Buy #", buyTicket, " by Sell #", sellTicket);
      }
      else
      {
         Print("Failed to close orders. Error code: ", GetLastError());
      }
   }
   else
   {
      Print("Could not find a Buy and a Sell order pair for Symbol: ", Symbol(), " with Magic: ", MagicNumber);
   }
}
//+------------------------------------------------------------------+

Key Functions Used

  1. OrderCloseBy(int ticket, int opposite, color arrow_color):

    • ticket: The unique number of the first order.
    • opposite: The unique number of the opposite order.
    • arrow_color: The color of the closing arrow on the chart.
    • Return: Returns true if successful, otherwise false.
  2. OrderSelect: Used to iterate through the pool of currently open trades (MODE_TRADES) to find the ticket numbers.

How Logic Works

  1. The script loops through all open orders.
  2. It filters for orders that match the Current Chart Symbol and the specified Magic Number.
  3. It stores the ticket number of the first OP_BUY it finds.
  4. It stores the ticket number of the first OP_SELL it finds.
  5. If both a Buy and a Sell ticket are found, it calls OrderCloseBy.

Important Notes

  • Volume Mismatch: If the Buy order is 1.0 lot and the Sell order is 0.5 lots, OrderCloseBy will close the 0.5 Sell and reduce the Buy order to 0.5 lots (a partial close). The remaining 0.5 Buy will stay open with a new ticket number (usually indicated in the comment as "from #...").
  • Spread Savings: This function is highly recommended for hedging strategies as it avoids paying the spread twice (once for opening the hedge, and again for closing both sides individually).

Q&A

Q: What happens if the lot sizes of the buy and sell orders are different?
A: The OrderCloseBy function will perform a partial close. The smaller volume will be fully closed, and the larger order will remain open with the remaining volume. A new ticket number is generated for the remainder of the larger order.

Q: Can I use OrderCloseBy on orders with different Magic Numbers?
A: Yes, as long as the orders are on the same symbol and account. The OrderCloseBy function only requires ticket numbers; it does not check Magic Numbers internally. However, the script provided above filters by Magic Number to ensure you don't accidentally close trades belonging to different strategies.

Q: Does OrderCloseBy work in the Strategy Tester?
A: Yes, OrderCloseBy is fully supported in the Strategy Tester and is essential for accurately backtesting hedging strategies.