Page 2 of 3
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:00 pm
by PTScalper
To handle pending orders, you must add a second loop that uses MT5's OrdersTotal() and OrderGetTicket() functions. MetaTrader 5 strictly separates active trades ("Positions") from pending limits and stops ("Orders"), so the CTrade class requires you to use trade.OrderDelete() rather than trade.PositionClose().
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:00 pm
by PTScalper
Here is the complete script that flattens all active JPY positions and wipes all JPY pending orders simultaneously:
Code: Select all
//+------------------------------------------------------------------+
//| CloseAllAndDelete_JPY.mq5 |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
void OnStart()
{
CTrade trade;
// Set a generous slippage deviation for extreme volatility (in points)
trade.SetDeviationInPoints(100);
// ==========================================
// 1. CLOSE ALL OPEN POSITIONS
// ==========================================
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i);
if(StringFind(symbol, "JPY") >= 0)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
bool result = trade.PositionClose(ticket);
if(!result)
{
Print("Failed to close position ", ticket, " on ", symbol, ". Error: ", GetLastError());
}
else
{
Print("Successfully closed position: ", ticket, " on ", symbol);
}
}
}
}
// ==========================================
// 2. DELETE ALL PENDING ORDERS
// ==========================================
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// OrderGetTicket inherently selects the order into the cache
ulong ticket = OrderGetTicket(i);
if(ticket > 0)
{
// Retrieve the symbol of the selected order
string symbol = OrderGetString(ORDER_SYMBOL);
if(StringFind(symbol, "JPY") >= 0)
{
bool result = trade.OrderDelete(ticket);
if(!result)
{
Print("Failed to delete order ", ticket, " on ", symbol, ". Error: ", GetLastError());
}
else
{
Print("Successfully deleted order: ", ticket, " on ", symbol);
}
}
}
}
}
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:00 pm
by PTScalper
Order Selection Syntax
Unlike positions, where PositionGetSymbol(i) gets the symbol directly from the index, pending orders in MQL5 require a two-step process. You must first call OrderGetTicket(i) to load the specific order into the environment's cache, and then use OrderGetString(ORDER_SYMBOL) to read its pair name. Just like the positions loop, iterating backward prevents the index from collapsing as orders are deleted.
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:01 pm
by PTScalper
To provide immediate confirmation, you can use MQL5's built-in Alert() function, which triggers a pop-up window and a sound in the MetaTrader terminal. To make the alert useful, it is best to add integer counters that track exactly how many positions and orders were successfully processed.
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:01 pm
by PTScalper
Here is the updated script featuring the tracking counters and the final alert:
Code: Select all
//+------------------------------------------------------------------+
//| CloseAllAndDelete_Alert_JPY.mq5 |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
void OnStart()
{
CTrade trade;
trade.SetDeviationInPoints(100);
// Counters to track successful executions
int positionsClosed = 0;
int ordersDeleted = 0;
// ==========================================
// 1. CLOSE ALL OPEN POSITIONS
// ==========================================
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i);
if(StringFind(symbol, "JPY") >= 0)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
if(trade.PositionClose(ticket))
{
positionsClosed++;
Print("Successfully closed position: ", ticket, " on ", symbol);
}
else
{
Print("Failed to close position ", ticket, ". Error: ", GetLastError());
}
}
}
}
// ==========================================
// 2. DELETE ALL PENDING ORDERS
// ==========================================
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket > 0)
{
string symbol = OrderGetString(ORDER_SYMBOL);
if(StringFind(symbol, "JPY") >= 0)
{
if(trade.OrderDelete(ticket))
{
ordersDeleted++;
Print("Successfully deleted order: ", ticket, " on ", symbol);
}
else
{
Print("Failed to delete order ", ticket, ". Error: ", GetLastError());
}
}
}
}
// ==========================================
// 3. FINAL ALERT NOTIFICATION
// ==========================================
if(positionsClosed > 0 || ordersDeleted > 0)
{
Alert("JPY Exposure Flattened!\nPositions Closed: ", positionsClosed, "\nOrders Deleted: ", ordersDeleted);
}
else
{
Alert("Script executed: No active JPY positions or orders found.");
}
}
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:01 pm
by PTScalper
How the Alert Works
The Alert() function automatically brings the MetaTrader platform to the foreground (if it was minimized) and plays the default terminal alert sound. By placing \n in the string, the pop-up formats the text into clean, separate lines so you can instantly verify that the numbers match what you expected to close.
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:02 pm
by PTScalper
To prevent closing positions when liquidity vanishes and spreads gap out to destructive levels, you can use the SymbolInfoInteger() function to check the current spread in points before executing the close.
Crucially, this filter should only be applied to active positions. Deleting pending orders does not incur spread costs, so those should still be wiped out regardless of market conditions to prevent them from accidentally triggering.
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:03 pm
by PTScalper
Here is the updated script with a hardcoded spread limit:
Code: Select all
//+------------------------------------------------------------------+
//| CloseAllAndDelete_MaxSpread_JPY.mq5 |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
// Hardcoded to prevent input dialog boxes from slowing down execution
// 500 points = 50 pips (on standard 5-digit/3-digit JPY brokers)
int MaxSpreadPoints = 500;
void OnStart()
{
CTrade trade;
trade.SetDeviationInPoints(100);
int positionsClosed = 0;
int positionsSkipped = 0;
int ordersDeleted = 0;
// ==========================================
// 1. CLOSE OPEN POSITIONS (WITH SPREAD FILTER)
// ==========================================
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
string symbol = PositionGetSymbol(i);
if(StringFind(symbol, "JPY") >= 0)
{
// Retrieve current spread in points
long currentSpread = SymbolInfoInteger(symbol, SYMBOL_SPREAD);
if(currentSpread > MaxSpreadPoints)
{
Print("SKIPPED: Spread for ", symbol, " is ", currentSpread, " points. (Limit: ", MaxSpreadPoints, ")");
positionsSkipped++;
continue; // Move to the next loop iteration without closing
}
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
if(trade.PositionClose(ticket))
{
positionsClosed++;
Print("Successfully closed position on ", symbol);
}
}
}
}
// ==========================================
// 2. DELETE PENDING ORDERS (NO SPREAD FILTER)
// ==========================================
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
if(ticket > 0)
{
string symbol = OrderGetString(ORDER_SYMBOL);
if(StringFind(symbol, "JPY") >= 0)
{
if(trade.OrderDelete(ticket))
{
ordersDeleted++;
Print("Successfully deleted order on ", symbol);
}
}
}
}
// ==========================================
// 3. FINAL ALERT NOTIFICATION
// ==========================================
string alertMsg = "JPY Script Executed!\n";
alertMsg += "Positions Closed: " + IntegerToString(positionsClosed) + "\n";
alertMsg += "Positions Skipped (High Spread): " + IntegerToString(positionsSkipped) + "\n";
alertMsg += "Orders Deleted: " + IntegerToString(ordersDeleted);
Alert(alertMsg);
}
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:03 pm
by PTScalper
Design Choices for Emergency Scripts
No User Inputs (#property script_show_inputs): While MQL5 allows you to create a pop-up box to type in the max spread when you launch the script, adding that line creates a physical roadblock. In a flash-volatility scenario, you cannot afford to waste 2 seconds clicking "OK" on a dialog box. Hardcoding the MaxSpreadPoints variable directly ensures instant firing.
The continue Statement: If the spread exceeds your limit, the script hits the continue command. This aborts the rest of the code for that specific position and instantly jumps to evaluate the next trade in the loop.
Points vs. Pips: MT5 reads spread in "points" (the final decimal place). For JPY pairs, brokers usually quote 3 decimal places (e.g., 150.123). Therefore, 1 pip = 10 points. A max spread of 500 equals 50 pips.
Re: Shutdown drills for yen traders: a case study approach
Posted: Sun Oct 25, 2026 9:05 pm
by PTScalper
To make the script persistently retry until the spread normalizes, you must wrap the position-closing logic in a continuous while loop. The script will scan the book, close what it can, and if any positions are skipped, it will pause for a fraction of a second and scan again.
Pending orders should still be deleted immediately on the first pass, as they are not subject to spread restrictions.