invalid volume issue MT5 Expert Verification

 
test on EURUSD,H1 (netting)
 2022.02.01 09:50:40   failed instant buy 0.01 EURUSD at 1.12584 sl: 1.12334 tp: 1.12734 [Invalid volume]
 2022.02.02 10:04:40   failed instant buy 0.01 EURUSD at 1.12886 sl: 1.12636 tp: 1.13036 [Invalid volume]
 2022.02.03 15:44:40   failed instant buy 0.01 EURUSD at 1.13416 sl: 1.13166 tp: 1.13566 [Invalid volume]

when trying to pass verification i am getting this error,  but i thought i covered everything in my two functions .  one being my Riskvolume and the other being NormaliseVolume.    


RiskVolume Function below. 

double GetRiskVolume( double risk, double loss ) {

   double equity     = AccountInfoDouble( ACCOUNT_EQUITY );
   double riskAmount = equity * risk; // risk in deposit currency

   double tickValue  = SymbolInfoDouble( Symbol(), SYMBOL_TRADE_TICK_VALUE ); // value of a tick in deposit currency
   double tickSize   = SymbolInfoDouble( Symbol(), SYMBOL_TRADE_TICK_SIZE );  // size of a tick price movement
   double lossTicks  = loss / tickSize;                                       // There may be rounding here, loss is in price movement

   double volume     = riskAmount / ( lossTicks * tickValue );
   volume            = NormaliseVolume( volume );

   return volume;
}



NormalizeVolume Function below 

double NormaliseVolume( double volume ) {

   if ( volume <= 0 ) return 0; // nothing to do

   double max    = SymbolInfoDouble( Symbol(), SYMBOL_VOLUME_MAX );
   double min    = SymbolInfoDouble( Symbol(), SYMBOL_VOLUME_MIN );
   double step   = SymbolInfoDouble( Symbol(), SYMBOL_VOLUME_STEP );

   double result = MathRound( volume / step ) * step;
   if ( result > max ) result = max;
   if ( result < min ) result = min;

   return result;
}



if there are no issues with these two functions then could the issue be in the OnTick() Function where i am placing the trade

 
  1. Limiting Number of Lots by a Specific Symbol ( SYMBOL_VOLUME_LIMIT )
  2. Use the function OrderCalcProfit instead.
The checks a trading robot must pass before publication in the Market
The checks a trading robot must pass before publication in the Market
  • www.mql5.com
Before any product is published in the Market, it must undergo compulsory preliminary checks in order to ensure a uniform quality standard. This article considers the most frequent errors made by developers in their technical indicators and trading robots. An also shows how to self-test a product before sending it to the Market.
 

actually i think the issue is with my opentrade bool  here look below.   look at //2. set volume based on risk

bool OpenTrade( ENUM_ORDER_TYPE type, double price, double sl, double takeProfit, long magic ) {

   // 1. allow 0 take profit
   if ( takeProfit == 0 ) return true;

   double tp = 0;

   if ( type == ORDER_TYPE_BUY ) {
      tp = price + takeProfit;
   }
   else {
      tp = price - takeProfit;
   }

   int digits    = ( int )SymbolInfoInteger( Symbol(), SYMBOL_DIGITS );
   price         = NormalizeDouble( price, digits );
   sl            = NormalizeDouble( sl, digits );
   tp            = NormalizeDouble( tp, digits );

   // 2. set volume based on risk
   double volume = 0;
   if ( InpRiskType == RISK_TYPE_EQUITY_PERCENT ) {
      volume = GetRiskVolume( InpRisk / 100, MathAbs( price - sl ) );
   }
   else if ( InpRiskType == RISK_TYPE_FIXED_LOTS ) {
      volume = InpRisk;
   }

#ifdef __MQL4__
   int ticket = OrderSend( Symbol(), type, volume, price, 0, sl, tp, InpTradeComment, ( int )magic );
   if ( ticket <= 0 ) {
      PrintFormat( "Error opening trade, type=%s, volume=%f, price=%f, sl=%f, tp=%f", EnumToString( type ), volume, price, sl, tp );
      return false;
   }
#endif

#ifdef __MQL5__
   Trade.SetExpertMagicNumber( magic );
   if ( !Trade.PositionOpen( Symbol(), type, volume, price, sl, tp, InpTradeComment ) ) {
      PrintFormat( "Error opening trade, type=%s, volume=%f, price=%f, sl=%f, tp=%f", EnumToString( type ), volume, price, sl, tp );
      return false;
   }
#endif

   return true;
}

i think the issue is on this line because when i use FIX Lot i have no issues at all.   

 
Ricks creations:

when trying to pass verification i am getting this error,  but i thought i covered everything in my two functions .  one being my Riskvolume and the other being NormaliseVolume.    


