Generate code in 3 minutes
Enter your idea and AI generates runnable code.
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).
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);
}
}
//+------------------------------------------------------------------+
OrderCloseBy(int ticket, int opposite, color arrow_color):
true if successful, otherwise false.OrderSelect: Used to iterate through the pool of currently open trades (MODE_TRADES) to find the ticket numbers.
OrderCloseBy.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 #...").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.