Cannot custom indicator in Expert Advisor

 

I have made a custom indicator written in MQL5 which does the following:

1-       Calculate the 9-period hull moving average for the open prices. Name it HMA9open

2-       Calculate the 9-period hull moving average for the high prices. Name it HMA9high

3-       Calculate the 9-period hull moving average for the low prices. Name it HMA9low

4-        Calculate Bullpower using the following equation: Bullpower = HMA9high - HMA9open

5-       Calculate Bearpower using the following equation: Bearpower = HMA9low - HMA9open

6-       Calculate Bullbearpower using the following equation: Bullbearpower = Bullpower + Bearpower. Name it BBP

7-       Plot BBP as a histogram which has a green color if its value is greater than or equal zero and a red color if its value is lower than zero

The indicator works fine and is painted as a green/red histogram oscillator around zero when compiled

This is the custom indicator’s code:

//+------------------------------------------------------------------+
//|                                              BullBearPower.mq5    |
//|                        Custom Indicator for Bull and Bear Power    |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Custom Indicator"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 7
#property indicator_plots   1
//--- plot BBP
#property indicator_label1  "BBP"
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrGreen,clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  5

//--- input parameters
input int HMA_Period = 9; // HMA Period

//--- indicator buffers
double HMA9openBuffer[];
double HMA9highBuffer[];
double HMA9lowBuffer[];
double BullPowerBuffer[];
double BearPowerBuffer[];
double BBPBuffer[];
double BBPHistogramColors[];