RiskVolume Function below. 



NormalizeVolume Function below 



if there are no issues with these two functions then could the issue be in the OnTick() Function where i am placing the trade

This is my current method for calculating lot size. You may be able to refer to it. I hope it will be helpful to you.

input string G_AutoLotsSetting    = "---------- Auto lots setting ----------"; // |
input string G_AutoLotsOptions    = "0=Balance, 1=SL risk, 2=TP risk, 3=Lots.";
input int    G_AutoLotsType       = 3;
input double G_MinLots            = 0.01;
input double G_MaxLots            = 50.00;
input double G_Balance            = 500;
input double G_SLRisk             = 2.00;
input double G_TPRisk             = 2.00;
input double G_Lots               = 0.01;
input bool   G_MartingaleSwitch   = false;
input bool   G_TotalCountSwitch   = false;
      int    G_TotalLossCount     = 0;
input double G_MartingaleMultiple = 2.50;

double AutoLots(string P_Symbol, int P_Magic, int P_StopLoss, int P_TakeProfit, int P_Multiple)
{
   double L_InitVolume = SymbolInfoDouble(P_Symbol, SYMBOL_VOLUME_MIN);
   double L_MinVolume  = SymbolInfoDouble(P_Symbol, SYMBOL_VOLUME_MIN);
   double L_MaxVolume  = SymbolInfoDouble(P_Symbol, SYMBOL_VOLUME_MAX);
   double L_TickValue  = SymbolInfoDouble(P_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double L_AutoVolume = 0;
   if (G_MinLots >= L_MinVolume)
   {
      L_MinVolume = G_MinLots;
   }
   if (G_MaxLots <= L_MaxVolume)
   {
      L_MaxVolume = G_MaxLots;
   }
   if (G_AutoLotsType == 0)
   {
      L_AutoVolume = (AccountInfoDouble(ACCOUNT_BALANCE) / G_Balance) * L_InitVolume;
   }
   else if (G_AutoLotsType == 1)
   {
      double L_RiskAmount = (AccountInfoDouble(ACCOUNT_BALANCE) * G_SLRisk) / 100.00;
      L_AutoVolume = L_RiskAmount / (P_StopLoss * P_Multiple * L_TickValue);
   }
   else if (G_AutoLotsType == 2)
   {
      double L_RiskAmount = (AccountInfoDouble(ACCOUNT_BALANCE) * G_TPRisk) / 100.00;
      L_AutoVolume = L_RiskAmount / (P_TakeProfit * P_Multiple * L_TickValue);
   }
   else if (G_AutoLotsType == 3)
   {
      L_AutoVolume = G_Lots;
   }
   if (G_MartingaleSwitch)
   {
      int L_AloneLossCount = 0;
      HistorySelect(0,TimeCurrent());
      if(HistoryDealsTotal() > 0)
      {
         for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
         {
            ulong L_OrderNumber = HistoryDealGetTicket(i);
            if (!HistoryDealSelect(L_OrderNumber))
            {
               continue;
            }
            bool L_Type   = HistoryDealGetInteger(L_OrderNumber,DEAL_ENTRY)  == DEAL_ENTRY_OUT;
            bool L_Symbol = HistoryDealGetString (L_OrderNumber,DEAL_SYMBOL) == P_Symbol;
            bool L_Magic  = HistoryDealGetInteger(L_OrderNumber,DEAL_MAGIC)  == P_Magic;
            if(L_Type && L_Symbol && L_Magic)
            {
               double L_OrderProfit = HistoryDealGetDouble(L_OrderNumber,DEAL_PROFIT);
               double L_OrderVolume = HistoryDealGetDouble(L_OrderNumber,DEAL_VOLUME);
               if (L_OrderProfit > 0)
               {
                  L_AloneLossCount = 0;
                  G_TotalLossCount = 0;
                  break;
               }
               else if (L_OrderProfit <= 0)
               {
                  L_AloneLossCount++;
                  G_TotalLossCount++;
                  if (!G_TotalCountSwitch)
                  {
                     L_AutoVolume = L_OrderVolume * MathPow(G_MartingaleMultiple, L_AloneLossCount);
                  }
                  else
                  {
                     L_AutoVolume = L_OrderVolume * MathPow(G_MartingaleMultiple, G_TotalLossCount);
                  }
               }
            }
         }
      }
   }
   double L_AutoLots = NormalizeDouble(L_AutoVolume,2);
   if (L_AutoLots >= L_MaxVolume)
   {
      L_AutoLots = L_MaxVolume;
   }
   else if (L_AutoLots <= L_MinVolume)
   {
      L_AutoLots = L_MinVolume;
   }
   return (L_AutoLots);
}