Discrepancies between script and backtest behaviour

 
I have been working on some code and I have reached a point where I am realizing that the backtest behaves erratically by performing actions and modifying variables that are not seen in the backtest "Journal" but I can see them reflected when printing these variables.
Primarily something that I don't understand is how the backtest works with the account balance. In my code, every time a buy order is sent I use the "AccountInfoDouble(ACCOUNT_MARGIN_FREE)" function to obtain the free margin available at that moment and calculate the corresponding volume and thus avoid problems of lack of money or a large volume in the purchase. At the same time I make sure to close the order before opening another so that there are no open orders that could be taking part of the free margin. As a way of controlling, I print the current balance value, free margin, price, volume, etc. every time a purchase is made. And what I am seeing is that during the backtest the value of free margin, equity and balance are drastically decreased as if the test deliberately leveraged the order by 10 at a time where there are losses with high percentages, even when the tester options are not enabling leverage. What is worse, when running the same EA with different initial deposits, I see that from a certain value onwards the algorithm goes from making almost 60 trades as it should to making only 1. For example, if the balance is 4000 you make 60 trades but if the balance is 3000 you make only 1, this limit is around the value in currency of the maximum volume allowed by the broker but I am not sure if it is related to this.

I would like to know first why the backtest has this behavior and what things can be improved in the code to avoid it, that is, if there are hidden variables that cannot be seen or better ways to work with the available balance or if there are a number of internal variables that cannot be seen. come but they affect the behavior and therefore beyond the information in the account we have to work with them. For example, I have noticed that if I print the result of "ACCOUNT_MARGIN_FREE" I get a different value than funcionAccountInfoDouble(ACCOUNT_MARGIN_FREE), it is as if there were a free margin value different from what we see in the account, this makes me suspect that beyond the volume I put into the purchase there may be hidden leverage or other variables that are having unexpected effects on the test. I leave you the code:
//+------------------------------------------------------------------+
//|                                                     RobotSMA.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
#include <Trade\Trade.mqh>
//#include <Trade\AccountInfo.mqh>


// Input Variables

input int ma1_period = 8; // MA Slow
input int ma2_period = 50; // MA Fast
input int rsi_period = 14;  // RSI period
input int rsi_bz = 30;  // RSI Buy Zone
input int rsi_sz = 70;  // RSI Sell Zone
input int macd_fast = 12;   // MACD fast EMA period
input int macd_slow = 26;   // MACD slow EMA period
input int macd_signal = 12;  // MACD signal line period
input double pips_sl = 10; // Stop Loss
input double pips_tp = 0.0112; // Take Profit

// Internal Variables
datetime date = 0;  // Declaración de la variable 'date'
double entry = 0;
int handle_ma1 = 0;
int handle_ma2 = 0;
int handle_rsi = 0;  // Declaration of 'handle_rsi'
int handle_macd = 0;
double array_ma_fast[];
double array_ma_slow[];
double array_rsi[];
double array_macd_main[];
double array_macd_signal[];
double array_macd_histogram[];
double perc_sl = 1-pips_sl/100;
double perc_tp = 1+pips_tp/100;
double balance = 0;
double balance2 = 0;
double balance3 = 0;
double balance4 = 0;
double balance5 = 0;
double vol=0;
int ticket = 0;
bool result;
double last_buy =0;
bool buy_context = false;
int retryAttempts = 3;
int retryCount = 0;
CTrade         trade; 
//CAccountInfo      account;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   handle_ma1 = iMA(Symbol(),Period(),ma1_period, 0, MODE_EMA,PRICE_CLOSE);
   handle_ma2 = iMA(Symbol(),Period(),ma2_period, 0, MODE_EMA,PRICE_CLOSE);
   handle_rsi = iRSI(Symbol(), Period(), rsi_period, PRICE_CLOSE);
   handle_macd = iMACD(Symbol(), Period(), macd_fast, macd_slow, macd_signal,PRICE_CLOSE);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+

