Inside Bar Paints Wrong Candle

Muhammad Shamsuddeen Muhammad  

The indicator seems to paint the wrong candles. The calculation seems to work when I choose a different drawing method (DRAW_ARROWS).


But I already have another indicator that draws arrows. So i dont want to clutter the chart.


Can someone kindly look over the code and assist me in fixing the issue.


Would really appreciate the aid.


//+------------------------------------------------------------------+
//|                                                     Fractals.mq5 |
//|                   Copyright 2009-2020, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2020, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 1
#property indicator_type1 DRAW_CANDLES
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrDarkSlateGray
#property indicator_width1 1
//--- indicator buffers
double H[];
double L[];
double O[];
double C[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, O, INDICATOR_DATA);
   SetIndexBuffer(1, H, INDICATOR_DATA);
   SetIndexBuffer(2, L, INDICATOR_DATA);
   SetIndexBuffer(3, C, INDICATOR_DATA);

   ArraySetAsSeries(O, true);
   ArraySetAsSeries(H, true);
   ArraySetAsSeries(L, true);
   ArraySetAsSeries(C, true);
  }
//+------------------------------------------------------------------+
//|  Fractals on 3 bars                                              |
//+------------------------------------------------------------------+
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<3)
      return(0);

   int start;
//--- clean up arrays
   if(prev_calculated<5)
     {
      start=2;
      ArraySetAsSeries(open, true);
      ArraySetAsSeries(high, true);
      ArraySetAsSeries(low, true);
      ArraySetAsSeries(close, true);
     }
   else
      start=rates_total-3;
//--- main cycle of calculations
   for(int i=start; i<rates_total-1 && !IsStopped(); i++)
     {
      //--- Upper Fractal
      if(high[i]<high[i-1] && low[i]>low[i-1])
         {
         H[i] = high[i];
         L[i] = low[i];
         O[i] = open[i];
         C[i] = close[i];
      }
      else
      {
         H[i] = EMPTY_VALUE;
         L[i] = EMPTY_VALUE;
         O[i] = EMPTY_VALUE;
         C[i] = EMPTY_VALUE;
      }
    }
   return(rates_total);
 }

//+------------------------------------------------------------------+
William Roeder  
tradingwisely: The indicator seems to paint the wrong candles.
  1. You do not set the OnCalc arrays to as-series except for the first run.

    In MT4, buffers and the predefined arrays are all ordered AsSeries. There is a difference between the arrays passed to OnCalculate (e.g. low[]) and the MT4 predefined variables (e.g. Low[].) The passed arrays have no default direction, just like MT5.

    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 - MQL4 Reference

  2. Your loop runs to rates_total-3 to rates_total-1, your loop is processing non-series direction (the oldest bars on the chart,)  but putting values into as-series buffer.

  3. See How to do your lookbacks correctly #9#14 & #19. (2016) Count down to zero, change your indexing (i-1) to as-series (i+1). Set the arrays to as-series.

Muhammad Shamsuddeen Muhammad  
William Roeder #:
  1. You do not set the OnCalc arrays to as-series except for the first run.

  2. Your loop runs to rates_total-3 to rates_total-1, your loop is processing non-series direction (the oldest bars on the chart,)  but putting values into as-series buffer.

  3. See How to do your lookbacks correctly #9#14 & #19. (2016) Count down to zero, change your indexing (i-1) to as-series (i+1). Set the arrays to as-series.

Ive tried to implement what you said for the past 3 days, but to no avail.

Regards to 1. I moved the As-Series to On-Init so it runs only once.

Regards to 2. I modified the rates_total code slightly.

Regards to 3, I changed the loop condition from i-1 to i+1.


Kindly see the updated code below for where I might have misinterpreted what you said.


//+------------------------------------------------------------------+
//|                                                     Fractals.mq5 |
//|                   Copyright 2009-2020, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2020, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 1
#property indicator_type1 DRAW_CANDLES
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrDarkGray
#property indicator_width1 1
//--- indicator buffers
double H[];
double L[];
double O[];
double C[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, O, INDICATOR_DATA);
   SetIndexBuffer(1, H, INDICATOR_DATA);
   SetIndexBuffer(2, L, INDICATOR_DATA);
   SetIndexBuffer(3, C, INDICATOR_DATA);

   ArraySetAsSeries(O, true);
   ArraySetAsSeries(H, true);
   ArraySetAsSeries(L, true);
   ArraySetAsSeries(C, true);
   
   double open[], high[], low[], close[];
   
   ArraySetAsSeries(open, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(close, true);
   
   int lookback = 1000;
  }
//+------------------------------------------------------------------+
//|  Inside Bar                                                      |
//+------------------------------------------------------------------+
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[])
  {
   
      
      
      int counted_bars = prev_calculated;
      if (counted_bars < 0) return(-1);
      if (counted_bars > 0) counted_bars--;
      int i = rates_total - counted_bars - 1;
      if (i == 0) i++;

      while(i >= 0)
         if(high[i]<high[i+1] && low[i]>low[i+1]){
            H[i] = high[i];
            L[i] = low[i];
            O[i] = open[i];
            C[i] = close[i];
         }
         else
         {
            H[i] = EMPTY_VALUE;
            L[i] = EMPTY_VALUE;
            O[i] = EMPTY_VALUE;
            C[i] = EMPTY_VALUE;
         }
      
   
   return rates_total; // Recalculate current bar next tick.
}

//+------------------------------------------------------------------+
William Roeder  
  1. void OnInit()
      {
    ⋮   
       double open[], high[], low[], close[];
       
       ArraySetAsSeries(open, true);
       ArraySetAsSeries(high, true);
       ArraySetAsSeries(low, true);
       ArraySetAsSeries(close, true);

    These do nothing. Those arrays are gone when the function returns.

  2. 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[])

    These are the arrays you are using.

  3.       int counted_bars = prev_calculated;
          if (counted_bars < 0) return(-1);
          if (counted_bars > 0) counted_bars--;
          int i = rates_total - counted_bars - 1;
          if (i == 0) i++;
    You didn't read and understand the link I provided, and implement your look back correctly.
Muhammad Shamsuddeen Muhammad  
William Roeder #:
  1. These do nothing. Those arrays are gone when the function returns.

  2. These are the arrays you are using.

  3. You didn't read and understand the link I provided, and implement your look back correctly.

Ok, I really appreciate the help so far, I think i now understand a little bit more.

I have made edits to the code prior. With


Regards to 1 and 2... I think you want me to utilize the Array Get As Series instead.

Regards to 3, I have used the sample code you provided in that post.


The code however now runs with no errors, but no candles are being highlighted. Kindly see modified code below:


//+------------------------------------------------------------------+
//|                                                     Fractals.mq5 |
//|                   Copyright 2009-2020, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2020, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 1
#property indicator_type1 DRAW_CANDLES
#property indicator_style1 STYLE_SOLID
#property indicator_color1 clrDarkGray
#property indicator_width1 1
//--- indicator buffers
double H[];
double L[];
double O[];
double C[];
int lookback;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, O, INDICATOR_DATA);
   SetIndexBuffer(1, H, INDICATOR_DATA);
   SetIndexBuffer(2, L, INDICATOR_DATA);
   SetIndexBuffer(3, C, INDICATOR_DATA);

   ArraySetAsSeries(O, true);
   ArraySetAsSeries(H, true);
   ArraySetAsSeries(L, true);
   ArraySetAsSeries(C, true);     
     
   }
//+------------------------------------------------------------------+
//|  Fractals on 3 bars                                              |
//+------------------------------------------------------------------+
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[])
  {
   
      
      ArrayGetAsSeries(open);
      ArrayGetAsSeries(high);
      ArrayGetAsSeries(low);
      ArrayGetAsSeries(close);
      
      lookback = 1000;
      int i=0;
      
      for(int iBar = Bars(_Symbol,PERIOD_CURRENT)-1-MathMax(lookback, prev_calculated); iBar >= 0; --iBar){
         if(high[i]<high[i+1] && low[i]>low[i+1]){
            H[i] = high[i];
            L[i] = low[i];
            O[i] = open[i];
            C[i] = close[i];
         }
         else
         {
            H[i] = EMPTY_VALUE;
            L[i] = EMPTY_VALUE;
            O[i] = EMPTY_VALUE;
            C[i] = EMPTY_VALUE;
         }
      
   }
   return rates_total-1; // Recalculate current bar next tick.
}

//+------------------------------------------------------------------+
William Roeder  

Read my link again.

  1.  if(high[i]<high[i+1] && low[i]>low[i+1]){
    Your look back is one. read my link again.
  2. for(int iBar = Bars(_Symbol,PERIOD_CURRENT)-1-MathMax(lookback, prev_calculated
    No need for Bars(), you already have rates_total. Read my link again.