The ManageTrailingStop module not working

 
Hello!
In this module, it is supposed to close half the volume after the price moves 10 pips into profit and move the stop loss to the entry point plus commission. However, unfortunately, after 10 pips of profit, the entire volume is closed in consecutive positions.

Module code:

void ManageTrailingStop()
{
   if(OrdersTotal() == 0) return; // Exit if no open orders

   int ticket = -1;
   for(int i = 0; i < OrdersTotal(); i++) // Find first matching order
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         if(OrderSymbol() == _Symbol && OrderMagicNumber() == 12345)
         {
            ticket = OrderTicket();
            break;
         }
      }
   }

   if(ticket == -1) return; // No matching order found

   if(OrderSelect(ticket, SELECT_BY_TICKET))
   {
      double point = Point * 10; // 1 pip = 10 points for XAUUSD
      double openPrice = OrderOpenPrice();
      double sl = OrderStopLoss();
      double commission = MathAbs(OrderCommission()) / OrderLots();

      if(OrderType() == OP_BUY)
      {
         double currentProfit = Bid - openPrice;
         if(currentProfit >= 10 * point && !riskFreeDone) // 10 pips = 100 points
         {
            double halfLots = NormalizeDouble(OrderLots() / 2, 2);
            if(OrderClose(ticket, halfLots, Bid, 3, clrRed))
            {
               Sleep(100); // Small delay for server update
               if(OrderSelect(ticket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
               {
                  if(OrderModify(ticket, openPrice, openPrice + commission, OrderTakeProfit(), 0, clrGreen))
                  {
                     riskFreeDone = true;
                     Print("Risk-free successful: SL moved to ", openPrice + commission);
                  }
                  else
                  {
                     Print("OrderModify failed: Error ", GetLastError());
                  }
               }
               return; // Exit after processing
            }
         }
         else if(currentProfit >= 20 * point && sl < openPrice + 10 * point) // 20 pips = 200 points
         {
            OrderModify(ticket, openPrice, openPrice + 10 * point, OrderTakeProfit(), 0, clrGreen);
         }
      }
      else if(OrderType() == OP_SELL)
      {
         double currentProfit = openPrice - Ask;
         if(currentProfit >= 10 * point && !riskFreeDone) // 10 pips = 100 points
         {
            double halfLots = NormalizeDouble(OrderLots() / 2, 2);
            if(OrderClose(ticket, halfLots, Ask, 3, clrRed))
            {
               Sleep(100); // Small delay for server update
               if(OrderSelect(ticket, SELECT_BY_TICKET) && OrderCloseTime() == 0)
               {
                  if(OrderModify(ticket, openPrice, openPrice - commission, OrderTakeProfit(), 0, clrGreen))
                  {
                     riskFreeDone = true;
                     Print("Risk-free successful: SL moved to ", openPrice - commission);
                  }
                  else
                  {
                     Print("OrderModify failed: Error ", GetLastError());
                  }
               }
               return; // Exit after processing
            }
         }
         else if(currentProfit >= 20 * point && sl > openPrice - 10 * point) // 20 pips = 200 points
         {
            OrderModify(ticket, openPrice, openPrice - 10 * point, OrderTakeProfit(), 0, clrGreen);
         }
      }
   }
}

Result log:

1       2025.03.03 03:53        buy     1       1.00    2870.55 2869.16 2873.16 0.00    10000.00
2       2025.03.03 03:54        close   1       0.50    2871.55 2869.16 2873.16 47.50   10047.50
3       2025.03.03 03:54        buy     2       0.50    2870.55 2869.16 2873.16 0.00    10047.50
4       2025.03.03 03:54        close   2       0.25    2871.58 2869.16 2873.16 24.50   10072.00
5       2025.03.03 03:54        buy     3       0.25    2870.55 2869.16 2873.16 0.00    10072.00
6       2025.03.03 03:54        close   3       0.13    2871.60 2869.16 2873.16 13.00   10085.00
7       2025.03.03 03:54        buy     4       0.12    2870.55 2869.16 2873.16 0.00    10085.00
8       2025.03.03 03:54        close   4       0.06    2871.62 2869.16 2873.16 6.12    10091.12
9       2025.03.03 03:54        buy     5       0.06    2870.55 2869.16 2873.16 0.00    10091.12
10      2025.03.03 03:54        close   5       0.03    2871.64 2869.16 2873.16 3.12    10094.24
11      2025.03.03 03:54        buy     6       0.03    2870.55 2869.16 2873.16 0.00    10094.24
12      2025.03.03 03:54        close   6       0.02    2871.67 2869.16 2873.16 2.14    10096.38
13      2025.03.03 03:54        buy     7       0.01    2870.55 2869.16 2873.16 0.00    10096.38
14      2025.03.03 03:54        close   7       0.01    2871.69 2869.16 2873.16 1.09    10097.47

Please help me

 

You are not checking if a trade is already being partially closed.

You have used 'riskFreeDone' but you have not inizialized it. Also it's a single variable, if you have multiple trades it will not work.

Usually on MT4, a common way to check if a trade is already partially closed, is to check if in the comment there is the # symbol. (Do the partial close if StringFind return -1)

MT4 already change comment to partially closed trades adding #from with the old ticket number. But be aware that this can be different on some brokers and also not supposed to be 100% consistent. Anyway, personally, using this approach I never had problem.