I can't figure out why the EA using iCustom doesn't work in the strategy tester

 

I am testing out iCustom with my own indicator which is a simple MA with arrow signals (long and short signals based on how the market price moves over the MA).  This indicator is not to be used as an EA in live scenario as the indicator has no risk management features and it is not making exit signals. So this is purely for educational purposes. I don't know what's wrong, I followed Renés cool tutorial on making EA-from-indicator using iCustom. The EA should simply open one position at the long signal (up arrow), and open another position at the short signal (down arrow).


Here is my indicator called "MAwithArrows" which implements two arrow buffers at buffer position 1 and 2:

//+------------------------------------------------------------------+
//|                                         MAwithArrows.mq5               |
//|                             https://www.mql5.com/en/users/phade/|
//+------------------------------------------------------------------+

#property copyright "Copyright 2023, https://www.mql5.com/en/users/phade/"
#property link      "https://www.mql5.com/en/users/phade/"
#property version   "1.01"

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3


#property indicator_label1  "Buy"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrBlack
#property indicator_width1  3

#property indicator_label2  "Sell"
#property indicator_type2   DRAW_ARROW
#property indicator_color2 clrBlack
#property indicator_width2  3

#property indicator_type3   DRAW_LINE
#property indicator_color3   clrGray // change to clrNONE to hide the line
#property indicator_style3   STYLE_DOT
#property indicator_label3   "Line"
#property indicator_width3   1


double indvalue[];
double slowma[];
int handle;
int max_bars;


input int slowPeriod = 44; // Moving Average Length
input int pointNum = 100; // Amount of points on MA crossover that should enable a signal

double value_buf_a[];
double value_buf_b[];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // ChartSetInteger(0, CHART_FOREGROUND, false);

    SetIndexBuffer(0, value_buf_a);
    SetIndexBuffer(1, value_buf_b);
    SetIndexBuffer(2, indvalue); 
    
    PlotIndexSetInteger(0, PLOT_ARROW, 233);   
    PlotIndexSetInteger(1, PLOT_ARROW, 234);
    
    handle = iMA(_Symbol, PERIOD_CURRENT, slowPeriod, 0, MODE_SMA, PRICE_CLOSE);

    if (handle == INVALID_HANDLE)
    {
        Print("Get MA Handle failed!");
        return INIT_FAILED;
    }
    
    ArrayInitialize(value_buf_a, 0.0);    // Set long signal to 0
    ArrayInitialize(value_buf_b, 0.0);  // Set short signal to 0


    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]){
                
    // Calculate the number of bars to copy
    int to_copy = rates_total - prev_calculated;
       
    
    if (Bars(_Symbol, _Period) < rates_total)
      return (-1);
        
  //  int limit = MathMin(rates_total - prev_calculated, rates_total-1);
    
 
    // Copy data from indicator buffers
    CopyBuffer(handle, 0, 0, to_copy, slowma);
    

    // Calculate the indicator values
    for (int i = prev_calculated; i < rates_total; i++){
    
         indvalue[i] = slowma[i];

         // Check for MA crossovers
         if (i > 0 && (i - 2) >= 0 && close[i] > (indvalue[i] + pointNum * _Point) && close[i - 2] < indvalue[i]){
         
            value_buf_a[i] = low[i];                 
         } 
         else{
            value_buf_a[i] = 0.0;
         }
         
         
         if (i > 0 && (i - 2) >= 0 && close[i] < (indvalue[i] - pointNum * _Point) && close[i - 2] > indvalue[i]){      
            value_buf_b[i] = high[i];     
         }
         else{
            value_buf_b[i] = 0.0; 
         }  
    }
    
    ArraySetAsSeries(indvalue, true);
    ArraySetAsSeries(value_buf_a, true);
    ArraySetAsSeries(value_buf_b, true);
     
    return rates_total;
}



//+------------------------------------------------------------------+

void OnDeinit(const int reason){

    ArrayFree(slowma);
    IndicatorRelease(handle);
}

Now here is the EA:

//+------------------------------------------------------------------+
//|                                                 BoomAndCrash.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"


#include <Trade/Trade.mqh>
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int handle;

CTrade trade;
input int slowPeriod = 44; // Moving Average Length
input int pointNum = 100; // Amount of points on MA crossover that should enable a signal


int OnInit()
  {
//---
  // handle = iCustom(NULL, 0, "Examples\\MAwithArrows", slowPeriod, pointNum);
   handle = iCustom(NULL, 0, "Examples\\MAwithArrows");     
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
      double arrSellSignals[], arrBuySignals[];
       
      CopyBuffer(handle, 0, 0, 1, arrBuySignals);
      CopyBuffer(handle, 1, 0, 1, arrSellSignals);
   
      if(arrSellSignals[0] > 0){
         for(int i=PositionsTotal()-1; i>=0; i--){
            ulong posTicket = PositionGetTicket(i);
            
            if(posTicket > 0){
               if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
                  trade.PositionClose(posTicket); //close this buy position
               }
            }        
         }
         
            if(PositionsTotal() == 0){   
               trade.Sell(0.03); //make one position with lot size 0.03
            }          
      }
         
         
       if(arrBuySignals[0] > 0){
         for(int i=PositionsTotal()-1; i>=0; i--){
            ulong posTicket = PositionGetTicket(i);
            
            if(posTicket>0){
               if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){
                  trade.PositionClose(posTicket); //close this sell position
               }
            }        
         }    
     
            if(PositionsTotal() == 0){   
               trade.Buy(0.03); //make one position with lot size 0.03
            }
       }
  }
//+------------------------------------------------------------------+


I have the buffer numbers set correctly in the EA, I'm so confused why the strategy tester just doesn't do anything when I hit the "Start" button. It loads for a minute and then doesn't bring up the chart or any data. What could be wrong ?

phade
phade
  • 2023.08.30
  • www.mql5.com
Trader's profile
 

the same EA does run in the strategy tester with another indicator using arrow buffers, so I don't understand at this point.

 
I'm thinking it might be closing the connection instantly as I don't enough enough RAM. I would appreciate it if someone else would see if it works on their machine. I'm attaching the indicator and the EA.
Files:
maEA.mq5  3 kb
 
phade #:
I'm thinking it might be closing the connection instantly as I don't enough enough RAM. I would appreciate it if someone else would see if it works on their machine. I'm attaching the indicator and the EA.

I replied to your message in general. Check for error messages returned from ArrayResize().

 

Finally I fixed the issue and see the EA consistently working in the strategy tester. As you might have guessed, the problem was the indicator and not the EA.

I removed ArraySetAsSeries, and I copied rates_total into the copybuffer instead of [rates_total - prev_calculated]

Then I changed the main for loop to iterate from prev_calculated until rates_total

// Calculate the indicator values
// (rates_total==prev_calculated) is 1 if it's true
// (rates_total==prev_calculated) is 0 if it's false


for (int i = prev_calculated - (rates_total==prev_calculated); i < rates_total; i++){

// code

}