//--- global variables
int wma_period, wma_handle1, wma_handle2, sqrt_period;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                           |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, BBPBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, BBPHistogramColors, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, HMA9openBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(3, HMA9highBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(4, HMA9lowBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, BullPowerBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(6, BearPowerBuffer, INDICATOR_CALCULATIONS);
   
   //--- set short name and decimal places
   IndicatorSetString(INDICATOR_SHORTNAME, "BullBearPower");
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   
   //--- validate HMA period
   if(HMA_Period < 2)
   {
      Print("HMA Period must be at least 2");
      return(INIT_PARAMETERS_INCORRECT);
   }
   
   //--- set global variables for HMA calculation
   wma_period = HMA_Period;
   sqrt_period = (int)MathFloor(MathSqrt(HMA_Period));
   
   //--- initialize empty buffers
   ArraySetAsSeries(HMA9openBuffer, true);
   ArraySetAsSeries(HMA9highBuffer, true);
   ArraySetAsSeries(HMA9lowBuffer, true);
   ArraySetAsSeries(BullPowerBuffer, true);
   ArraySetAsSeries(BearPowerBuffer, true);
   ArraySetAsSeries(BBPBuffer, true);
   ArraySetAsSeries(BBPHistogramColors, true);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Hull Moving Average calculation                                   |
//+------------------------------------------------------------------+
void CalculateHMA(const double &price[], double &hma[], int rates_total, int prev_calculated)
{
   double wma1[], wma2[], diff[], sqrt_wma[];
   ArraySetAsSeries(wma1, true);
   ArraySetAsSeries(wma2, true);
   ArraySetAsSeries(diff, true);
   ArraySetAsSeries(sqrt_wma, true);
   
   ArrayResize(wma1, rates_total);
   ArrayResize(wma2, rates_total);
   ArrayResize(diff, rates_total);
   ArrayResize(sqrt_wma, rates_total);
   
   //--- calculate WMAs
   for(int i = 0; i < rates_total - wma_period && i < rates_total; i++)
   {
      double sum = 0, weight = 0;
      for(int j = 0; j < wma_period; j++)
      {
         if(i + j < rates_total)
         {
            sum += price[i + j] * (wma_period - j);
            weight += (wma_period - j);
         }
      }
      if(weight > 0)
         wma1[i] = sum / weight;
      else
         wma1[i] = 0;
   }
   
   for(int i = 0; i < rates_total - wma_period / 2 && i < rates_total; i++)
   {
      double sum = 0, weight = 0;
      for(int j = 0; j < wma_period / 2; j++)
      {
         if(i + j < rates_total)
         {
            sum += price[i + j] * (wma_period / 2 - j);
            weight += (wma_period / 2 - j);
         }
      }
      if(weight > 0)
         wma2[i] = sum / weight;
      else
         wma2[i] = 0;
   }
   
   //--- calculate 2*WMA(n/2) - WMA(n)
   for(int i = 0; i < rates_total; i++)
   {
      if(wma1[i] != 0 && wma2[i] != 0)
         diff[i] = 2 * wma2[i] - wma1[i];
      else
         diff[i] = 0;
   }
   
   //--- calculate WMA of the difference
   for(int i = 0; i < rates_total - sqrt_period && i < rates_total; i++)
   {
      double sum = 0, weight = 0;
      for(int j = 0; j < sqrt_period; j++)
      {
         if(i + j < rates_total)
         {
            sum += diff[i + j] * (sqrt_period - j);
            weight += (sqrt_period - j);
         }
      }
      if(weight > 0)
         hma[i] = sum / weight;
      else
         hma[i] = 0;
   }
}

//+------------------------------------------------------------------+
//| 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[])
{
   //--- set array as series
   ArraySetAsSeries(open, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   
   //--- calculate HMAs
   CalculateHMA(open, HMA9openBuffer, rates_total, prev_calculated);
   CalculateHMA(high, HMA9highBuffer, rates_total, prev_calculated);
   CalculateHMA(low, HMA9lowBuffer, rates_total, prev_calculated);
   
   //--- calculate BullPower, BearPower, and BBP
   for(int i = 0; i < rates_total && i < rates_total - HMA_Period; i++)
   {
      if(HMA9openBuffer[i] != 0 && HMA9highBuffer[i] != 0 && HMA9lowBuffer[i] != 0)
      {
         BullPowerBuffer[i] = HMA9highBuffer[i] - HMA9openBuffer[i];
         BearPowerBuffer[i] = HMA9lowBuffer[i] - HMA9openBuffer[i];
         BBPBuffer[i] = BullPowerBuffer[i] + BearPowerBuffer[i];
         BBPHistogramColors[i] = (BBPBuffer[i] >= 0) ? 0 : 1; // 0 for green, 1 for red
      }
      else
      {
         BullPowerBuffer[i] = 0;
         BearPowerBuffer[i] = 0;
         BBPBuffer[i] = 0;
         BBPHistogramColors[i] = 0;
      }
   }
   
   return(rates_total);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   //--- clean up
}


Now I need to write an expert advisor code in MQL5 which:

1-       Opens only one buy position whenever the custom indicator’s value equals more than zero, and closes any open sell positions

2-       Opens only one sell position whenever the custom indicator’s value equals less than zero, and closes any open buy positions

This is my attempt at writing the EA’s code :

//+------------------------------------------------------------------+
//|                                              BullBearPowerEA.mq5  |
//|                        Expert Advisor for BullBearPower Indicator  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Your Name"
#property link      "https://www.mql5.com"
#property version   "1.00"

//--- input parameters
input int      HMA_Period = 9;        // HMA Period for Indicator
input double   LotSize = 0.1;         // Lot Size
input int      Slippage = 3;          // Slippage (in points)
input string   IndicatorName = "BullBearPower"; // Indicator Name

//--- global variables
int indicator_handle;
double BBPBuffer[];

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- create handle for the BullBearPower indicator
   indicator_handle = iCustom(_Symbol, _Period, IndicatorName, HMA_Period);
   if(indicator_handle == INVALID_HANDLE)
   {
      Print("Failed to create indicator handle: ", GetLastError());
      return(INIT_FAILED);
   }
   
   //--- set array as series
   ArraySetAsSeries(BBPBuffer, true);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   //--- release indicator handle
   if(indicator_handle != INVALID_HANDLE)
      IndicatorRelease(indicator_handle);
}

//+------------------------------------------------------------------+
//| Close positions by type                                           |
//+------------------------------------------------------------------+
void ClosePositions(int type)
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_TYPE) == type)
         {
            CTrade trade;
            trade.PositionClose(ticket, Slippage);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Check if position exists for the symbol and type                  |
//+------------------------------------------------------------------+
bool PositionExists(int type)
{
   for(int i = 0; i < PositionsTotal(); i++)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
      {
         if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_TYPE) == type)
            return true;
      }
   }
   return false;
}

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
{
   //--- get indicator data
   if(CopyBuffer(indicator_handle, 0, 0, 2, BBPBuffer) <= 0)
   {
      Print("Failed to copy indicator buffer: ", GetLastError());
      return;
   }
   
   //--- get current BBP value
   double bbp_current = BBPBuffer[0]; // previous bar
   
   CTrade trade;
   
   //--- buy condition: BBP >= 0
   if(bbp_current >= 0)
   {
      //--- close all sell positions
      ClosePositions(POSITION_TYPE_SELL);
      
      //--- open buy position if no buy position exists
      if(!PositionExists(POSITION_TYPE_BUY))
      {
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         trade.Buy(LotSize, _Symbol, ask, 0, 0, "BBP Buy");
      }
   }
   //--- sell condition: BBP < 0
   else
   {
      //--- close all buy positions
      ClosePositions(POSITION_TYPE_BUY);
      
      //--- open sell position if no sell position exists
      if(!PositionExists(POSITION_TYPE_SELL))
      {
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         trade.Sell(LotSize, _Symbol, bid, 0, 0, "BBP Sell");
      }
   }
}

//+------------------------------------------------------------------+
//| Include trade library                                             |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

The EA gives 0 errors when compiled. However when i try to backtest the EA it gives these errors (in the attached screenshot)

How can i solve this issue? 

 

Your image shows “cannot load indicator/BullBearPower.ex5”

Either you didn't put the indicator in the indicators folder, and/or you didn't successfully compile it.

 
William Roeder #:

Your image shows “cannot load indicator/BullBearPower.ex5”

Either you didn't put the indicator in the indicators folder, and/or you didn't successfully compile it.

So the problem is in the indicator not the EA ? I have the indicator in the indicators folder as shown in the attached photo. Should i move it to the examples or free indicators folder? 

you can also copy the indicator's code in the code editor and compile it , it will give you zero errors. And i know the indicator's code works well because it paints the oscillator when added to the chart as in the photo

 

The problem is clear. Your indicator name is "BBP test" but you called it with another name.

input string   IndicatorName = "BullBearPower"; // Indicator Name
The real filename should be put into iCustom call, not the Indicator Shortname.
 

Just recompile the indicator and make sure it is in the correct folder...why do you have an input parameter for the path of the indicator instead of just hardcoding it in your EA????

 
Fabio Cavalloni #:

The problem is clear. Your indicator name is "BBP test" but you called it with another name.

The real filename should be put into iCustom call, not the Indicator Shortname.
Thanks it worked. Do you know if i can embed the custom indicator's code right into the EA's code so that i can use it directly without the call function? 
 
Alfred Manyasi #:

Just recompile the indicator and make sure it is in the correct folder...why do you have an input parameter for the path of the indicator instead of just hardcoding it in your EA????

I checked and the indicator's name was incorrect. Regarding hardcoding the custom indicator in the EA. How can i do that? do you have an article or video explaining that as i can't find any 
 
sodastodas #:
Thanks it worked. Do you know if i can embed the custom indicator's code right into the EA's code so that i can use it directly without the call function? 
Use #resource command to embed the indicator .ex5 inside the EA .ex5.

All coding approach remain the same, just a little adjustment into the iCustom indicator name that need "::" at the beginning of the name. You don't need to "embed the code".

Search on documentations and you will find all related information!