Custom indicator buffers always zero

 

If my custom indicator works as coded, even when called by iCustom on visual mode it works fine. Buffers draw and reset as coded.

Why would buffers be always zero when called in an EA on Comment()?

What possible stupid mistakes I could have made?

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
#property indicator_type1   DRAW_ARROW
#property indicator_type2   DRAW_ARROW
#property indicator_type3   DRAW_ARROW
#property indicator_type4   DRAW_ARROW
#property indicator_color1  Blue
#property indicator_color2  Red
#property indicator_color3  Red
#property indicator_color4  Blue
#property indicator_label1  "HH"
#property indicator_label2  "LL"
#property indicator_label3  "HL"
#property indicator_label4  "LH"

double HHBuffer[];
double HLBuffer[];
double LLBuffer[];
double LHBuffer[];
double HHstore = 0, HLsotre = 0, LLstore = 0, LHstore = 0;
int    ExtArrowShift = 8;
double HHstoret = 0, LLstoret = 0; //these ones can be zeroed without affecting the main calculations
double _low = 0, _high = 0; // store lows and highs of last calculated incase there's a gap
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, HHBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, LHBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, LLBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, HLBuffer, INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0, PLOT_ARROW, 217);
   PlotIndexSetInteger(1, PLOT_ARROW, 217);
   PlotIndexSetInteger(2, PLOT_ARROW, 218);
   PlotIndexSetInteger(3, PLOT_ARROW, 218);
//--- arrow shifts when drawing
   PlotIndexSetInteger(0, PLOT_ARROW_SHIFT, -8);
   PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, -ExtArrowShift);
   PlotIndexSetInteger(2, PLOT_ARROW_SHIFT, ExtArrowShift);
   PlotIndexSetInteger(3, PLOT_ARROW_SHIFT, 8);
