EA MT4 with CCI does not correctly buy and sell

 

Why does my EA in MT4 sometimes does not

  • close sell and buy correctly at CCI with value lower then -100
  • close buy and sell correctly at CCI with value higher then 100

?

  • The CCI shown in the picture is just the standard CCI in MT4 that I saved as a template to use in a backtest.
  • The CCI used in the EA is created with iCCI().

I used "Open prices only" to backtest.

In attachment, a picture of the backtest.

//+------------------------------------------------------------------+
//|                                                        myCCI.mq4 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict

int magic=1000;
int slippage=10;
double lots=0.1;

int n;
int buyCount;
int sellCount;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
// String for the signal
   string signal ="";

// Define the iCCI
   double iCCIValue=iCCI(Symbol(),0,14,PRICE_TYPICAL,0);

// If it is below -100
   if(iCCIValue<-100)
     {
      CloseOpenOrders(OP_SELL);
      if(CountOrders(OP_BUY)==0)
        {
         OpenOrder(OP_BUY);
         signal="buy";
        }
     }

// else if it is above 100
   if(iCCIValue>100)
     {
      CloseOpenOrders(OP_BUY);
      if(CountOrders(OP_SELL)==0)
        {
         OpenOrder(OP_SELL);
         signal="sell";
        }
     }

// Chart output
   Comment("Signal: ",signal,"\n","iCCI Value: ",iCCIValue);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountOrders(int tradeOperation)
  {
   int countOrders=0;
   for(int cnt=0; cnt<OrdersTotal(); cnt++)
     {
      if(OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType()==tradeOperation && OrderSymbol()==Symbol() && OrderMagicNumber()== magic)
            countOrders++;
        }
      else
         Print("Failed to select the order - ",GetLastError());
     }
   return(countOrders);
  }

// https://www.earnforex.com/guides/close-orders-mql4-orderclose/
void CloseOpenOrders(int tradeOperation)
  {
// Normalization of the slippage.

// We scan all the orders backwards.
// This is required as if we start from the first order, we will have problems with the counters and the loop.
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      // We select the order of index i, selecting by position and from the pool of market/pending trades.
      // If the selection is successful we try to close the order.
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
         if(OrderType()==tradeOperation && OrderSymbol()==Symbol() && OrderMagicNumber()== magic)
           {
            // We define the close price, which depends on the type of order.
            // We retrieve the price for the instrument of the order using MarketInfo(OrderSymbol(), MODE_BID) or MODE_ASK.
            // And we normalize the price found.
            double closePrice=0;
            RefreshRates();
            if(OrderType()==OP_BUY)
               closePrice=NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),Digits);
            if(OrderType()==OP_SELL)
               closePrice=NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),Digits);

            // If the order fails to be closed, we print the error.
            bool res;
            res = OrderClose(OrderTicket(),OrderLots(),closePrice,slippage,CLR_NONE);
            if(res == false)
               Print("Failed to close the order - ",GetLastError());
            else
               Print("Succes to close the order - ",GetLastError());
           }
         // If the OrderSelect() fails, we return the cause.
         }
      else
         Print("Failed to select the order - ",GetLastError());
     }
// We can use a delay if the execution is too fast.
// Sleep() will wait X milliseconds before proceeding with the code.
// Sleep(300);
  }
  
void OpenOrder(int tradeOperation)
  {
   int ticket=0;
   if(tradeOperation == OP_BUY)
      ticket = OrderSend(Symbol(), tradeOperation, lots, Ask, slippage, 0, 0, "OrderSend "+Symbol()+"_"+As_string(PERIOD_CURRENT)+"_Buy", magic);
   else if(tradeOperation == OP_SELL)
      ticket = OrderSend(Symbol(), tradeOperation, lots, Bid, slippage, 0, 0, "OrderSend "+Symbol()+"_"+As_string(PERIOD_CURRENT)+"_Sell", magic);

   if(ticket < 0)
      Print("Failed to send the order - ",GetLastError());
   else
      Print("Succes to send the order - Your ticket # is: " + string(ticket));
  }

// As_string(PERIOD_CURRENT)       Get current timeframe as e.g. "H1"
// https://www.mql5.com/en/forum/143516
string As_string(ENUM_TIMEFRAMES period)
  {
   if(period == PERIOD_CURRENT)
      period = (ENUM_TIMEFRAMES) _Period;
   string period_xxx = EnumToString(period);                // PERIOD_XXX
   return StringSubstr(period_xxx, 7);                      // XXX
  }
Files:
Backtest.PNG  324 kb
 

Hi and good morning,

i will try to explain it to you: the value of CCI is calculated every tick (maybe a hundred times) in a period and
at the time your order was opend or closed the CCI was surly above 100 (you can use a Print() statement to
check this) But there are ticks after the open order that modify the CCI that you see in the indicator picture.

I hope, this helps you.

Best regards

 
Werner Klehr:

Hi and good morning,

i will try to explain it to you: the value of CCI is calculated every tick (maybe a hundred times) in a period and
at the time your order was opend or closed the CCI was surly above 100 (you can use a Print() statement to
check this) But there are ticks after the open order that modify the CCI that you see in the indicator picture.

I hope, this helps you.

Best regards

Hi back too you. Thx for the reply!

I tought that was only for live trading or backtesting on every tick. So it can also change the cci when backtesting on "Open prices only"?

Reason: