Validation state: Validation completed with errors

 

I'm having issues validating an update to an EA, and I can't figure out what I'm doing wrong. The problem is with the trailing stop, and even though I validate the SYMBOL_TRADE_FREEZE_LEVEL and SYMBOL_TRADE_STOPS_LEVEL, I still get the error "[Modification failed due to order or position being close to market]." I hope you can help me. Regards.

void TrailingStop(ulong ticket, int TrailingStart, int TrailingStep)
  {
//---
   if(!Posicion.SelectByTicket(ticket))
      return;
//---
   double precioEntrada = Posicion.PriceOpen();
//--- Si la posición es BUY
   if(Posicion.PositionType() == POSITION_TYPE_BUY)
     {
      // Precio Bid menos precio de entrada es mayor a trailing start?
      double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
      if(bid - precioEntrada > TrailingStart * Point())
        {
         // La distancia del bid al SL es mayor que el step?
         if(bid - Posicion.StopLoss() > TrailingStep * Point())
           {
            double nuevoSL = bid - TrailingStep * Point();
            nuevoSL = NormalizeDouble(nuevoSL, Digits()) ;
            //---
            if(nuevoSL <= Posicion.StopLoss()) // El nuevo SL no debe estar más abajo
               return;
            //---
            if(bid - Posicion.StopLoss() <= SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL) * Point())
               return;
            //---
            if(bid - nuevoSL <= SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) * Point())
               return;
            //---
            Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit());
           }
        }
     }
//--- Si la posición es SELL
   else
     {
      double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      // Precio de entrada menos precio ask es mayor a trailing start?
      if(precioEntrada - ask > TrailingStart * Point())
        {
         // Si StopLoss es cero, o la distancia del SL al ask es mayor que el step
         if(Posicion.StopLoss() == 0 || Posicion.StopLoss() - ask > TrailingStep * Point())
           {
            double nuevoSL = ask + TrailingStep * Point();
            nuevoSL = NormalizeDouble(nuevoSL, Digits());
            //---
            if(Posicion.StopLoss() != 0 && nuevoSL >= Posicion.StopLoss()) // El nuevo SL no debe estar más arriba
               return;
            //---
            if(Posicion.StopLoss() - ask <= SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL) * Point())
               return;
            //---
            if(nuevoSL - ask <= SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) * Point())
               return;
            //---
            Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit());
           }
        }
     }
  }
 
Try this.
Documentation on MQL5: Trade Functions / OrderCheck
Documentation on MQL5: Trade Functions / OrderCheck
  • www.mql5.com
OrderCheck - Trade Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
fxsaber #:
Try this.
Thanks for your response. I apply that check before sending the order to open a position. But the issue arises when modifying the stop loss, not due to the account balance.
 
Antonio Simon Del Vecchio #:
Thanks for your response. I apply that check before sending the order to open a position. But the issue arises when modifying the stop loss, not due to the account balance.

You can do this check before modifying a position.

 
fxsaber #:

You can do this check before modifying a position.

I have added the function OrderCheck(...) and it still generates the same error [Modification failed due to order or position being close to market]. I can't seem to figure out what I'm doing wrong.
void TrailingStop(ulong ticket, int TrailingStart, int TrailingStep)
  {
   if(!Posicion.SelectByTicket(ticket))
      return;
//---
   long stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
   double priceLevel = stopLevel * Point();
//---
   long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
   double priceFreezeLevel = freezeLevel * Point();
//---
   double precioEntrada = Posicion.PriceOpen();
//--- Si la posición es BUY
   if(Posicion.PositionType() == POSITION_TYPE_BUY)
     {
      double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
      if(bid - precioEntrada > TrailingStart * Point())
        {
         if(bid - Posicion.StopLoss() > TrailingStep * Point())
           {
            double nuevoSL = bid - TrailingStep * Point();
            nuevoSL = NormalizeDouble(nuevoSL, Digits());
            //---
            if(nuevoSL <= Posicion.StopLoss())
               return;
            //---
            if(bid - Posicion.StopLoss() <= priceFreezeLevel)
               return;
            //---
            if(bid - nuevoSL <= priceLevel)
               return;
            //---
            MqlTradeRequest request;
            MqlTradeCheckResult checkResult;
            ZeroMemory(request);
            ZeroMemory(checkResult);
            request.action = TRADE_ACTION_SLTP;
            request.position = Posicion.Ticket();
            request.sl = nuevoSL;
            request.tp = Posicion.TakeProfit();
            //---
            if(OrderCheck(request, checkResult))
              {
               Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit());
              }
           }
        }
     }
//--- Si la posición es SELL
   else
     {
      double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      if(precioEntrada - ask > TrailingStart * Point())
        {
         if(Posicion.StopLoss() == 0 || Posicion.StopLoss() - ask > TrailingStep * Point())
           {
            double nuevoSL = ask + TrailingStep * Point();
            nuevoSL = NormalizeDouble(nuevoSL, Digits());
            //---
            if(Posicion.StopLoss() != 0 && nuevoSL >= Posicion.StopLoss())
               return;
            //---
            if(Posicion.StopLoss() - ask <= priceFreezeLevel)
               return;
            //---
            if(nuevoSL - ask <= priceLevel)
               return;
            //---
            MqlTradeRequest request;
            MqlTradeCheckResult checkResult;
            ZeroMemory(request);
            ZeroMemory(checkResult);
            request.action = TRADE_ACTION_SLTP;
            request.position = Posicion.Ticket();
            request.sl = nuevoSL;
            request.tp = Posicion.TakeProfit();
            //---
            if(OrderCheck(request, checkResult))
              {
               Trade.PositionModify(Posicion.Ticket(), nuevoSL, Posicion.TakeProfit());
              }
           }
        }
     }
  }
 
Antonio Simon Del Vecchio #:
I have added the function OrderCheck(...) and it still generates the same error [Modification failed due to order or position being close to market]. I can't seem to figure out what I'm doing wrong.

No not like this. Paste this code at the beginning of the EA. After this, erroneous orders will not be issued.

#include <Trade\Trade.mqh>

class CTrade2 : public CTrade
{
public:
  virtual bool OrderSend( const MqlTradeRequest &request, MqlTradeResult &result )
  {
    return(this.OrderCheck(request, this.m_check_result) && CTrade::OrderSend(request, result));
  }  
};

#define CTrade CTrade2
 
fxsaber #:

No not like this. Paste this code at the beginning of the EA. After this, erroneous orders will not be issued.

Thanks, I've implemented the CTrade2 class at the beginning of the code, but it still didn't work. I'm starting to believe that the issue lies in the validation system.
 

Forum on trading, automated trading systems and testing trading strategies

Tick size vs Point(), can be a little tricky in Multicurrency EA

Fernando Carreiro, 2022.03.09 12:11

Tick Size and Point Size can be very different especially on stocks and other symbols besides forex.

Always use Tick Size to adjust and align your prices, not the point size. In essence, make sure that your price quotes, are properly aligned to the Tick size (see following examples).

...
double tickSize = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE );
...
double normalised_price = round( price / tick_size ) * tick_size;
...
// Or use a function
double Round2Ticksize( double price )
{
   double tick_size = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE );
   return( round( price / tick_size ) * tick_size );
};
 
Fernando Carreiro #:

Thank you, Fernando. I had checked 2 of the three topics you shared. I hadn't seen the one about Tick Size Vs Point(). I implemented that change and also rounding to avoid using Digits(), but despite that, the validation error still occurs. I'm sharing the code using tickSize instead of Point() and keeping OrderCheck(...) since I see it makes sense to use it with TRADE_ACTION_SLTP where it is. I also changed the names of some variables and the comments to English for better understanding.

If anyone sees where my mistake is, I would appreciate it.