//--- sets drawing line empty value--
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| 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[])
{
   if(rates_total < 2)
      return(0);
   int start;
//--- clean up arrays
   if(prev_calculated < 2) {
      start = 2;
      ArrayInitialize(HHBuffer, EMPTY_VALUE);
      ArrayInitialize(LLBuffer, EMPTY_VALUE);
      ArrayInitialize(LHBuffer, EMPTY_VALUE);
      ArrayInitialize(HLBuffer, EMPTY_VALUE);
   } else
      start = rates_total - 1;
//--- main cycle of calculations
   for(int i = start; i < rates_total - 1 && !IsStopped(); i++) {
      //clean LH & HL storage if there's an engulfing bar
      if(high[i + 1] == HHstore && low[i + 1] == LLstore) {
         HLsotre = 0;
         LHstore = 0;
      }
      //---Higher high logic after first calculations
      if(LHstore != 0) {
         if(high[i] >= HHstore || high[i] > LHstore) {
            HHstore = high[i];
            HHstoret = high[i]; // store this HH so that we can hide HH calc when a LH form
            HHBuffer[i] = HHstore;
            _low = low[i]; // store this low incase we need a low of last calculated HH
         } else
            HHBuffer[i] = EMPTY_VALUE;
      }
      //---Higher high logic first calculations
      if(LHstore == 0) {
         if(high[i] >= HHstore && high[i + 1] < high[i]) {
            HHstore = high[i];
            HHstoret = high[i]; // store this hh so that we can hide HH calc when a LH form
            HHBuffer[i] = HHstore;
            _low = low[i]; // store this low incase we need a low of last calculated HH
         } else
            HHBuffer[i] = EMPTY_VALUE;
      }
      //--- Lower LoW logic
      if(LLstore == 0)
         LLstore = low[i - 1];
      if(low[i] <= LLstore || low[i] < HLsotre) {
         LLstore = low[i];
         LLstoret = low[i]; // store this LL so that we can hide LL calc when a HL form
         LLBuffer[i] = LLstore;
         _high = high[i]; // store this high incase we need a high of the last calc LL
      } else
         LLBuffer[i] = EMPTY_VALUE;
      //HL & LH logic after HH & LL has been calculated
      if(LLstore != 0 && HHstore != 0) {
         //--- HL logic
         if(HLsotre == 0)
            HLsotre = LLstore;
         if(high[i] == HHstore && (low[i] > LLstore || low[i] > HLsotre)) {
            HLsotre = low[i];
            LHstore = 0;
            HLBuffer[i] = HLsotre;
            LLstoret = 0; // Hide the last calculated LL until its needed
         } else
            HLBuffer[i] = EMPTY_VALUE;
         //--- LH logic
         if(low[i] == LLstore && (high[i] < HHstore || high[i] < LHstore)) {
            LHstore = high[i];
            HLsotre = 0;
            LHBuffer[i] = LHstore;
            HHstoret = 0; // Hide this last calculated HH until its needed
         } else
            LHBuffer[i] = EMPTY_VALUE;
      }
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
Step on New Rails: Custom Indicators in MQL5
Step on New Rails: Custom Indicators in MQL5
  • www.mql5.com
I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.
 

How should we know without your code?

But one hint I can give you: check the logs, Expert and Journal!

 
Lativ_:

If my custom indicator works as coded, even when called by iCustom on visual mode it works fine. Buffers draw and reset as coded.

Why would buffers be always zero when called in an EA on Comment()?

What possible stupid mistakes I could have made?

Did you use the correct buffer_num when copying buffer value?
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
Documentation on MQL5: Timeseries and Indicators Access / CopyBuffer
  • www.mql5.com
CopyBuffer - Timeseries and Indicators Access - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

Do you really expect an answer? There are no mind readers here and our crystal balls are cracked. Always post all relevant code (using Code button) or attach the source file.
     How To Ask Questions The Smart Way. (2004)
          Be precise and informative about your problem

We can't see your iCustom code, nor your indicator.

 
William Roeder #:

Do you really expect an answer? There are no mind readers here and our crystal balls are cracked. Always post all relevant code (using Code button) or attach the source file.
     How To Ask Questions The Smart Way. (2004)
          Be precise and informative about your problem

We can't see your iCustom code, nor your indicator.

I'm sorry about that I was not done with it. Here's my final code. When I run it on live data it works as it should but buffers are always zero even when called by iCustom

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
#property indicator_type1   DRAW_ARROW
#property indicator_type2   DRAW_ARROW
#property indicator_type3   DRAW_ARROW
#property indicator_type4   DRAW_ARROW
#property indicator_color1  Blue
#property indicator_color2  Red
#property indicator_color3  Red
#property indicator_color4  Blue
#property indicator_label1  "HH"
#property indicator_label2  "LL"
#property indicator_label3  "HL"
#property indicator_label4  "LH"

double HHBuffer[];
double HLBuffer[];
double LLBuffer[];
double LHBuffer[];
double HHstore = 0, HLsotre = 0, LLstore = 0, LHstore = 0;
int    ExtArrowShift = 8;
double HHstoret = 0, LLstoret = 0; //these ones can be zeroed without affecting the main calculations
double _low = 0, _high = 0; // store lows and highs of last calculated incase there's a gap
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, HHBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, LHBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, LLBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, HLBuffer, INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0, PLOT_ARROW, 217);
   PlotIndexSetInteger(1, PLOT_ARROW, 217);
   PlotIndexSetInteger(2, PLOT_ARROW, 218);
   PlotIndexSetInteger(3, PLOT_ARROW, 218);
//--- arrow shifts when drawing
   PlotIndexSetInteger(0, PLOT_ARROW_SHIFT, -8);
   PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, -ExtArrowShift);
   PlotIndexSetInteger(2, PLOT_ARROW_SHIFT, ExtArrowShift);
   PlotIndexSetInteger(3, PLOT_ARROW_SHIFT, 8);
