Errors in EA and not behaving as it is wanted

 

Hello MQL5ers

My EA is not acting as I wanted it to be. My intentions were as follows:

  1. The EA is supposed to be suitable for Indian Stock Markets where stocks are price based with min tick size is 0.05. Somehow back test results are not matching up as per the orders getting executed. For example as the default target is ₹5.00 and max trades per day is 5 Nos., the maximum profit should have been for 100 quntity = 100 x 5 x 5 *x 2 Days = ₹2,500.00, if all the trades are in profit. Whereas the backtest result is showing pretty much more than that and unrealistic.
  2. Quantity has been keptas integer as Indian Stock Quantity can only be on multiple of 1.
  3. It is buy/sell stop orders and if the order doesn't get executed, after X (here default is 5) the order will get cancelled.
  4. The max order count is supposed to be for completed orders but I guess it is also counting the cancelled orders. The max order counts should exclude the cancelled buy/sell stop orders.
  5. Trailing stop loss concept was if the price moves the trailing stop distnce from the open price, initially the stoploss price will move to the order open price and as the price moves by the step of trailingstop, the stoploss will also move the same same stop depending upon the bid or ask.
  6. A few times the order send error 130 is also apprearing.

I am unable to find out where I am going wrong and would appreciate if some kind soul can help me to get it right. I am pasting the whole code hereunder:

//+------------------------------------------------------------------+
//|                                                Indian Stocks.mq4 |
//|                                      Copyright 2024, Santanu Das |
//|                                        https://www.santanudas.in |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Santanu Das"
#property link      "https://www.santanudas.in"
#property version   "1.00"
#property strict
enum Tppl {
   Both,
   Long_Only,
   Short_Only,
};
extern Tppl    Pos_Type       = Both;        // Long/Short or Both
extern int     LotSize        = 100.0;       // Quantity in Integers
extern double  TakeProfit     = 5.0;         // Profit Points in INR
extern bool    enableTrail    = True;        // Enable Trailing Stop Loss
extern double  TrailingStop   = 2.0;         // Trailing Stop Loss in INR
extern int     Max_Trades     = 5;           // Daily Max Nos. of Trades
extern double  bufferPrice    = 2.0;         // Entry Price Buffer in INR
extern int     Cancel_After   = 5;           // Stop Order Cancel after X Bars
extern string  Start_Time     = "08:45";     // Trade Entry Session Start Time
extern string  End_Time       = "15:10";     // Trade Entry Session End Time
extern int     MagicNumber    = 25111972;    // Magic Number

int            buySellTicket, buyNormOrders, sellNormOrders;
int            sellStopOrders, buyStopOrders;
double         BuyProf=0;
double         SellProf=0;
double         StopLoss=0;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {
   ProfVal();
   if(BuyProf  >= TakeProfit) closeBuyPos();
   if(BuyProf  <= StopLoss * -1) closeBuyPos();
   if(SellProf <= StopLoss * -1) closeSellPos();
   if(SellProf >= TakeProfit) closeSellPos();

   if(!alocs2()) {
      CloseAll();
      return;
   }
   stopOrderCount();
   normalOrderCount();
   UpdateTrailingStop();

   if(Cancel_After > 0 && barCount()>= Cancel_After)
      CloseAll();
   //if (OrderType()> 1 && OrderOpenTime() < Time[Cancel_After]) OrderDelete(OrderTicket()) 
   
   double Bull=iCustom(Symbol(),Period(),"Santanu Ind",4,1);
   double Bear=iCustom(Symbol(),Period(),"Santanu Ind",5,1);

   if(Pos_Type != Long_Only)
   if(Bear>0.00001 && Bear<20000000 && sellNormOrders == 0 && sellStopOrders == 0)
   if(Max_Trades >0 && DailyC() <= Max_Trades)
   Sell_Stop();
   else
   if(Max_Trades == 0)
   Sell_Stop();
   
   if(Pos_Type!=Short_Only)
   if(Bull>0.000001 && Bull<200000000 && buyNormOrders==0 && buyStopOrders==0)
   if(Max_Trades >0 && DailyC()<= Max_Trades)
   Buy_Stop();
   else
   if(Max_Trades==0)
   Buy_Stop();

}
//+------------------------------------------------------------------+
//| Expert custom function                                             |
//+------------------------------------------------------------------+
// Proft Claculation
void ProfVal() {
   BuyProf=0;
   SellProf=0;
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS)== true && OrderSymbol()==Symbol()) {
         if(OrderType() == OP_BUY && OrderMagicNumber()==MagicNumber) {
            BuyProf += OrderProfit();
         }
         if(OrderType() == OP_SELL && OrderMagicNumber()==MagicNumber) {
            SellProf += OrderProfit();
         }
      }
   }
}

// Buy Position Close
void closeBuyPos() {
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS) && OrderSymbol()== Symbol()&& OrderMagicNumber() == MagicNumber) {
         if(OrderType()== OP_BUY) {
            bool res = OrderClose(OrderTicket(),OrderLots(),OrderOpenPrice(),5573,NULL);
         }
      }
   }
}

// Sell Position Close
void closeSellPos() {
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS) && OrderSymbol()== Symbol() && OrderMagicNumber() == MagicNumber) {
         if(OrderType()== OP_SELL) {
            bool res=OrderClose(OrderTicket(),OrderLots(),OrderOpenPrice(),5573,NULL);
         }
      }
   }
}
// Buy Stop Order
void Buy_Stop(){
   double buyLimitPrice = 0;
   buyLimitPrice        = High[1] + bufferPrice;
   StopLoss             = High[1] - Low[1];
   buySellTicket=OrderSend(NULL,OP_BUYSTOP,LotSize,buyLimitPrice,3,0,0,NULL,MagicNumber,0,clrGreen);
   buySellTicket=0;
}

// Sell Stop Order
void Sell_Stop() {
   double sellLimitPrice=0;
   sellLimitPrice       = Low[1] - bufferPrice;
   StopLoss             = High[1] - Low[1];
   buySellTicket=OrderSend(NULL,OP_SELLSTOP,LotSize,sellLimitPrice,3,0,0,NULL,MagicNumber,0,clrNONE);
   buySellTicket=0;
}

// Time Functions
bool alocs2(){
   int Mns = TIME_MINUTES;
   if(StrToTime(Start_Time)==StrToTime(End_Time)
      && StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES))==StrToTime(Start_Time))
      return true;
   
   if(StrToTime(Start_Time)<StrToTime(End_Time) 
      && StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES))>=StrToTime(Start_Time)
      && StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES)) <=StrToTime(End_Time))
      return true;
   
   if(StrToTime(Start_Time)>StrToTime(End_Time) 
      && ((StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES))>=StrToTime(End_Time)
      && StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES))<=23) 
      || ((StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES)))<=StrToTime(Start_Time)
      && StrToTime(TimeToStr(TimeCurrent(),TIME_MINUTES))>0)))
      return true;
   
   return false;
}

// Close All Positions
void CloseAll() {
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS) && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
         //bool res = OrderClose(OrderTicket(),OrderLots(),OrderOpenPrice(),5573,NULL);
         bool rest= OrderDelete(OrderTicket());
      }
   }
}
// Count Numbers of Stop Orders
void stopOrderCount() {
   buyStopOrders=0;
   sellStopOrders=0;
   for(int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
      if(OrderSelect(cnt,SELECT_BY_POS)==true 
      && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
         if((OrderType()==OP_BUYLIMIT) || (OrderType()==OP_BUYSTOP)) buyStopOrders++;
         if((OrderType()==OP_SELLLIMIT) || (OrderType()==OP_SELLSTOP)) sellStopOrders++;
      }
   }
}

// Count Numbers of Normal Orders
void normalOrderCount() {
   buyNormOrders=0;
   sellNormOrders=0;
   for(int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
      if(OrderSelect(cnt,SELECT_BY_POS)==true 
      && OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) {
         if((OrderType()==OP_BUY)) buyNormOrders++;
         if((OrderType()==OP_SELL)) sellNormOrders++;
      }
   }
}

// Trailing StopLoss Calculation
void UpdateTrailingStop() {
   if(TrailingStop == 0 || enableTrail == false) return;
   bool res;
   double new_stop_loss = 0.0;
   double close_Price = 0.0;
   RefreshRates();
        if(OrderType() == OP_BUY)
                close_Price     = Bid;
        if(OrderType() == OP_SELL)
                close_Price     = Ask;
        for(int i=0; i<OrdersTotal(); i++) {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == true 
      && OrderSymbol() == Symbol() && OrderMagicNumber()== MagicNumber) {
         if(OrderType() == OP_BUY) {
            if (close_Price - OrderOpenPrice() >= TrailingStop)
               new_stop_loss = close_Price - TrailingStop;
            if (OrderStopLoss() < new_stop_loss || (OrderStopLoss() == 0))
               res = OrderModify(OrderTicket(),OrderOpenPrice(),new_stop_loss,OrderTakeProfit(),0,clrBlue);
         }
         else if (OrderType() == OP_SELL) {
            if (OrderOpenPrice() - close_Price >= TrailingStop)
               new_stop_loss = close_Price + TrailingStop;
            if (OrderStopLoss() < new_stop_loss || (OrderStopLoss() == 0))
               res = OrderModify(OrderTicket(),OrderOpenPrice(),new_stop_loss,OrderTakeProfit(),0,clrBlue);
         }
      }
   }
}

// Counting Bars after Buy/Sell Signal
int barCount() {
   datetime pos = 0;
   int cbt = 0;
   for(int k=0; k<OrdersTotal(); k++) {
      if(OrderSelect(k, SELECT_BY_POS, MODE_TRADES) == true && OrderSymbol()==Symbol()) {
         pos=OrderOpenTime();
         cbt=Bars(Symbol(), 0, pos, TimeCurrent());
      }
   }
   return cbt;
}

// Count the numbers of Trades
int DailyC() {
   int CountSymbolPositions = 0;
   static datetime new_D1 = 0;
   datetime today = StrToTime(StringConcatenate(Year(), ".", Month(), ".", Day()));
   if ( new_D1 != today){
           new_D1 = today;
           Print("## New day detected. Reseting conters");
           CountSymbolPositions = 0;        //Reset counters
   }
   for(int cnt=OrdersTotal()-1; cnt>=0; cnt--) {
      if(OrderSelect(cnt, SELECT_BY_POS) == true
      && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
      if(TimeDay(TimeCurrent()) == TimeDay(OrderOpenTime()))
         CountSymbolPositions++;}
      
      for(int i=OrdersHistoryTotal()-1; i>=0; i--) {
         if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) 
         && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
         if(TimeDay(TimeCurrent())== TimeDay(OrderOpenTime()))
         CountSymbolPositions++;
      }
   return CountSymbolPositions;
}
 
Your topic has been moved to the section: MQL4 and MetaTrader 4
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 
Santanu Das: A few times the order send error 130 is also apprearing.
   buySellTicket=OrderSend(NULL,OP_BUYSTOP,LotSize,buyLimitPrice,3,0,0,NULL,MagicNumber,0,clrGreen);

Be careful with NULL.

  1. On MT4, you can use NULL in place of _Symbol only in those calls that the documentation specially says you can. iHigh does, iCustom does, MarketInfo does not, OrderSend does not.
  2. Don't use NULL (except for pointers where you explicitly check for it.) Use _Symbol and _Period, that is minimalist as possible and more efficient.
  3. Zero is the same as PERIOD_CURRENT which means _Period. Don't hard code numbers.
  4. MT4: No need for a function call with iHigh(NULL,0,s) just use the predefined arrays, i.e. High[].
    MT5: create them.
  5. Cloud Protector Bug? - MQL4 programming forum (2020)