//+------------------------------------------------------------------+
//|                               CloseAllOnLossPercentOfBalance.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh>

CTrade trade;

// DLL Import for simulating Ctrl+E (AutoTrading toggle)
#import "user32.dll"
    void keybd_event(int bVk, int bScan, int dwFlags, int dwExtraInfo);
#import

#define REL  0x0002
#define CTRL 0x11
#define E    0x45

//--- Input parameters
input double LossPercentOfBalance   = 1.0;    // Loss % to trigger close and disable (e.g., 1%)
input bool   DisableAT              = false;  // Disable Auto Trading?
 
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("CloseOnProfit MT5 EA initialized.");
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Print("CloseOnProfit MT5 EA deinitialized.");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double totalSymbolProfit = 0.0;
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);

   //--- Calculate total profit for this symbol
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol)
         {
            double profit = PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
            totalSymbolProfit += profit;
         }
      }
   }

   double triggerProfit = (LossPercentOfBalance / 100.0) * balance;

   if(totalSymbolProfit< 0 && totalSymbolProfit <= -triggerProfit)
   {
      //--- Close all positions and delete all pending orders
      CloseAndDeleteAllSymbolOrders(_Symbol);

      //--- Check again if there are no more open positions or pending orders for this symbol
      bool noOrdersLeft = true;
      if(HasOpenPositionsOrOrders(_Symbol))
         noOrdersLeft = false;

      //--- If no more orders and AutoTrading is enabled, disable it
      if(DisableAT && noOrdersLeft && IsAutoTradingAllowed())
      {
         DisableAutoTrading();
      }
   }
  }
//+------------------------------------------------------------------+
//| Function to close all positions and delete pending orders       |
//+------------------------------------------------------------------+
void CloseAndDeleteAllSymbolOrders(string symbol)
{
   //--- Close all positions
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == symbol)
         {
            ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
            double volume = PositionGetDouble(POSITION_VOLUME);
            if(type == POSITION_TYPE_BUY || type == POSITION_TYPE_SELL)
            {
               if(!trade.PositionClose(ticket))
               {
                  Print("Failed to close position #", ticket, " Error: ", GetLastError());
                  Sleep(500);
                  if(!trade.PositionClose(ticket))
                     Print("Retry failed to close position #", ticket, " Error: ", GetLastError());
                  else
                     Print("Retry SUCCESS to close position #", ticket);
               }
            }
         }
      }
   }

   //--- Delete all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(OrderSelect(OrderGetTicket(i)))
      {
         if(OrderGetString(ORDER_SYMBOL) == symbol)
         {
            ENUM_ORDER_TYPE order_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
            // Check if it's a pending order
            if(order_type == ORDER_TYPE_BUY_LIMIT || order_type == ORDER_TYPE_SELL_LIMIT ||
               order_type == ORDER_TYPE_BUY_STOP  || order_type == ORDER_TYPE_SELL_STOP)
            {
               ulong order_ticket = OrderGetTicket(i);
               if(!trade.OrderDelete(order_ticket))
               {
                  Print("Failed to delete pending order #", order_ticket, " Error: ", GetLastError());
                  Sleep(500);
                  if(!trade.OrderDelete(order_ticket))
                     Print("Retry failed to delete pending order #", order_ticket, " Error: ", GetLastError());
                  else
                     Print("Retry SUCCESS to delete pending order #", order_ticket);
               }
            }
         }
      }
   }
}
//+------------------------------------------------------------------+
//| Function to check if any open positions or orders exist         |
//+------------------------------------------------------------------+
bool HasOpenPositionsOrOrders(string symbol)
{
   for(int i=PositionsTotal()-1; i>=0; i--)
   {
      if(PositionSelectByTicket(PositionGetTicket(i)))
      {
         if(PositionGetString(POSITION_SYMBOL) == symbol)
            return true;
      }
   }
   for(int i=OrdersTotal()-1; i>=0; i--)
   {
      if(OrderSelect(OrderGetTicket(i)))
      {
         if(OrderGetString(ORDER_SYMBOL) == symbol)
         {
            ENUM_ORDER_TYPE order_type = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
            if(order_type == ORDER_TYPE_BUY_LIMIT || order_type == ORDER_TYPE_SELL_LIMIT ||
               order_type == ORDER_TYPE_BUY_STOP  || order_type == ORDER_TYPE_SELL_STOP)
               return true;
         }
      }
   }
   return false;
}
//+------------------------------------------------------------------+
//| Function to check if AutoTrading is enabled                     |
//+------------------------------------------------------------------+
bool IsAutoTradingAllowed()
{
   return (TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == 1);
}
//+------------------------------------------------------------------+
//| Function to simulate Ctrl+E to disable Auto Trading             |
//+------------------------------------------------------------------+
void DisableAutoTrading()
{
   Print("Simulating Ctrl+E to disable Auto Trading...");
   keybd_event(CTRL,0,0,  0);
   keybd_event(E,   0,0,  0);
   keybd_event(CTRL,0,REL,0);
   keybd_event(E,   0,REL,0);
}
//+------------------------------------------------------------------+