void OnTick()
  {
   datetime LocalTime=TimeLocal();
   string HoursAndMinutes=TimeToString(LocalTime,TIME_MINUTES);
   string YearAndDate=TimeToString(LocalTime,TIME_DATE);
   MqlDateTime DateTimeStructure;
   TimeToStruct(LocalTime, DateTimeStructure);
   int day = DateTimeStructure.day_of_week;
   int hour = DateTimeStructure.hour;
   
   
   
   if (iTime(Symbol(),Period(),0) != date){
      
      entry = SymbolInfoDouble(Symbol(), SYMBOL_BID);
      
      if (Buy_Signal() && buy_context == false){
         
         entry = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
         balance = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
         balance2 = AccountInfoDouble(ACCOUNT_EQUITY);
         balance3 = AccountInfoDouble(ACCOUNT_BALANCE);
         balance4 = AccountInfoDouble(ACCOUNT_CREDIT);
         balance5 = AccountInfoDouble(ACCOUNT_PROFIT);
         vol = balance/entry;
         vol = MathFloor(vol * MathPow(10, 1)) / MathPow(10, 1);
         double min_volume = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN),_Digits);
         double max_volume = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX),_Digits);
         
         if(vol > max_volume){vol = max_volume;}
         Print("Max Volume=",max_volume,"Min Volume=",min_volume);
         Print("Volume=",NormalizeDouble(vol,_Digits), " Price=", NormalizeDouble(entry, _Digits), " Free Margin=", balance, " Equity=", balance2, " Balance=", balance3, " Credit=", balance4);
         result = trade.Buy(NormalizeDouble(vol,_Digits), Symbol(), NormalizeDouble(entry, _Digits), "Buy Order");
         if(result){
         Print("Buy Order Executed correctly");
         }else{
         Print("Buy Order Failed");
         ExpertRemove();
         }
         
         buy_context = true;
         last_buy = entry;
         
      }else if (Sell_Signal() && buy_context == true){
            //ticket = GetOpenPositionTicket();
            ticket = PositionGetTicket(PositionsTotal()-1);
            Print("Open position ticket: ", ticket);
            result = trade.PositionClose(ticket);
            
            // Check the result of the closing operation
            if (result){
               Print("Order with ticket ", ticket, " closed successfully.");
               buy_context = false;
            }
            else{
            Print("Error closing order with ticket ", ticket, ". Error code: ", GetLastError());
    
            }
            
      }
      
      else if  (buy_context == true && entry < last_buy * perc_sl){
            //ticket = GetOpenPositionTicket();
            ticket = PositionGetTicket(PositionsTotal()-1);
            Print("Open position ticket: ", ticket);
            result = trade.PositionClose(ticket);
            // Check the result of the closing operation
            if (result){
               Print("Order with ticket ", ticket, " closed successfully.");
               buy_context = false;
            }
            else{
               Print("Error closing order with ticket ", ticket, ". Error code: ", GetLastError());
            }
        } 
      else if (buy_context == true && entry > last_buy * perc_tp){ 
            //ticket = GetOpenPositionTicket();
            ticket = PositionGetTicket(PositionsTotal()-1);
            Print("Open position ticket: ", ticket);
            result = trade.PositionClose(ticket);
            // Check the result of the closing operation
            if (result){
            Print("Order with ticket ", ticket, " closed successfully.");
               buy_context = false;
            }
            else{
               Print("Error closing order with ticket ", ticket, ". Error code: ", GetLastError());
            }
        }
       else if (buy_context == true && day == 5 && hour == 22){
         Print("Closing open orders because is the end of Friday.");
         //ticket = GetOpenPositionTicket();
         ticket = PositionGetTicket(PositionsTotal()-1);
         Print("Open position ticket: ", ticket);
         result = trade.PositionClose(ticket);
         // Check the result of the closing operation
         if (result){
            Print("Order with ticket ", ticket, " closed successfully.");
            buy_context = false;
            }
         else{
            Print("Error closing order with ticket ", ticket, ". Error code: ", GetLastError());
            }
        }    
        

      

  
      date = iTime(Symbol(),Period(),0);
   }
   
  }
//+------------------------------------------------------------------+


// Funciones 

bool Buy_Signal (){
   
//   if (array_ma_fast[0] > array_ma_slow[0] && array_ma_fast[1] < array_ma_slow[1] &&
   ArraySetAsSeries(array_ma_fast,true);
   ArraySetAsSeries(array_ma_slow,true);
   CopyBuffer(handle_ma1,0,1,2,array_ma_fast);
   CopyBuffer(handle_ma2,0,1,2,array_ma_slow);
   
   ArraySetAsSeries(array_rsi, true);
   CopyBuffer(handle_rsi, 0, 1, 2, array_rsi);

   ArraySetAsSeries(array_macd_main, true);
   ArraySetAsSeries(array_macd_signal, true);
   ArraySetAsSeries(array_macd_histogram, true);
   CopyBuffer(handle_macd, 0, 1, 2, array_macd_main);
   CopyBuffer(handle_macd, 1, 1, 2, array_macd_signal);
   CopyBuffer(handle_macd, 2, 1, 2, array_macd_histogram);
   
   if(     array_rsi[0] < rsi_bz &&  // RSI is below 30 (oversold condition)
        array_macd_main[0] > array_macd_signal[0] && array_macd_main[1] < array_macd_signal[1]){
      return true;
   } else {
      return false;
   }    
}

bool Sell_Signal(){


     ArraySetAsSeries(array_ma_fast,true);
     ArraySetAsSeries(array_ma_slow,true);
     CopyBuffer(handle_ma1,0,1,2,array_ma_fast);
     CopyBuffer(handle_ma2,0,1,2,array_ma_slow);
   
     ArraySetAsSeries(array_rsi, true);
     CopyBuffer(handle_rsi, 0, 1, 2, array_rsi);

     ArraySetAsSeries(array_macd_main, true);
     ArraySetAsSeries(array_macd_signal, true);
     ArraySetAsSeries(array_macd_histogram, true);
     CopyBuffer(handle_macd, 0, 1, 2, array_macd_main);
     CopyBuffer(handle_macd, 1, 1, 2, array_macd_signal);
     CopyBuffer(handle_macd, 2, 1, 2, array_macd_histogram);
     
     
//   if (array_ma_fast[0] < array_ma_slow[0] && array_ma_fast[1] > array_ma_slow[1] &&
    if (array_rsi[0] > rsi_sz){  // RSI is above 70 (overbought condition)
//      if (array_macd_main[0] < array_macd_signal[0] && array_macd_main[1] > array_macd_signal[1]){
      return true;
   } else {
      return false;
   }    
}

ulong GetOpenPositionTicket()
{
    for (int i = 0; i < PositionsTotal(); i++)
    {
        ulong ticket = PositionGetTicket(i);
        
        // Check if the position is open
        if (PositionSelectByTicket(ticket) && PositionGetSymbol(i) == Symbol() && PositionGetInteger(POSITION_TYPE) <= ORDER_TYPE_BUY)

        {
            return ticket;
        }
    }

    return 0;  // No open position found
}