No Trading Operation EA - Validation issue

 

Hi All,

I am trying to get pass the No Trading Operation - Validation Issue. After reading up on the different threads in this forum. I am attempting to create a skeleton to verify that I am on the right track. 

But... I am still having the same No Trading operation error. Below are the code for it. If some kind soul can point me in the right direction.

21 March 2021 Update

Did some further digging. I have added the following

1. Volume Check

2. New Order Check

3. Money Check

4. Position Check

The code attach will make 1 trade per new bar. But seems like its still facing the same issue.


//+------------------------------------------------------------------+
//|                                            TestingValidation.mq5 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021."
#property link      "https://www.mql5.com"
#property version   "1.7"

#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
CPositionInfo m_position;
CTrade m_trade;
datetime lastBar;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
lastBar = iTime(Symbol(),PERIOD_CURRENT,1);
//---
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && ! MQLInfoInteger(MQL_TESTER))
{
  return (false);
}
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double lot = NormalizeDouble(0.01, _Digits);
   string err;
   MqlTick last_tick;
   SymbolInfoTick(Symbol(), last_tick);
   
   if (!CheckMoneyForTrade(Symbol(), lot,ORDER_TYPE_BUY)){
   return;
   } 
   if (!CheckVolumeValue(lot, err) ){
   return;
   }
   
   if(lastBar < iTime(Symbol(),PERIOD_CURRENT,0)){
      double tp = NormalizeDouble(last_tick.bid + 1000 * _Point , _Digits);
      double sl = NormalizeDouble(last_tick.bid - (1000) * _Point, _Digits);
      double maxVol = NewOrderAllowedVolume(Symbol());
     if (lot > maxVol){
      lot = maxVol;
     }
     if (!CheckStopLoss_Takeprofit(ORDER_TYPE_BUY, sl, tp))
      Print("The StopLoss or TakeProfit level is incorrect!");
      
     m_trade.Buy(lot,Symbol(),SYMBOL_ASK, sl, tp, "");
     lastBar = iTime(Symbol(),PERIOD_CURRENT,0);
   }
     
   }

//+------------------------------------------------------------------+
  
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(symb,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   //--- call of the checking function
   if(!OrderCalcMargin(type,symb,lots,price,margin))
     {
      //--- something went wrong, report and return false
      Print("Error in ",__FUNCTION__," code=",GetLastError());
      return(false);
     }
   //--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
      return(false);
     }
//--- checking successful
   return(true);
  }

bool CheckVolumeValue(double volume,string &description)
  {
//--- minimal allowed volume for trade operations
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- maximal allowed volume of trade operations
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get minimal step of volume changing
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                               volume_step,ratio*volume_step);
      return(false);
     }
   description="Correct volume value";
   return(true);
  }
  
bool IsNewOrderAllowed()
  {
//--- get the number of pending orders allowed on the account
   int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);

//--- if there is no limitation, return true; you can send an order
   if(max_allowed_orders==0) return(true);

//--- if we passed to this line, then there is a limitation; find out how many orders are already placed
   int orders=OrdersTotal();

//--- return the result of comparing
   return(orders<max_allowed_orders);
  }
  
  
  //+------------------------------------------------------------------+
//| Return the maximum allowed volume for an order on the symbol     |
//+------------------------------------------------------------------+
double NewOrderAllowedVolume(string symbol)
  {
   double allowed_volume=0;
//--- get the limitation on the maximal volume of an order
   double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
//--- get the limitation on the volume by a symbol
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
   if(max_volume==0) 
      max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
//--- get the volume of the open position by a symbol
   double opened_volume=PositionVolume();
   if(opened_volume>=0)
     {
     Print("MaxVolume : " + max_volume + " opened_Volume = " + opened_volume);
      //--- if we have exhausted the volume
      if(max_volume-opened_volume<=0)
         return(0);

      //--- volume of the open position doesn't exceed max_volume
      double orders_volume_on_symbol=PendingsVolume(symbol);
      allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
      if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
      Print("Allowed Volume " + allowed_volume);
     }
   return(allowed_volume);
  }
  
  //+------------------------------------------------------------------+
//| Return the size of position on the specified symbol              |
//+------------------------------------------------------------------+
double PositionVolume()
  {
  ResetLastError();
//--- try to select position by a symbol
   bool selected=PositionSelect(Symbol());
//--- there is a position
   if(selected)
      //--- return volume of the position
      return(PositionGetDouble(POSITION_VOLUME));
   else
     {
      //--- report a failure to select position
      Print(__FUNCTION__," Failed to perform PositionSelect() for symbol ",Symbol()
," Error ",GetLastError());
      return(0);
     }
  }
  
  //+------------------------------------------------------------------+
//|  returns the volume of current pending order by a symbol         |
//+------------------------------------------------------------------+
double   PendingsVolume(string symbol)
  {
   double volume_on_symbol=0;
   ulong ticket;
//---  get the number of all currently placed orders by all symbols
   int all_orders=OrdersTotal();

//--- get over all orders in the loop
   for(int i=0;i<all_orders;i++)
     {
      //--- get the ticket of an order by its position in the list
      if(ticket=OrderGetTicket(i))
        {
         //--- if our symbol is specified in the order, add the volume of this order
         if(symbol==OrderGetString(ORDER_SYMBOL))
            volume_on_symbol+=OrderGetDouble(ORDER_VOLUME_INITIAL);
        }
     }
//--- return the total volume of currently placed pending orders for a specified symbol
   return(volume_on_symbol);
  }
  
  
  bool CheckStopLoss_Takeprofit(ENUM_ORDER_TYPE type,double SL,double TP)
  {
   MqlTick mqltick;
   SymbolInfoTick(Symbol(),mqltick);
//--- get the SYMBOL_TRADE_STOPS_LEVEL level
   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);
     }
//---
   bool SL_check=false,TP_check=false;
//--- check only two order types
   switch(type)
     {
      //--- Buy operation
      case  ORDER_TYPE_BUY:
        {
         //--- check the StopLoss
         SL_check=(mqltick.bid-SL>stops_level*_Point);
         if(!SL_check)
            PrintFormat("For order %s StopLoss=%.5f must be less than %.5f"+
                        " (Bid=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),SL,mqltick.bid-stops_level*_Point,mqltick.bid,stops_level);
         //--- check the TakeProfit
         TP_check=(TP-mqltick.bid>stops_level*_Point);
         if(!TP_check)
            PrintFormat("For order %s TakeProfit=%.5f must be greater than %.5f"+
                        " (Bid=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),TP,mqltick.bid+stops_level*_Point,mqltick.bid,stops_level);
         //--- return the result of checking
         return(SL_check&&TP_check);
        }
      //--- Sell operation
      case  ORDER_TYPE_SELL:
        {
         //--- check the StopLoss
         SL_check=(SL-mqltick.ask>stops_level*_Point);
         if(!SL_check)
            PrintFormat("For order %s StopLoss=%.5f must be greater than %.5f "+
                        " (Ask=%.5f + SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),SL,mqltick.ask +stops_level*_Point,mqltick.ask,stops_level);
         //--- check the TakeProfit
         TP_check=(mqltick.ask-TP>stops_level*_Point);
         if(!TP_check)
            PrintFormat("For order %s TakeProfit=%.5f must be less than %.5f "+
                        " (Ask=%.5f - SYMBOL_TRADE_STOPS_LEVEL=%d points)",
                        EnumToString(type),TP,mqltick.ask -stops_level*_Point,mqltick.ask,stops_level);
         //--- return the result of checking
         return(TP_check&&SL_check);
        }
      break;
     }
//--- a slightly different function is required for pending orders
   return false;
  } 
Discover new MetaTrader 5 opportunities with MQL5 community and services
Discover new MetaTrader 5 opportunities with MQL5 community and services
  • 2021.03.20
  • www.mql5.com
MQL5: language of trade strategies built-in the MetaTrader 5 Trading Platform, allows writing your own trading robots, technical indicators, scripts and libraries of functions
 

Forum on trading, automated trading systems and testing trading strategies

When you post code please use the CODE button (Alt-S)!

Use the CODE button


 
LanceGG:

Hi All,

I am trying to get pass the No Trading Operation - Validation Issue. After reading up on the different threads in this forum. I am attempting to create a skeleton to verify that I am on the right track. 

But... I am still having the same No Trading operation error. Below are the code for it. If some kind soul can point me in the right direction.

After reading the various topics concerning this issue, why have you started yet another new topic instead of posting in one of them?

 
Keith Watford:

After reading the various topics concerning this issue, why have you started yet another new topic instead of posting in one of them?

Hi Keith,

I am not trying to resolve the individual issue but more like to understand what is part of the "No Trading Operation" error, as its pretty cryptic.

Therefore what I am trying to do here, is to have a skeleton that pass the validation, hopefully this helps the community. That's why I am posting it as a separate topic, but if you think its no worth the 2 cents, I am happy for you to close this off.

Let me know if that's against the TOS.

Cheers,

Lance

 
Sergey Golubev:


Thanks. Will modified it