Problem Description
Solution
To implement a feature that automatically closes all open trades at a specific time (e.g., 5 PM) on Fridays, you need to check the server time within the OnTick() function.
Here is the complete, robust MQL4 code snippet that you can integrate into your Expert Advisor.
MQL4 Code Implementation
//+------------------------------------------------------------------+
//| FridayCloseBot.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
//--- Input Parameters
input int MagicNumber = 123456; // Unique ID for this EA's trades
input int Slippage = 3; // Max slippage allowed in points
input int CloseDay = 5; // Day to close (0=Sun, 1=Mon, ..., 5=Fri, 6=Sat)
input int CloseHour = 17; // Hour to close (Server Time, 0-23)
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if the current time matches the closing criteria
if(IsClosingTime())
{
CloseAllPositions();
}
// --- Your standard entry logic would go here ---
// Example: if(!IsClosingTime() && EntryCondition) { OpenTrade(); }
}
//+------------------------------------------------------------------+
//| Check if it is time to close trades |
//+------------------------------------------------------------------+
bool IsClosingTime()
{
// DayOfWeek(): 0=Sunday, 1=Monday, ..., 5=Friday, 6=Saturday
// Hour(): Returns the current hour (0, 1, 2, ... 23) of the last known server time
if(DayOfWeek() == CloseDay && Hour() >= CloseHour)
{
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
//| Close all open positions for this EA |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
// Iterate backwards through orders to avoid index shifting issues when closing
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
// Select the order by index
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
// Filter by Symbol and Magic Number to ensure we only close our own trades
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
// Refresh rates to get the absolute latest Bid/Ask prices
RefreshRates();
bool result = false;
// Close Buy Positions
if(OrderType() == OP_BUY)
{
result = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, clrRed);
}
// Close Sell Positions
else if(OrderType() == OP_SELL)
{
result = OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, clrRed);
}
// Error Handling
if(!result)
{
Print("Failed to close order #", OrderTicket(), ". Error: ", GetLastError());
}
}
}
}
}
Key Logic Explanation
-
IsClosingTime()Function:- Uses
DayOfWeek(): Returns5for Friday. - Uses
Hour(): Returns the current hour of the Broker's Server Time (not your local computer time). - The logic
Hour() >= CloseHourensures that if the bot is disconnected exactly at 17:00 and reconnects at 17:05, it will still trigger the close logic.
- Uses
-
CloseAllPositions()Function:- Reverse Loop: The loop
for(int i = OrdersTotal() - 1; i >= 0; i--)iterates backwards. This is critical. If you close an order at index 0, the order at index 1 shifts down to index 0. A forward loop would skip orders; a reverse loop handles this correctly. OrderSelect: Selects the trade from the pool.- Filters: Checks
OrderSymbol() == Symbol()andOrderMagicNumber() == MagicNumberto ensure the bot doesn't close manual trades or trades from other bots. RefreshRates(): Called before closing to ensureBidandAskvariables hold the most current price data, reducingOff Quoteserrors.
- Reverse Loop: The loop
Important Considerations
- Server Time vs. Local Time: The
Hour()function uses the MetaTrader 4 server time. You must check your broker's time zone offset. If your broker is GMT+2 and you want to close at 5 PM your local time, you must adjust theCloseHourinput accordingly. - Execution: This logic runs inside
OnTick. If no ticks (price updates) occur exactly at 17:00:00 (e.g., low liquidity), the close command will execute on the very next tick received (e.g., 17:00:05).
Q&A
Q: How do I prevent the bot from opening new trades after closing them on Friday?
A: You should wrap your entry logic in a condition that checks !IsClosingTime(). For example:
if(!IsClosingTime() && YourEntrySignal == true) {
// OrderSend logic here
}
Q: Will this close Pending Orders (Limit/Stop orders)?
A: The code provided specifically checks for OP_BUY and OP_SELL (market orders). To close pending orders, you would add checks for OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP, and OP_SELLSTOP, and use OrderDelete() instead of OrderClose().
Q: What happens if the market is closed when the time is reached?
A: If the market is closed, OrderClose will fail with error 132 (Market is closed). However, since OnTick only runs when price updates come in, the code generally won't run if the market is fully halted, unless you are running it in a timer loop. For standard Forex pairs on Friday at 5 PM, the market is usually still open.