EA is not entering trade when Ctrade buy/sell methods are called

 

Hi, Ive made an EA that uses custom indicators and CTrade class. The problem is that the EA doesnt take all entries decpite the entry conditions being met and the entire 'trade' code block being run.
Heres the code:


//+------------------------------------------------------------------+
//|                                              Zero-Lag Shandy.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"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include <Trade/Trade.mqh>
input int start = 10; //start hour
input int end= 20;//end hour

input int     ShandelierAtrPeriod      =  1; // Shandelier Atr period
input double  ShandelierAtrMultiplier1 = 2.0; // Shandelier Atr 1st multiplier
input double  ShandelierAtrMultiplier2 = 1; // Shandelier Atr 2nd multiplier
input int     ShandelierLookBackPeriod =  1; // Shandelier Look-back period
input double  ATR_PERCENTAGE = 0.3; //Minimum ATR Percentage   
input int     SMAPeriod =  50; //SMA Period

input ENUM_APPLIED_PRICE     SMASource =  PRICE_CLOSE; //SMA Source
input int PipRange = 10; //Cross range SMA\
input int swingPeriod = 24; //Swing Period

int SMAHandle;
int ShandelierHandle;
int ATRHandle;
double ShandelierUp[];
double ShandelierDwn[];
double SMA[];
double ATR[];

enum Signal
  {
      Signal_Buy,
      Signal_Sell,
      Signal_Over,
      Signal_Under
  };
  

Signal ShandelierSignal;
Signal PrevShandelierSignal;
Signal SMASignal;
bool atr_aprove = false;
ulong posTicket = 0;
double _tp, _sl;
CTrade market = CTrade();

int TradesEntered = 0;

int OnInit()
{
//---
    SMAHandle = iCustom(_Symbol, PERIOD_CURRENT, "Zero Lags SMA MT5", SMAPeriod, SMASource);
    ShandelierHandle = iCustom(_Symbol, PERIOD_CURRENT, "Chandelier exit", ShandelierAtrPeriod, ShandelierAtrMultiplier1, ShandelierAtrMultiplier2, ShandelierLookBackPeriod);
    ATRHandle = iATR(_Symbol, PERIOD_CURRENT, 3);
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   CopyBuffer(ShandelierHandle, 0, 1, 1, ShandelierUp);
   CopyBuffer(ShandelierHandle, 1, 1, 1, ShandelierDwn);
   CopyBuffer(SMAHandle, 0, 1, 1, SMA);
   CopyBuffer(ATRHandle, 0, 1, 1, ATR);
   
   
   
   double close = iClose(_Symbol, PERIOD_CURRENT, 1);
   double atr_percent = (ATR[0] / close) * 100;
   
   if (atr_percent > 0.03) 
   {
      atr_aprove = true;
   }
   else
     {
         atr_aprove = false;
     }
   
   if(PositionsTotal() == 0)
   {
      posTicket = 0;
   }
   
   
   if(close > SMA[0])
   {
      SMASignal = Signal_Over;
   }
   else if (close < SMA[0])
   {
      SMASignal = Signal_Under;
   }
   
   
   if(close > ShandelierUp[0])
   {
      ShandelierSignal = Signal_Buy;
   }
   else if (close < ShandelierDwn[0])
   {
      ShandelierSignal = Signal_Sell;
   }
   
   int current_hour = time_to_hour(TimeCurrent());
   int current_min = time_to_min(TimeCurrent());

   if (current_hour == 0) return;
   if (current_min == 0) return;
   if ((current_hour > start && current_hour < end) && current_min % 5 == 0)
   {
      if (ShandelierSignal != PrevShandelierSignal)
      {
         if(ShandelierSignal == Signal_Buy && posTicket == 0 && SMASignal == Signal_Over)
         {
         
            double low  = iLow(_Symbol, PERIOD_CURRENT, iLowest(_Symbol,PERIOD_CURRENT, MODE_LOW,swingPeriod,0)) ;
            double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            double stop_pips = ask - low;
            double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * _Point;
            double  stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
            
            double lots = CalculateLots(0.01, stop_pips);
            if (stop_pips < spread + stop_level)
            {
               _sl = ask - (spread + stop_level);
            }
            else
              {
                  _sl = ask - stop_pips;
              }
            _tp = ask + (stop_pips * 3);
            market.Buy(lots, _Symbol, 0, _sl, _tp, "buy");
            posTicket = market.ResultOrder();
            TradesEntered++;
            Print("buy");
         }
         else if(ShandelierSignal == Signal_Sell && posTicket == 0 && SMASignal == Signal_Under )
         {
            double high = iHigh(_Symbol, PERIOD_CURRENT, iHighest(_Symbol,PERIOD_CURRENT,MODE_HIGH,swingPeriod,0)) ;
            double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double stop_pips =  high - bid;
            double spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * _Point;
            double  stop_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
            double lots = CalculateLots(0.01, stop_pips);
            if (stop_pips < spread + stop_level)
            {
               _sl = bid + (spread + stop_level);
            }
            else
              {
               _sl = bid + stop_pips;
              }
               
            //double lots = Lot(stop_pips, 0.01);
            _tp = bid -  (stop_pips * 3);
            market.Sell(lots, _Symbol, 0, _sl,  _tp, "sell");
            posTicket = market.ResultOrder();
            TradesEntered++;
            Print("sell");
         }
      }
      
      
      
      
      
      
      PrevShandelierSignal = ShandelierSignal;
      Print(TradesEntered);

      }  

}
//+------------------------------------------------------------------+

double CalculateLots(double RiskPercentage, double SLDistance )
{
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   if(tickSize == 0 || tickValue == 0|| lotStep == 0)
     {
         Print(__FUNCTION__, " Error while getting account info");
     }
   
   double riskedMoney = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercentage / 100;
   double moneyLotStep = (SLDistance/tickSize) * lotStep;
   
   if(moneyLotStep == 0)
     {
         Print(__FUNCTION__, " Cannot calculate lots");
     }
   double lots = MathFloor(riskedMoney / moneyLotStep) * lotStep;
   
   return lots;

}

int time_to_min(datetime time)
{
   MqlDateTime _struct;
   TimeToStruct(time, _struct);
   return _struct.min;
}

int time_to_hour(datetime time)
{
   MqlDateTime _struct;
   TimeToStruct(time, _struct);
   return _struct.hour;
}


I added a counter('TradesEntered' variable in code) to keep track of how  much the entry conditions are true and compared that to the backtest results, Ive attached the pictures.

I'm hoping that i've overlooked something small and that the problem isn't with the CTrade class.

Thanks for taking a look.

Files:
 
TJFrags:

Hi, Ive made an EA that uses custom indicators and CTrade class. The problem is that the EA doesnt take all entries decpite the entry conditions being met and the entire 'trade' code block being run.
Heres the code:



I added a counter('TradesEntered' variable in code) to keep track of how  much the entry conditions are true and compared that to the backtest results, Ive attached the pictures.

I'm hoping that i've overlooked something small and that the problem isn't with the CTrade class.

Thanks for taking a look.

You could debug further by having separate counters for buy and sell (BuyTradesEntered etc) and then check the backtest result. You might also consider checking the return value of the buy and sell commands, see if it returns false at any point. Also, are you seeing any trade errors in the journal file?

 
ceejay1962 #:

You could debug further by having separate counters for buy and sell (BuyTradesEntered etc) and then check the backtest result. You might also consider checking the return value of the buy and sell commands, see if it returns false at any point. Also, are you seeing any trade errors in the journal file?

I did as you suggested. As you suspected the buy and sell methods return false. I tried using getLastError() method to see the error but all it returns is 0. There are no errors in the journal. If u need to see the updated code including ur suggestions let me know
Discover new MetaTrader 5 opportunities with MQL5 community and services
Discover new MetaTrader 5 opportunities with MQL5 community and services
  • 2024.12.26
  • 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
 
Print(market.ResultRetcodeDescription());
 
fxsaber #:
fxsaber #:
THanks for the comment. This returned "Invalid Volume". Testing with a lot size of 0.2 yeilded matching results. This must mean the CalculateLots funnction is the problem. I'm trying to figure that out now
 
The issue was that my CalcutaleLots function was returning 0.0 as the lot size.This was an easy enough fix. Thanks for the help guys