void TrailingStop(ulong ticket, int TrailingStart, int TrailingStep)
  {
// Retrieve the minimum price change for the symbol
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
// Check if the position with the given ticket exists, return if not
   if(!Position.SelectByTicket(ticket))
      return;
// Calculate the minimum stop level and its equivalent in price
   long stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
   double priceLevel = stopLevel * tickSize;
// Calculate the freezing level and its equivalent in price
   long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
   double priceFreezeLevel = freezeLevel * tickSize;
// Get the entry price of the position
   double entryPrice = Position.PriceOpen();
// If the position is a BUY
   if(Position.PositionType() == POSITION_TYPE_BUY)
     {
      double bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
      // Check if the bid price has moved enough to start trailing
      if(bid - entryPrice > TrailingStart * tickSize)
        {
         // Check if the bid price has moved a step from the current SL
         if(bid - Position.StopLoss() > TrailingStep * tickSize)
           {
            // Calculate the new stop loss
            double newSL = bid - TrailingStep * tickSize;
            newSL = round(newSL / tickSize) * tickSize;
            // Verify the new SL is not moving backwards
            if(newSL <= round(Position.StopLoss() / tickSize) * tickSize)
               return;
            // Verify if the SL change is not within the freeze level
            if(bid - Position.StopLoss() <= priceFreezeLevel)
               return;
            // Verify if the SL change is not within the minimum stop level
            if(bid - newSL <= priceLevel)
               return;
            // Prepare the trade request and check result
            MqlTradeRequest request;
            MqlTradeCheckResult checkResult;
            ZeroMemory(request);
            ZeroMemory(checkResult);
            request.action = TRADE_ACTION_SLTP;
            request.position = Position.Ticket();
            request.sl = newSL;
            request.tp = Position.TakeProfit();
            // Check and execute the order
            if(OrderCheck(request, checkResult))
               // Modify the position with the new SL
               Trade.PositionModify(Position.Ticket(), newSL, Position.TakeProfit());
           }
        }
     }
// If the position is a SELL
   else
     {
      double ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
      // Check if the ask price has moved enough to start trailing
      if(entryPrice - ask > TrailingStart * tickSize)
        {
         // Check if the ask price has moved a step from the current SL
         if(Position.StopLoss() == 0 || Position.StopLoss() - ask > TrailingStep * tickSize)
           {
            // Calculate the new stop loss
            double newSL = ask + TrailingStep * tickSize;
            newSL = round(newSL / tickSize) * tickSize;
            // Verify the new SL is not moving backwards
            if(Position.StopLoss() != 0 && newSL >= round(Position.StopLoss() / tickSize) * tickSize)
               return;
            // Verify if the SL change is not within the freeze level
            if(Position.StopLoss() != 0 && Position.StopLoss() - ask <= priceFreezeLevel)
               return;
            // Verify if the SL change is not within the minimum stop level
            if(newSL - ask <= priceLevel)
               return;
            // Prepare the trade request and check result
            MqlTradeRequest request;
            MqlTradeCheckResult checkResult;
            ZeroMemory(request);
            ZeroMemory(checkResult);
            request.action = TRADE_ACTION_SLTP;
            request.position = Position.Ticket();
            request.sl = newSL;
            request.tp = Position.TakeProfit();
            // Check and execute the order
            if(OrderCheck(request, checkResult))
               // Modify the position with the new SL
               Trade.PositionModify(Position.Ticket(), newSL, Position.TakeProfit());
           }
        }
     }
  }
 
Antonio Simon Del Vecchio #:
Thanks, I've implemented the CTrade2 class at the beginning of the code, but it still didn't work. I'm starting to believe that the issue lies in the validation system.

If you put a breakpoint inside this function, does it stop?

Forum on trading, automated trading systems and testing trading strategies

Validation state: Validation completed with errors

fxsaber, 2023.11.23 21:39

#include <Trade\Trade.mqh>

class CTrade2 : public CTrade
{
public:
  virtual bool OrderSend( const MqlTradeRequest &request, MqlTradeResult &result )
  {
    DebugBreak();

    return(this.OrderCheck(request, this.m_check_result) && CTrade::OrderSend(request, result));
  }  
};

#define CTrade CTrade2
 
fxsaber #:

If you put a breakpoint inside this function, does it stop?

Yes, in debugging mode, the simulator stops right at the beginning of the process.

Reason: