Close-All/Close-All.mq5
2025-09-19 20:12:52 +00:00

376 lines
30 KiB
MQL5

//+------------------------------------------------------------------+
//| Close-All.mq5 |
//| Copyright © 2018, Amr Ali |
//| https://www.mql5.com/en/users/amrali |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2018, Amr Ali"
#property link "https://www.mql5.com/en/users/amrali"
#property version "9.300"
#property description "A script to close all market positions and/or pending orders."
#property script_show_inputs
//---
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Arrays\ArrayLong.mqh>
//---
CTrade trade; // trading object
CPositionInfo position; // position info object
COrderInfo order; // order info object
CArrayLong arr_tickets; // array tickets
//---
enum ENUM_CLOSE_MODE
{
CLOSE_MODE_ALL, // Positions and Pending Orders
CLOSE_MODE_POSITIONS, // Positions Only
CLOSE_MODE_ORDERS // Pending Orders
};
enum ENUM_CLOSE_SYMBOL
{
CLOSE_SYMBOL_ALL, // All Symbols
CLOSE_SYMBOL_CHART // Current Chart Symbol
};
enum ENUM_CLOSE_PROFIT
{
CLOSE_PROFIT_ALL, // All Profitable and Losing Positions
CLOSE_PROFIT_PROFITONLY, // Profitable Positions Only
CLOSE_PROFIT_LOSSONLY // Losing Positions Only
};
enum ENUM_CLOSE_TYPE
{
CLOSE_TYPE_ALL, // All Buy and Sell Positions
CLOSE_TYPE_BUY, // Buy Positions Only
CLOSE_TYPE_SELL // Sell Positions Only
};
enum ENUM_CLOSE_ORDERS
{
CLOSE_ORDERS_ALL, // All Order Types
CLOSE_ORDERS_LIMIT, // Limit Orders Only
CLOSE_ORDERS_STOP, // Stop Orders Only
CLOSE_ORDERS_STOPLIMIT // Stop Limit Orders Only
};
//--- input parameters
input ENUM_CLOSE_MODE InpCloseMode = CLOSE_MODE_ALL; // Mode
input ENUM_CLOSE_SYMBOL InpCloseSymbol = CLOSE_SYMBOL_ALL; // Symbols
input ENUM_CLOSE_PROFIT InpCloseProfit = CLOSE_PROFIT_ALL; // Profit / Loss
input ENUM_CLOSE_TYPE InpCloseType = CLOSE_TYPE_ALL; // Buy / Sell
input ENUM_CLOSE_ORDERS InpCloseOrders = CLOSE_ORDERS_ALL; // Pending Orders
input string xx2; // ============
input uint RTOTAL = 5; // Retries
input uint SLEEPTIME = 1000; // Sleep Time (msec)
input bool InpAsyncMode = true; // Asynchronous Mode
input bool InpDisAlgo = false; // Disable AlgoTrading Button
//+------------------------------------------------------------------+
//| script start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- preliminary checks for trading functions
if(CheckTradingPermission()==false)
{
return;
}
//--- initialize common information
trade.SetDeviationInPoints(INT_MAX);
trade.SetAsyncMode(InpAsyncMode);
trade.SetMarginMode();
trade.LogLevel(LOG_LEVEL_ERRORS);
//--- close positions and/or delete pending orders
switch((ENUM_CLOSE_MODE)InpCloseMode)
{
case CLOSE_MODE_ALL:
ClosePositions();
DeletePendingOrders();
break;
case CLOSE_MODE_POSITIONS:
ClosePositions();
break;
case CLOSE_MODE_ORDERS:
DeletePendingOrders();
break;
}
//--- disable the 'algo-trading' button
if(InpDisAlgo)
{
AlgoTradingStatus(false);
}
}
//+------------------------------------------------------------------+
//| Check for permission to perform automated trading |
//+------------------------------------------------------------------+
bool CheckTradingPermission()
{
if(!MQLInfoInteger(MQL_TESTER))
{
//--- Terminal - internet connection
if(!TerminalInfoInteger(TERMINAL_CONNECTED))
{
Alert("Error: No connection to the trade server!");
return(false);
}
//--- Account - server connection
if(!AccountInfoInteger(ACCOUNT_LOGIN))
{
Alert("Error: Trade information is not downloaded (not connected).");
return(false);
}
//--- Terminal - Checking for permission to perform automated trading in the terminal
if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Alert("Error: Automated trading is not allowed in the terminal settings, or 'Algo Trading' button is disabled.");
return(false);
}
//--- Expert - Checking if trading is allowed for a certain running Expert Advisor/script
if(!MQLInfoInteger(MQL_TRADE_ALLOWED))
{
Alert("Error: Live trading is not allowed in the program properties of '", MQLInfoString(MQL_PROGRAM_NAME), "'");
return(false);
}
//---
if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
{
Alert("Error: Trading is not allowed for the account ", AccountInfoInteger(ACCOUNT_LOGIN), " [investor mode].");
return(false);
}
//---
if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT))
{
Alert("Error: Expert advisors are not allowed for the account ", AccountInfoInteger(ACCOUNT_LOGIN), " at the trade server.");
return(false);
}
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Checks if the market is currently open for the specified symbol |
//+------------------------------------------------------------------+
bool CheckSessionTrade(const string symbol)
{
MqlDateTime STime;
datetime time = TimeTradeServer(STime);
datetime time_sec = time % PeriodSeconds(PERIOD_D1);
//---
datetime from,to;
uint session_index=0;
while(SymbolInfoSessionTrade(symbol,(ENUM_DAY_OF_WEEK)STime.day_of_week,session_index++,from,to))
if(time_sec >=from && time_sec <= to)
return true;
//---
return false;
}
//+------------------------------------------------------------------+
//| Close market positions |
//+------------------------------------------------------------------+
void ClosePositions()
{
//---
for(uint retry=0; retry<RTOTAL && !IsStopped(); retry++)
{
bool result = true;
//--- Collect and Close Method (FIFO-Compliant, for US brokers)
//--- Tickets are processed starting with the oldest one.
arr_tickets.Shutdown();
for(int i=0; i<PositionsTotal() && !IsStopped(); i++)
{
ResetLastError();
if(!position.SelectByIndex(i))
{
PrintFormat("> Error: selecting position with index #%d failed. Error Code: %d",i,GetLastError());
result = false;
continue;
}
if(InpCloseSymbol==CLOSE_SYMBOL_CHART && position.Symbol()!=Symbol())
{
continue;
}
if(InpCloseProfit==CLOSE_PROFIT_PROFITONLY && (position.Swap()+position.Profit()<=0))
{
continue;
}
if(InpCloseProfit==CLOSE_PROFIT_LOSSONLY && (position.Swap()+position.Profit()>=0))
{
continue;
}
if(InpCloseType==CLOSE_TYPE_BUY && position.PositionType()!=POSITION_TYPE_BUY)
{
continue;
}
if(InpCloseType==CLOSE_TYPE_SELL && position.PositionType()!=POSITION_TYPE_SELL)
{
continue;
}
//--- build array of position tickets to be processed
if(!arr_tickets.Add(position.Ticket()))
{
PrintFormat("> Error: adding position ticket #%I64u failed.",position.Ticket());
result = false;
}
}
//--- now process the list of tickets stored in the array
for(int i=0; i<arr_tickets.Total() && !IsStopped(); i++)
{
ResetLastError();
ulong curr_ticket = arr_tickets.At(i);
if(!position.SelectByTicket(curr_ticket))
{
PrintFormat("> Error: selecting position ticket #%I64u failed. Error Code: %d",curr_ticket,GetLastError());
result = false;
continue;
}
//--- check trading session
if(!CheckSessionTrade(position.Symbol()))
{
PrintFormat("> Error: closing position ticket #%I64u on %s is prohibited [Market closed].",position.Ticket(),position.Symbol());
continue;
}
//--- check freeze level
int freeze_level = (int)SymbolInfoInteger(position.Symbol(),SYMBOL_TRADE_FREEZE_LEVEL);
double point = SymbolInfoDouble(position.Symbol(),SYMBOL_POINT);
bool TP_check = MathAbs(position.PriceCurrent() - position.TakeProfit()) > freeze_level * point;
bool SL_check = MathAbs(position.PriceCurrent() - position.StopLoss()) > freeze_level * point;
if(!TP_check || !SL_check)
{
PrintFormat("> Error: closing position ticket #%I64u on %s is prohibited. Position TP or SL is too close to activation price [FROZEN].",position.Ticket(),position.Symbol());
result = false;
continue;
}
//--- trading object
trade.SetExpertMagicNumber(position.Magic());
trade.SetTypeFillingBySymbol(position.Symbol());
//--- close positions
if(trade.PositionClose(position.Ticket()) && (trade.ResultRetcode()==TRADE_RETCODE_DONE || trade.ResultRetcode()==TRADE_RETCODE_PLACED))
{
PrintFormat("Position ticket #%I64u on %s to be closed.",position.Ticket(),position.Symbol());
PlaySound("expert.wav");
}
else
{
PrintFormat("> Error: closing position ticket #%I64u on %s failed. Retcode=%u (%s)",position.Ticket(),position.Symbol(),trade.ResultRetcode(),trade.ResultComment());
result = false;
}
}
if(result)
break;
Sleep(SLEEPTIME);
PlaySound("timeout.wav");
}
}
//+------------------------------------------------------------------+
//| Delete pending orders |
//+------------------------------------------------------------------+
void DeletePendingOrders()
{
//---
for(uint retry=0; retry<RTOTAL && !IsStopped(); retry++)
{
bool result = true;
//--- Collect and Close Method (FIFO-Compliant, for US brokers)
//--- Tickets are processed starting with the oldest one.
arr_tickets.Shutdown();
for(int i=0; i<OrdersTotal() && !IsStopped(); i++)
{
ResetLastError();
if(!order.SelectByIndex(i))
{
PrintFormat("> Error: selecting order with index #%d failed. Error Code: %d",i,GetLastError());
result = false;
continue;
}
if(InpCloseSymbol==CLOSE_SYMBOL_CHART && order.Symbol()!=Symbol())
{
continue;
}
if(InpCloseOrders==CLOSE_ORDERS_LIMIT && order.OrderType()!=ORDER_TYPE_BUY_LIMIT && order.OrderType()!=ORDER_TYPE_SELL_LIMIT)
{
continue;
}
if(InpCloseOrders==CLOSE_ORDERS_STOP && order.OrderType()!=ORDER_TYPE_BUY_STOP && order.OrderType()!=ORDER_TYPE_SELL_STOP)
{
continue;
}
if(InpCloseOrders==CLOSE_ORDERS_STOPLIMIT && order.OrderType()!=ORDER_TYPE_BUY_STOP_LIMIT && order.OrderType()!=ORDER_TYPE_SELL_STOP_LIMIT)
{
continue;
}
//--- build array of order tickets to be processed
if(!arr_tickets.Add(order.Ticket()))
{
PrintFormat("> Error: adding order ticket #%I64u failed.",order.Ticket());
result = false;
}
}
//--- now process the list of tickets stored in the array
for(int i=0; i<arr_tickets.Total() && !IsStopped(); i++)
{
ResetLastError();
ulong curr_ticket = arr_tickets.At(i);
if(!order.Select(curr_ticket))
{
PrintFormat("> Error: selecting order ticket #%I64u failed. Error Code: %d",curr_ticket,GetLastError());
result = false;
continue;
}
//--- check trading session
if(!CheckSessionTrade(order.Symbol()))
{
PrintFormat("> Error: deleting order ticket #%I64u on %s is prohibited [Market closed].",order.Ticket(),order.Symbol());
continue;
}
//--- check freeze level
int freeze_level = (int)SymbolInfoInteger(order.Symbol(),SYMBOL_TRADE_FREEZE_LEVEL);
double point = SymbolInfoDouble(order.Symbol(),SYMBOL_POINT);
bool activ_check = MathAbs(order.PriceCurrent() - order.PriceOpen()) > freeze_level * point;
if(!activ_check)
{
PrintFormat("> Error: deleting order ticket #%I64u on %s is prohibited. Order open price is too close to activation price [FROZEN].",order.Ticket(),order.Symbol());
result = false;
continue;
}
//--- delete orders
if(trade.OrderDelete(order.Ticket()) && (trade.ResultRetcode()==TRADE_RETCODE_DONE || trade.ResultRetcode()==TRADE_RETCODE_PLACED))
{
PrintFormat("Order ticket #%I64u on %s to be deleted.",order.Ticket(),order.Symbol());
PlaySound("expert.wav");
}
else
{
PrintFormat("> Error: deleting order ticket #%I64u on %s failed. Retcode=%u (%s)",order.Ticket(),order.Symbol(),trade.ResultRetcode(),trade.ResultComment());
result = false;
}
}
if(result)
break;
Sleep(SLEEPTIME);
PlaySound("timeout.wav");
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define MT_WMCMD_EXPERTS 32851
#define WM_COMMAND 0x0111
#define GA_ROOT 2
#include <WinAPI\winapi.mqh>
//+------------------------------------------------------------------+
//| Toggle auto-trading button |
//+------------------------------------------------------------------+
void AlgoTradingStatus(bool Enable)
{
bool Status = (bool) TerminalInfoInteger(TERMINAL_TRADE_ALLOWED);
if(Enable != Status)
{
HANDLE hChart = (HANDLE) ChartGetInteger(ChartID(), CHART_WINDOW_HANDLE);
PostMessageW(GetAncestor(hChart, GA_ROOT), WM_COMMAND, MT_WMCMD_EXPERTS, 0);
}
}
//+------------------------------------------------------------------+