Heikin Ashi RSI Oscillator: error plotting candles

 

Hi,

I was trying to convert this indicator from TradingView to MQL5 but it badly prints the candles, as in the attached photo, and i don't understand where is the problem.

From the TradingView indicator i want to convert only the Heiken Ashi code, not RSI and Stoch lines.

Here there is the code:

//+------------------------------------------------------------------+
//|                                   Heiken_Ashi_RSI_Oscillator.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_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  DodgerBlue, Red
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"
//--- indicator buffers
double ExtOBuffer[];
double ExtHBuffer[];
double ExtLBuffer[];
double ExtCBuffer[];
double ExtColorBuffer[];

input int periodoRSI=14;
input int smoothRSI=1;

int handle_harsi_close,handle_harsi_open,handle_harsi_low,handle_harsi_high;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double HA_RSI_CLOSE(int shift)
  {
   double value[];
   if(handle_harsi_close!=INVALID_HANDLE)
     {
      if(CopyBuffer(handle_harsi_close,0,shift,1,value)>0)
         return(value[0]);
     }
   return(WRONG_VALUE);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double HA_RSI_OPEN(int shift)
  {
   double value[];
   if(handle_harsi_close!=INVALID_HANDLE)
     {
      if(CopyBuffer(handle_harsi_open,0,shift,1,value)>0)
         return(value[0]);
     }
   return(WRONG_VALUE);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double HA_RSI_HIGH(int shift)
  {
   double value[];
   if(handle_harsi_close!=INVALID_HANDLE)
     {
      if(CopyBuffer(handle_harsi_high,0,shift,1,value)>0)
         return(value[0]);
     }
   return(WRONG_VALUE);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double HA_RSI_LOW(int shift)
  {
   double value[];
   if(handle_harsi_close!=INVALID_HANDLE)
     {
      if(CopyBuffer(handle_harsi_low,0,shift,1,value)>0)
         return(value[0]);
     }
   return(WRONG_VALUE);
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
   handle_harsi_close=iRSI(_Symbol,PERIOD_CURRENT,periodoRSI,PRICE_CLOSE);
   handle_harsi_open=iRSI(_Symbol,PERIOD_CURRENT,periodoRSI,PRICE_OPEN);
   handle_harsi_high=iRSI(_Symbol,PERIOD_CURRENT,periodoRSI,PRICE_HIGH);
   handle_harsi_low=iRSI(_Symbol,PERIOD_CURRENT,periodoRSI,PRICE_LOW);
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtOBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtHBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ExtLBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,ExtCBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,ExtColorBuffer,INDICATOR_COLOR_INDEX);
//---
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- sets first bar from what index will be drawn
   IndicatorSetString(INDICATOR_SHORTNAME,"Heiken Ashi RSI Oscillator");
//--- sets drawing line empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);


  }
//+------------------------------------------------------------------+
//| Heiken Ashi                                                      |
//+------------------------------------------------------------------+
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 start;
//--- preliminary calculations
   if(prev_calculated==0)
     {
      ExtLBuffer[0]=low[0];
      ExtHBuffer[0]=high[0];
      ExtOBuffer[0]=open[0];
      ExtCBuffer[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;

//--- the main loop of calculations
   for(int i=start; i<rates_total && !IsStopped(); i++)
     {

      double _closeRSI = HA_RSI_CLOSE(0);
      double _openRSI = HA_RSI_CLOSE(1);
      double _highRSI_raw = HA_RSI_HIGH(0);
      double _lowRSI_raw = HA_RSI_LOW(0);
      double _highRSI = MathMax(_highRSI_raw, _lowRSI_raw);
      double _lowRSI = MathMin(_highRSI_raw, _lowRSI_raw);

      double _close = (_openRSI + _highRSI + _lowRSI + _closeRSI) / 4;
      double _open = (_openRSI + _closeRSI) / 2;
      double _high = MathMax(_highRSI, MathMax(_open, _close));
      double _low = MathMin(_lowRSI, MathMin(_open, _close));

      ExtLBuffer[i]=_low;
      ExtHBuffer[i]=_high;
      ExtOBuffer[i]=_open;
      ExtCBuffer[i]=_close;

      //--- set candle color
      if(_open<_close)
         ExtColorBuffer[i]=0.0; // set color DodgerBlue
      else
         ExtColorBuffer[i]=1.0; // set color Red
     }
//---
   return(rates_total);
  }
//+------------------------------------------------------------------+

Thank you

Files:
screen.png  15 kb
 
  1.    SetIndexBuffer(0,ExtOBuffer,INDICATOR_DATA);
       SetIndexBuffer(1,ExtHBuffer,INDICATOR_DATA);
       SetIndexBuffer(2,ExtLBuffer,INDICATOR_DATA);
       SetIndexBuffer(3,ExtCBuffer,INDICATOR_DATA);
       SetIndexBuffer(4,ExtColorBuffer,INDICATOR_COLOR_INDEX);
    ⋮
    if(prev_calculated==0)
         {
          ExtLBuffer[0]=low[0];
          ExtHBuffer[0]=high[0];
          ExtOBuffer[0]=open[0];
          ExtCBuffer[0]=close[0];
    1. You haven't indicated that the buffers and arrays are being accessed non-series.

    2. Buffers are automatically size, are as-series, and elements are moved for you, new elements are set to EMPTY_VALUE (or your designated. They can also draw on the chart automatically.

    3. In MT4, buffers and MT4 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

    4. In MT5, you must set the direction.

      To define the indexing direction in the time[], open[], high[], low[], close[], tick_volume[], volume[] and spread[] arrays, call the ArrayGetAsSeries() function. In order not to depend on defaults, call the ArraySetAsSeries() function for the arrays to work with.           Event Handling / OnCalculate - Reference on algorithmic/automated trading language for MetaTrader 5

  2.       if(CopyBuffer(handle_harsi_high,0,shift,1,value)>0)
    1. What direction is a shift of zero here? What is your caller expecting?

    2. Why create separate functions when you can us iClose, etc.?