//--- sets drawing line empty value--
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
}
//+------------------------------------------------------------------+
//| 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[])
{
   if(rates_total < 2)
      return(0);
   int start;
//--- clean up arrays
   if(prev_calculated < 2) {
      start = 2;
      ArrayInitialize(HHBuffer, EMPTY_VALUE);
      ArrayInitialize(LLBuffer, EMPTY_VALUE);
      ArrayInitialize(LHBuffer, EMPTY_VALUE);
      ArrayInitialize(HLBuffer, EMPTY_VALUE);
   } else
      start = rates_total - 1;
//--- main cycle of calculations
   for(int i = start; i < rates_total - 1 && !IsStopped(); i++) {
      //clean LH & HL storage if there's an engulfing bar
      if(high[i + 1] == HHstore && low[i + 1] == LLstore) {
         HLsotre = 0;
         LHstore = 0;
      }
      //---Higher high logic after first calculations
      if(LHstore != 0) {
         if(high[i] >= HHstore || high[i] > LHstore) {
            HHstore = high[i];
            HHstoret = high[i]; // store this HH so that we can hide HH calc when a LH form
            HHBuffer[i] = HHstore;
            _low = low[i]; // store this low incase we need a low of last calculated HH
         } else
            HHBuffer[i] = EMPTY_VALUE;
      }
      //---Higher high logic first calculations
      if(LHstore == 0) {
         if(high[i] >= HHstore && high[i + 1] < high[i]) {
            HHstore = high[i];
            HHstoret = high[i]; // store this hh so that we can hide HH calc when a LH form
            HHBuffer[i] = HHstore;
            _low = low[i]; // store this low incase we need a low of last calculated HH
         } else
            HHBuffer[i] = EMPTY_VALUE;
      }
      //--- Lower LoW logic
      if(LLstore == 0)
         LLstore = low[i - 1];
      if(low[i] <= LLstore || low[i] < HLsotre) {
         LLstore = low[i];
         LLstoret = low[i]; // store this LL so that we can hide LL calc when a HL form
         LLBuffer[i] = LLstore;
         _high = high[i]; // store this high incase we need a high of the last calc LL
      } else
         LLBuffer[i] = EMPTY_VALUE;
      //HL & LH logic after HH & LL has been calculated
      if(LLstore != 0 && HHstore != 0) {
         //--- HL logic
         if(HLsotre == 0)
            HLsotre = LLstore;
         if(high[i] == HHstore && (low[i] > LLstore || low[i] > HLsotre)) {
            HLsotre = low[i];
            LHstore = 0;
            HLBuffer[i] = HLsotre;
            LLstoret = 0; // Hide the last calculated LL until its needed
         } else
            HLBuffer[i] = EMPTY_VALUE;
         //--- LH logic
         if(low[i] == LLstore && (high[i] < HHstore || high[i] < LHstore)) {
            LHstore = high[i];
            HLsotre = 0;
            LHBuffer[i] = LHstore;
            HHstoret = 0; // Hide this last calculated HH until its needed
         } else
            LHBuffer[i] = EMPTY_VALUE;
      }
   }
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
 

On live data



On Back Test


 
      start = rates_total - 1;
//--- main cycle of calculations
   for(int i = start; i < rates_total - 1 && !IsStopped(); i++) {
      //clean LH & HL storage if there's an engulfing bar
      if(high[i + 1] == HHstore && low[i + 1] == LLstore) {
  1. i starts at rates_total - 1; your loop never runs.
  2. high[rates_total] does not exist, array exceeded.
  3. Why are you reading a future value?
  4. You never set high[] direction.
    To determine the indexing direction of time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[], call ArrayGetAsSeries(). In order not to depend on default values, you should unconditionally call the ArraySetAsSeries() function for those arrays, which are expected to work with.
              Event Handling Functions - Functions - Language Basics - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
William Roeder #:
  1. i starts at rates_total - 1; your loop never runs.
  2. high[rates_total] does not exist, array exceeded.
  3. Why are you reading a future value?
  4. You never set high[] direction.

Learning everyday. The number 3 Point, reading a future didn't make sense to me either but that what finally made the code work I guess

Reason: