[Invalid Stops]- Print("Stop Level is: ", stops_level); returning 0

 

Hello,

I am encountering the "Invalid Stops" error message in my EA code. After conducting a check, the value that is being returned is 0. I have confirmed that the issue is related to the stop loss and not the take profit, as I am not placing a take profit at execution.

I would like to know if you have any suggestions as to what might be causing this error message to appear, and how I can go about resolving it. I would appreciate any insights or advice you might have regarding this matter.

Thank you.

Check:

 int stops_level=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL);
   if(stops_level!=0)
     {
      PrintFormat("SYMBOL_TRADE_STOPS_LEVEL=%d: StopLoss and TakeProfit must"+
                  " not be nearer than %d points from the closing price",stops_level,stops_level);
     }
     Print("Stop Level is:  ", stops_level);

Output:


 bool Buy_SL_check=(symbol_Info.Bid()-EMA_TrailStop[0] > stopLevel*_Point);
 bool Sell_SL_check=(EMA_TrailStop[0]-symbol_Info.Ask() > stopLevel*_Point);
 
Rafael Santos:

Hello,

I am encountering the "Invalid Stops" error message in my EA code. After conducting a check, the value that is being returned is 0. I have confirmed that the issue is related to the stop loss and not the take profit, as I am not placing a take profit at execution.

I would like to know if you have any suggestions as to what might be causing this error message to appear, and how I can go about resolving it. I would appreciate any insights or advice you might have regarding this matter.

Thank you.

Check:

Output:


My friend you should share your source code.

 
Rafael Santos:

Hello,

I am encountering the "Invalid Stops" error message in my EA code. After conducting a check, the value that is being returned is 0. I have confirmed that the issue is related to the stop loss and not the take profit, as I am not placing a take profit at execution.

I would like to know if you have any suggestions as to what might be causing this error message to appear, and how I can go about resolving it. I would appreciate any insights or advice you might have regarding this matter.

Thank you.

Check:

Output:


0 is not the stop level, it is the minimum number of points from last price where you can place a stop
 
Paul Anscombe #:
0 is not the stop level, it is the minimum number of points from last price where you can place a stop

How do I get the actual stop level?


Thanks!

 
Rafael Santos #:

How do I get the actual stop level?


Thanks!

As noted by Yashar, you should post the source code where you get the invalid stop error, as well as the values used for you entry price and sl, and finally the last tick price (bid/ask).
 

Apologies for the delay in my response. I have diligently conducted further research and attempted various solutions to address the issue at hand, unfortunately without success.

In order to ensure compliance with all necessary criteria a trading robot must meet prior to being published in the Market,https://www.mql5.com/en/articles/2555, I have initiated a test template for m Expert Advisors (EAs).

so far, all  checks implemented appear to be functioning correctly, with the exception of the "invalid stop levels" error. I have provided the relevant code and a snippet of the output values pertaining to the stop levels below. Your assistance and expertise in resolving this matter would be greatly appreciated.


Buy trade output:



Sell trade output:



//+------------------------------------------------------------------+
//|                                        Invalid Stoploss Test.mq5 |
//|                        Copyright 2023,Santos Family Holdings LLC |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023,Santos Family Holdings LLC"
#property version   "1.0"

#include <Trade\Trade.mqh>
#include <Trade\AccountInfo.mqh>
#include <MovingAverages.mqh>

input int magicNumber = 11162022;// Magic Number

input int startHour = 0; //Start Hour
input int startMinute = 0; //Start Minute
input int endHour = 23; // End Hour
input int endMinute = 59; // End minute

input double maxDailyDrawdownPercent = 10.0; // Maximum daily drawdown percent

input double lotSize = 0.1; // Lot size
input double stopLossPoints =3000; // Stoploss in points
input double takeProfitPoints =13000; // Take profit in points
input int trailingStopPoints = 3000; //Trailing stoploss in points ***Not active yet***

input bool tradeMonday = true; //Trade on Moday
input bool tradeTuesday = true; //Trade on Tuesday
input bool tradeWednesday = true; //Trade on Wednesday
input bool tradeThursday = true; //Trade on Thursday
input bool tradeFriday = true; //Trade on Friday

//Global Variables
double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double PointValue =0;

//Trade classes and Handles
CTrade trade;
CAccountInfo AccInfo;
int ma6Handle, ma26Handle, ma58Handle, ma60Handle;

//+------------------------------------------------------------------+
//| Oninit                                                           |
//+------------------------------------------------------------------+
int OnInit()
  {
  //Set Magic number and Filing type
   trade.SetTypeFillingBySymbol(_Symbol);
   trade.SetExpertMagicNumber(magicNumber);
   
// Initialize moving averages
   ma6Handle = iMA(_Symbol, PERIOD_CURRENT, 6, 0, MODE_SMA, PRICE_CLOSE);
   ma26Handle = iMA(_Symbol, PERIOD_CURRENT, 26, 0, MODE_SMA, PRICE_CLOSE);
   ma58Handle = iMA(_Symbol, PERIOD_CURRENT, 58, 0, MODE_SMA, PRICE_CLOSE);
   ma60Handle = iMA(_Symbol, PERIOD_CURRENT, 60, 0, MODE_SMA, PRICE_CLOSE);
   if(ma6Handle == INVALID_HANDLE || ma26Handle == INVALID_HANDLE || ma58Handle == INVALID_HANDLE || ma60Handle == INVALID_HANDLE)
     {
      return INIT_FAILED;
     }
     else
     {
      Print("Moving average indicator handles have been initialized ");
     }
     
//Check valid lotsize
   if(!checkValidVolume(lotSize))
     {
      Print("Invalid Volume, Check lot size: ",lotSize);
      return INIT_FAILED;
     }
     else
     {
      Print("Lot size is withing the symbol requirements, lot size: ", lotSize);
     }
//Check if trading is allowed
   bool tradeAllowed= TerminalInfoInteger(TERMINAL_TRADE_ALLOWED);
   if(!tradeAllowed)
     {
      Print("Terminal check: Trading is not allowed");
      return INIT_FAILED;
     }
     else
     {
      Print("Terminal check: Trading is allowed");
     }

   double MyPoint=_Point;
   if(_Digits==3 || _Digits==5)
      MyPoint=_Point*10;
   PointValue= MyPoint;
   if(!PointValue)
     {
      Print("Current symbol point value Error: ",GetLastError());
      return INIT_FAILED;
     }
   else
     {
      Print("The current symbol point value is: ",PointValue);
     }


   if(!Bars(_Symbol,_Period)>100)
     {
      Print("There is not enough price history available on this chart.");
      return INIT_FAILED;
     }
   else
     {Print("There is enough price data for trading on this chart");}

   return INIT_SUCCEEDED;
  }
//+------------------------------------------------------------------+
//| Check for open                                                   |
//+------------------------------------------------------------------+
void CheckForOpen(void)
  {
// Run Checks before placing trades
   if(!isTradingTime())
     {Print("It is not time to trade, Start Hour: ", startHour,"Start Minute: ", startMinute);}
   else
     {
      if(!isTradingDay())
        {Print("Today is not an active trading day, check inputs for more information");}
      else
        {
         if(!checkMaxDailyDrawdown())
           {Print("The Max Daily drawdown has been reached: ", checkMaxDailyDrawdown(), " There will be no more tarding for today");}
         else
           {
            //Print("The Max Daily drawdown is : ", checkMaxDailyDrawdown());


            // Update moving average values
            double ma6Value[2], ma26Value[2], ma58Value[2], ma60Value[2];
            if(CopyBuffer(ma6Handle, 0, 0, 2, ma6Value) != 2 ||
               CopyBuffer(ma26Handle, 0, 0, 2, ma26Value) != 2 ||
               CopyBuffer(ma58Handle, 0, 0, 2, ma58Value) != 2 ||
               CopyBuffer(ma60Handle, 0, 0, 2, ma60Value) != 2)
              {
               Print("Error updating moving average values.");
               return;
              }


            ENUM_ORDER_TYPE signal=WRONG_VALUE;
            if(//---Buy conditions
               //example condition for testing
               ma6Value[0] > ma60Value[0]

            )
               signal=ORDER_TYPE_BUY;    // Set buy order type

            if(//---Sell Conditions
               //example condition for testing
               ma6Value[0] < ma60Value[0]


            )
               signal=ORDER_TYPE_SELL;    // Set sell order type



            if(signal==ORDER_TYPE_BUY)
              {
               double entryPrice = Ask;
               double stopLoss = entryPrice - stopLossPoints * PointValue;
               double takeProfit = entryPrice + takeProfitPoints * PointValue;
               Print("Buy Order Entry Price: ", entryPrice," Buy Order Stoploss: ",stopLoss," Buy Order Take profit: ",takeProfit," Symbol trade stops level: ", SYMBOL_TRADE_STOPS_LEVEL," checkStopLossTakeProfitLevels(): ", checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit));
               double marginCheck = AccInfo.MarginCheck(_Symbol,ORDER_TYPE_BUY,lotSize,entryPrice);
               double freeMarginCheck = AccInfo.FreeMargin();
               //Print("marginCheck: ", marginCheck,"freeMarginCheck: ",freeMarginCheck);

               //Check margin and stop levels
               if(marginCheck < freeMarginCheck && checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit))
                 {
                  //Open buy trade
                  if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,lotSize,entryPrice,stopLoss,takeProfit))
                    {Print("Buy trade Error code ", GetLastError());}
                 }
              }
            else
              {
               if(signal==ORDER_TYPE_SELL)
                 {
                  double entryPrice = Bid;
                  double stopLoss = entryPrice + stopLossPoints * PointValue;
                  double takeProfit = entryPrice - takeProfitPoints * PointValue;
                  Print("Sell Order Entry Price: ", entryPrice," Sell Order Stoploss: ",stopLoss," Sell Order Take profit: ",takeProfit," Symbol trade stops level: ", SYMBOL_TRADE_STOPS_LEVEL," checkStopLossTakeProfitLevels(): ", checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit));
                  double marginCheck = AccInfo.MarginCheck(_Symbol,ORDER_TYPE_SELL,lotSize,entryPrice);
                  double freeMarginCheck = AccInfo.FreeMargin();
                  //Print("marginCheck: ", marginCheck,"freeMarginCheck: ",freeMarginCheck);



                  //Check margin and stop levels
                  if(marginCheck < freeMarginCheck && checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit))
                    {
                     //Open sell trade
                     if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,lotSize,entryPrice,stopLoss,takeProfit))
                       {Print("Sell trade Error code ", GetLastError());}
                    }
                 }

              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//|OnTick                                                            |
//+------------------------------------------------------------------+
void OnTick()
  {
//---If there are no open orders, check for open conditions
   if(TotalOrdersCount() <= 0)
      CheckForOpen();
   /*
      if(trailingStopPoints > 0 && TotalOrdersCount() > 0)
         applyTrailingStop();

   */
//Print("Ontick Error.");



  }
//+------------------------------------------------------------------+
//| Check for active trading time                                    |
//+------------------------------------------------------------------+
bool isTradingTime()
  {
   MqlDateTime mqlDateTime;
   TimeToStruct(TimeCurrent(), mqlDateTime);
   int currentHour = mqlDateTime.hour;
   int currentMinute = mqlDateTime.min;

   int startTimeInMinutes = startHour * 60 + startMinute;
   int endTimeInMinutes = endHour * 60 + endMinute;
   int currentTimeInMinutes = currentHour * 60 + currentMinute;

   if(startTimeInMinutes <= currentTimeInMinutes && currentTimeInMinutes <= endTimeInMinutes)
     {
      return true;
     }

   return false;
  }
//+------------------------------------------------------------------+
//| Check volume                                                     |
//+------------------------------------------------------------------+
bool checkValidVolume(double volume)
  {
   double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   if(volume < minVolume || volume > maxVolume)
     {
      return false;
     }

   double volumeDifference = volume - minVolume;
   double stepCount = MathRound(volumeDifference / volumeStep);

   if(MathAbs(volumeDifference - stepCount * volumeStep) > 0.0001)
     {
      return false;
     }

   return true;
  }
//+------------------------------------------------------------------+
//|Check SL TP Levels                                                |
//+------------------------------------------------------------------+
bool checkStopLossTakeProfitLevels(double entryPrice, double stopLoss, double takeProfit)
  {
   double minStopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
   double freezeLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * _Point;

   if(MathAbs(entryPrice - stopLoss) < minStopLevel || MathAbs(entryPrice - takeProfit) < minStopLevel)
     {
      return false;
     }

   if(MathAbs(entryPrice - stopLoss) < freezeLevel || MathAbs(entryPrice - takeProfit) < freezeLevel)
     {
      return false;
     }

   return true;
  }
//+------------------------------------------------------------------+
//| Check for active trading day                                     |
//+------------------------------------------------------------------+
bool isTradingDay()
  {
   datetime currentTime = TimeCurrent();
   MqlDateTime mqlDateTime;
   TimeToStruct(currentTime, mqlDateTime);
   ENUM_DAY_OF_WEEK currentDayOfWeek = (ENUM_DAY_OF_WEEK)mqlDateTime.day_of_week;

   switch(currentDayOfWeek)
     {
      case MONDAY:
         return tradeMonday;
      case TUESDAY:
         return tradeTuesday;
      case WEDNESDAY:
         return tradeWednesday;
      case THURSDAY:
         return tradeThursday;
      case FRIDAY:
         return tradeFriday;
      default:
         return false;
     }
  }
//+------------------------------------------------------------------+
//|Check max daily drawdown                                          |
//+------------------------------------------------------------------+
bool checkMaxDailyDrawdown(void)
  {
   static datetime lastTradingDay = 0;
   static double initialBalance = 0;

   datetime currentDay = TimeCurrent() / 86400;
   if(currentDay > lastTradingDay)
     {
      lastTradingDay = currentDay;
      initialBalance = AccountInfoDouble(ACCOUNT_BALANCE);
     }

   double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
   double drawdown = initialBalance - currentBalance;
   double drawdownPercent = (drawdown / initialBalance) * 100;
//Print("Calculated draw down percent is :", drawdownPercent,"the max daily drawdown percent is: ",maxDailyDrawdownPercent);
   return drawdownPercent <= maxDailyDrawdownPercent;
  }
//+------------------------------------------------------------------+
//| Trailing stop                                                    |
//+------------------------------------------------------------------+
void applyTrailingStop(void)
  {
   int totalOrders = PositionsTotal();
   double trailingStopPointsapply = trailingStopPoints * PointValue;

   for(int i = 0; i < totalOrders; i++)
     {
      string symbol = PositionGetSymbol(i);
      if(symbol != _Symbol)
         continue; // Skip positions of other symbols

      if(PositionGetInteger(POSITION_MAGIC) != magicNumber)
         continue; // Skip positions with a different magic number

      ulong ticket = PositionGetTicket(i);
      double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
      double stopLoss = PositionGetDouble(POSITION_SL);

      double newStopLoss = 0;
      if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
        {
         newStopLoss = Bid - trailingStopPointsapply;
         if(newStopLoss > openPrice && (stopLoss < openPrice || newStopLoss > stopLoss) && newStopLoss != stopLoss)
           {
            if(!trade.PositionModify(ticket, newStopLoss, PositionGetDouble(POSITION_TP)))
              {
               PrintFormat("Error: Failed to modify position. Error code: %d", GetLastError());
              }
           }
        }
      else
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
           {
            newStopLoss = Ask + trailingStopPointsapply;
            if(newStopLoss < openPrice && (stopLoss > openPrice || newStopLoss < stopLoss) && newStopLoss != stopLoss)
              {
               if(!trade.PositionModify(ticket, newStopLoss, PositionGetDouble(POSITION_TP)))
                 {
                  PrintFormat("Error: Failed to modify position. Error code: %d", GetLastError());
                 }
              }
           }
     }
  }
//+------------------------------------------------------------------+
//|Total Orders count                                                |
//+------------------------------------------------------------------+
int TotalOrdersCount()
  {
   int result=0;
   int posTotal=PositionsTotal();
   for(int posIndex=posTotal-1; posIndex>=0; posIndex--)
     {
      ulong ticket=PositionGetTicket(posIndex);
      if(PositionSelectByTicket(ticket) && PositionGetInteger(POSITION_MAGIC)==magicNumber)
         result++;
     }
   return (result);
  }
//+------------------------------------------------------------------+
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.
 
Rafael Santos #:

Apologies for the delay in my response. I have diligently conducted further research and attempted various solutions to address the issue at hand, unfortunately without success.

In order to ensure compliance with all necessary criteria a trading robot must meet prior to being published in the Market,https://www.mql5.com/en/articles/2555, I have initiated a test template for m Expert Advisors (EAs).

so far, all  checks implemented appear to be functioning correctly, with the exception of the "invalid stop levels" error. I have provided the relevant code and a snippet of the output values pertaining to the stop levels below. Your assistance and expertise in resolving this matter would be greatly appreciated.


Buy trade output:



Sell trade output:



Are you sure you can use price like 32617.58 for US30 ?

What is the tick size for this symbol on your broker ?

 
Alain Verleyen #:

Are you sure you can use price like 32617.58 for US30 ?

What is the tick size for this symbol on your broker ?

  double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

    if (tickSize > 0) {
        PrintFormat("The tick size for the symbol %s is: %f", _Symbol, tickSize);
    } else {
        Print("Error: Failed to get the tick size.");
    }

output: 


 
Rafael Santos #:

output: 


Ok, I had not checked the code yet.

double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

You can't declare global price and use that in your request, you need to get the ACTUAL prices (Bid/Ask) at the moment you send your request.

Use SymbolInfotTick().

 
Alain Verleyen #:

Ok, I had not checked the code yet.

You can't declare global price and use that in your request, you need to get the ACTUAL prices (Bid/Ask) at the moment you send your request.

Use SymbolInfotTick().

I appreciate your attention to the matter. I have updated the code and executed a back test for the previous month. Under previous circumstances, the log viewer would display a few pages of invalid stop level errors; however, after implementing the actual current ask/bid using the SymbolInfoTick() function, there has been a noticeable improvement.

Despite this positive change, the issue has not been fully resolved. I would appreciate any insights or suggestions you may have to help eliminate the remaining "Invalid Stop levels" errors. Thank you in advance for your assistance and expertise.



code update:

// get the current Actual ask/bid price
            MqlTick currentTick;
            if(SymbolInfoTick(_Symbol, currentTick))
              {
               double bidPrice = currentTick.bid;
               double askPrice = currentTick.ask;

               PrintFormat("Bid price for %s: %f", _Symbol, bidPrice);
               PrintFormat("Ask price for %s: %f", _Symbol, askPrice);


               if(signal==ORDER_TYPE_BUY)
                 {
                  double entryPrice = askPrice;
                  double stopLoss = entryPrice - stopLossPoints * PointValue;
                  double takeProfit = entryPrice + takeProfitPoints * PointValue;
                  Print("Buy Order Entry Price: ", entryPrice," Buy Order Stoploss: ",stopLoss," Buy Order Take profit: ",takeProfit," Symbol trade stops level: ", SYMBOL_TRADE_STOPS_LEVEL," checkStopLossTakeProfitLevels(): ", checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit));
                  double marginCheck = AccInfo.MarginCheck(_Symbol,ORDER_TYPE_BUY,lotSize,entryPrice);
                  double freeMarginCheck = AccInfo.FreeMargin();
                  //Print("marginCheck: ", marginCheck,"freeMarginCheck: ",freeMarginCheck);

                  //Check margin and stop levels
                  if(marginCheck < freeMarginCheck && checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit))
                    {
                     //Open buy trade
                     if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,lotSize,entryPrice,stopLoss,takeProfit))
                       {Print("Buy trade Error code ", GetLastError());}
                    }
                 }
               else
                 {
                  if(signal==ORDER_TYPE_SELL)
                    {
                     double entryPrice = bidPrice;
                     double stopLoss = entryPrice + stopLossPoints * PointValue;
                     double takeProfit = entryPrice - takeProfitPoints * PointValue;
                     Print("Sell Order Entry Price: ", entryPrice," Sell Order Stoploss: ",stopLoss," Sell Order Take profit: ",takeProfit," Symbol trade stops level: ", SYMBOL_TRADE_STOPS_LEVEL," checkStopLossTakeProfitLevels(): ", checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit));
                     double marginCheck = AccInfo.MarginCheck(_Symbol,ORDER_TYPE_SELL,lotSize,entryPrice);
                     double freeMarginCheck = AccInfo.FreeMargin();
                     //Print("marginCheck: ", marginCheck,"freeMarginCheck: ",freeMarginCheck);



                     //Check margin and stop levels
                     if(marginCheck < freeMarginCheck && checkStopLossTakeProfitLevels(entryPrice,stopLoss,takeProfit))
                       {
                        //Open sell trade
                        if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,lotSize,entryPrice,stopLoss,takeProfit))
                          {Print("Sell trade Error code ", GetLastError());}
                       }
                    }

                 }
              }
 

You need to normalize your calculate price (SL/TP).

Forum on trading, automated trading systems and testing trading strategies

Need help to round order last digit to 0 or 5

Alain Verleyen, 2016.10.23 18:47

Normalize your price like that :

//+------------------------------------------------------------------+
//| Normalize price according to tick size                           |
//+------------------------------------------------------------------+
double normalizePrice(double price)
  {
   double tickSize=SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE);
   return(MathRound(price/tickSize)*tickSize);
  }

Reason: