Problem Description
Solution
Here is a complete MQL4 script designed to close all active positions (Buy and Sell) for all symbols, not just the chart the script is attached to.
Script Logic
- Reverse Loop: It iterates through the order pool backwards (from the last order to the first). This is crucial because closing an order changes the total count and index of remaining orders.
- Symbol Independence: It uses
MarketInfo(OrderSymbol(), ...)to get the correct Bid/Ask prices for every specific order, allowing it to close trades on EURUSD, GBPJPY, and Gold simultaneously. - Position Filtering: It specifically targets
OP_BUYandOP_SELLtypes, ignoring pending orders (Limit/Stop orders).
MQL4 Code
Save this code as a .mq4 file in your MQL4/Scripts folder.
//+------------------------------------------------------------------+
//| CloseAllPositions.mq4 |
//| Copyright 2023, MetaQuotes |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes"
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property show_inputs
//--- Input Parameters
input int Slippage = 5; // Maximum deviation in pips
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
// Loop through all orders backwards
// We loop backwards because closing an order shifts the indices of remaining orders
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// Select the order by position
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
// Define variables for closing
bool result = false;
int ticket = OrderTicket();
double lots = OrderLots();
string symbol = OrderSymbol();
int type = OrderType();
// Get current prices for the specific symbol of the order
// We use MarketInfo because the order might be for a symbol different
// from the chart the script is running on.
double bid = MarketInfo(symbol, MODE_BID);
double ask = MarketInfo(symbol, MODE_ASK);
// Check if the order is a BUY position
if(type == OP_BUY)
{
// Close Buy at Bid price
result = OrderClose(ticket, lots, bid, Slippage, clrRed);
if(!result)
{
Print("Failed to close BUY order #", ticket, " on ", symbol, ". Error: ", GetLastError());
}
else
{
Print("Successfully closed BUY order #", ticket, " on ", symbol);
}
}
// Check if the order is a SELL position
else if(type == OP_SELL)
{
// Close Sell at Ask price
result = OrderClose(ticket, lots, ask, Slippage, clrBlue);
if(!result)
{
Print("Failed to close SELL order #", ticket, " on ", symbol, ". Error: ", GetLastError());
}
else
{
Print("Successfully closed SELL order #", ticket, " on ", symbol);
}
}
// Note: Pending orders (OP_BUYLIMIT, OP_SELLSTOP, etc.) are ignored
}
}
}
//+------------------------------------------------------------------+
How to Install and Use
- Open MetaTrader 4.
- Press F4 to open the MetaEditor.
- In the Navigator panel (left side), right-click on the Scripts folder and select New File.
- Select Script, name it
CloseAllPositions, and click Finish. - Delete everything in the new window and paste the code provided above.
- Press F7 to Compile. Ensure there are no errors in the "Errors" tab at the bottom.
- Return to the main MetaTrader 4 window.
- Locate
CloseAllPositionsin the Navigator panel under Scripts. - Drag and drop the script onto any open chart. It will immediately attempt to close all active market positions for all symbols.
Q&A: MQL4 Strategy Implementation
Q: Why does the script loop backwards (i--) instead of forwards?
A: When you close an order using OrderClose, it is removed from the trading pool. If you loop forwards (0 to Total), closing order #0 shifts order #1 into the #0 slot. The loop then increments to index 1, effectively skipping the order that just moved. Looping backwards ensures that removing an order does not affect the indices of the orders yet to be processed.
Q: Will this script close Pending Orders (Limit/Stop)?
A: No. The code explicitly checks for OrderType() == OP_BUY and OrderType() == OP_SELL. Pending orders (like OP_BUYLIMIT or OP_SELLSTOP) require the OrderDelete() function rather than OrderClose(). If you wish to delete pending orders as well, additional logic blocks checking for those types would need to be added.
Q: Why use MarketInfo() instead of the predefined Bid and Ask variables?
A: The predefined Bid and Ask variables only contain the prices for the current chart the script is attached to. Since your requirement is to close positions on "every chart" (all symbols), the script might encounter a GBPUSD trade while running on a EURUSD chart. MarketInfo(OrderSymbol(), MODE_BID) retrieves the correct price for the specific symbol of the order being processed.
Q: What happens if the market is moving fast and the price changes while the script is running?
A: The script includes a Slippage input parameter (default set to 5). This allows the trade to close even if the price deviates by up to 5 points (or pips, depending on broker digits) from the requested price during the execution instant. If the price moves beyond this slippage, the OrderClose function will fail, and the error will be printed to the "Experts" tab in the Terminal. You would simply run the script again to retry.