Plotting issue and the data is different on ATR (MQL5)

 

Hey, I'm having a issue on a ATR indicator. Even though the codes don't have any problem when compiling, it doesn't plot on the screen. I think there is a thing that I didn't get on PlotIndexes. I also checked the datas of arrays(ind_buffer1, ind_buffer2) and nothing is wrong, the data is correct while I'm printing and checking it in the EA, but on Data Window it's different than the indicator shows me. I didn't get the logic here. Anyone can illuminate me or show me where I'm incorrect?


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

#property  indicator_chart_window
#property  indicator_buffers 2
#property  indicator_plots   1
#property  indicator_type1   DRAW_ARROW
#property  indicator_color1  RoyalBlue
#property  indicator_width1  0
#property  indicator_style1  0
#property  indicator_type2   DRAW_ARROW
#property  indicator_color2  Red
#property  indicator_width2  0
#property  indicator_style2  0

input int BackPeriod = 2000;
input int ATRPeriod = 20;
input double Factor = 2;
input bool MedianPrice = true;
input bool MedianBase = true;
input bool CloseBase = false;
input double distance = 0;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int rates_total_global     = 0; // Globally Scoped copy of "rates_total" (if required)
int prev_calculated_global = 0; // Globally Scoped copy of "prev_calculated"

//---- indicator buffers
double     ind_buffer1[];
double     ind_buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   /*SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0, 159);
   SetIndexDrawBegin(0,ATRPeriod);*/
   SetIndexBuffer(0,ind_buffer1);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,0);
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ARROW);
   PlotIndexSetInteger(0,PLOT_ARROW,0);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ATRPeriod);
//SetIndexStyle(1,DRAW_LINE,EMPTY,2);
   /*SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1, 159);
   SetIndexDrawBegin(1,ATRPeriod);*/
   SetIndexBuffer(1,ind_buffer2);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,1);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_ARROW);
   PlotIndexSetInteger(1,PLOT_ARROW,0);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ATRPeriod);

//---- name for DataWindow and indicator subwindow label
   IndicatorSetString(INDICATOR_SHORTNAME,"ATR Stop("+ATRPeriod+" * "+Factor+")");
   PlotIndexSetString(0,PLOT_LABEL,"Support");
   PlotIndexSetString(1,PLOT_LABEL,"Resistance");
   
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+2);
//---
   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[])
  {
//---
   rates_total_global     = rates_total;     // Update Global copy (if required)
   prev_calculated_global = prev_calculated; // Update Global copy

   int limit;
   int counted_bars=IndicatorCountedMQL4();
   double PrevUp, PrevDn;
   double CurrUp, CurrDn;
   double PriceCurr, PricePrev;
   double PriceLvl;
   double PriceHLorC;
   double LvlUp = 0;
   double LvlDn = 100000;
   int Dir = 1;
   int InitDir;
//---- check for possible errors
   if(counted_bars<0)
      return(-1);
//---- last counted bar will be recounted
//if(counted_bars>0) counted_bars--;
   if(counted_bars==0)
      counted_bars++;
   if(BackPeriod==0)
      limit=Bars(_Symbol,PERIOD_CURRENT)-counted_bars;
   else
      limit=BackPeriod;
//---- fill in buffervalues
   InitDir = 0;
   Print("");
   Print("limit: ",limit);
   for(int i=limit; i>=0; i--)
     {
      if(MedianPrice)
         PriceLvl = (high[i] + low[i])/2;
      else
         PriceLvl = close[i];

      if(MedianBase)
        {
         PriceCurr = (high[i] + low[i])/2;
         PricePrev = (high[i+1] + low[i+1])/2;
        }
      else
        {
         PriceCurr = close[i];
         PricePrev = close[i+1];
        }

      if(InitDir == 0)
        {
         CurrUp=PriceCurr - (iATRMQL4(NULL,0,ATRPeriod,i) * Factor);
         PrevUp=PricePrev - (iATRMQL4(NULL,0,ATRPeriod,i+1) * Factor);
         CurrDn=PriceCurr + (iATRMQL4(NULL,0,ATRPeriod,i) * Factor);
         PrevDn=PricePrev + (iATRMQL4(NULL,0,ATRPeriod,i+1) * Factor);

         if(CurrUp > PrevUp)
            Dir = 1;
         LvlUp = CurrUp;
         if(CurrDn < PrevDn)
            Dir = -1;
         LvlDn = CurrDn;
         InitDir = 1;

        }

      CurrUp=PriceLvl - (iATRMQL4(NULL,0,ATRPeriod,i) * Factor);
      CurrDn=PriceLvl + (iATRMQL4(NULL,0,ATRPeriod,i) * Factor);

      //if (i==0) Comment("Dir:",Dir,",CurrUp:",CurrUp,",PrevUp:",PrevUp,",CurrDn:",CurrDn,",PrevDn:",PrevDn);
      if(Dir == 1)
        {
         if(CurrUp > LvlUp)
           {
            ind_buffer1[i] = NormalizeDouble(CurrUp-distance,_Digits);
            LvlUp = CurrUp;
           }
         else
           {
            ind_buffer1[i] = NormalizeDouble(LvlUp-distance,_Digits);
           }
         ind_buffer2[i] = EMPTY_VALUE;
         if(CloseBase)
            PriceHLorC = close[i];
         else
            PriceHLorC=low[i];
         if(PriceHLorC < ind_buffer1[i])
           {
            Dir = -1;
            LvlDn = 100000;
           }
        }

      if(Dir == -1)
        {
         if(CurrDn < LvlDn)
           {
            ind_buffer2[i] = NormalizeDouble(CurrDn+distance,_Digits);
            LvlDn = CurrDn;
           }
         else
           {
            ind_buffer2[i] = NormalizeDouble(LvlDn+distance,_Digits);
           }
         ind_buffer1[i] = EMPTY_VALUE;
         if(CloseBase)
            PriceHLorC = close[i];
         else
            PriceHLorC=high[i];
         if(PriceHLorC > ind_buffer2[i])
           {
            Dir = 1;
            LvlUp = 0;
           }
        }

      if(Dir == 1)
        {
         if(CurrUp > LvlUp)
           {
            ind_buffer1[i] = CurrUp-distance;
            LvlUp = CurrUp;
           }
         else
           {
            ind_buffer1[i] = LvlUp-distance;
           }
         ind_buffer2[i] = EMPTY_VALUE;
         if(CloseBase)
            PriceHLorC = close[i];
         else
            PriceHLorC=low[i];
         if(PriceHLorC < ind_buffer1[i])
           {
            Dir = -1;
            LvlDn = 100000;
           }
        }

      //if (ind_buffer1[0]!=EMPTY_VALUE && ind_buffer1[1]==EMPTY_VALUE) {ind_buffer1[i+1]=ind_buffer1[i];}
      //if (ind_buffer2[0]!=EMPTY_VALUE && ind_buffer2[1]==EMPTY_VALUE) {ind_buffer2[i+1]=ind_buffer2[i];}
      Print("Ind Buffer1[i]:  ", ind_buffer1[i]);
      Print("Ind Buffer2[i]:  ", ind_buffer2[i]);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double iATRMQL4(string symbol,
                int tf,
                int period,
                int shift)
  {
   ENUM_TIMEFRAMES timeframe=TFMigrate(tf);
   int handle=iATR(symbol,timeframe,period);
   if(handle<0)
     {
      Print("The iATR object is not created: Error",GetLastError());
      return(-1);
     }
   else
      return(CopyBufferMQL4(handle,0,shift));
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES TFMigrate(int tf)
  {
   switch(tf)
     {
      case 0:
         return(PERIOD_CURRENT);
      case 1:
         return(PERIOD_M1);
      case 5:
         return(PERIOD_M5);
      case 15:
         return(PERIOD_M15);
      case 30:
         return(PERIOD_M30);
      case 60:
         return(PERIOD_H1);
      case 240:
         return(PERIOD_H4);
      case 1440:
         return(PERIOD_D1);
      case 10080:
         return(PERIOD_W1);
      case 43200:
         return(PERIOD_MN1);

      case 2:
         return(PERIOD_M2);
      case 3:
         return(PERIOD_M3);
      case 4:
         return(PERIOD_M4);
      case 6:
         return(PERIOD_M6);
      case 10:
         return(PERIOD_M10);
      case 12:
         return(PERIOD_M12);
      case 16385:
         return(PERIOD_H1);
      case 16386:
         return(PERIOD_H2);
      case 16387:
         return(PERIOD_H3);
      case 16388:
         return(PERIOD_H4);
      case 16390:
         return(PERIOD_H6);
      case 16392:
         return(PERIOD_H8);
      case 16396:
         return(PERIOD_H12);
      case 16408:
         return(PERIOD_D1);
      case 32769:
         return(PERIOD_W1);
      case 49153:
         return(PERIOD_MN1);
      default:
         return(PERIOD_CURRENT);
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CopyBufferMQL4(int handle,int index,int shift)
  {
   double buf[];
   switch(index)
     {
      case 0:
         if(CopyBuffer(handle,0,shift,1,buf)>0)
            return(buf[0]);
         break;
      case 1:
         if(CopyBuffer(handle,1,shift,1,buf)>0)
            return(buf[0]);
         break;
      case 2:
         if(CopyBuffer(handle,2,shift,1,buf)>0)
            return(buf[0]);
         break;
      case 3:
         if(CopyBuffer(handle,3,shift,1,buf)>0)
            return(buf[0]);
         break;
      case 4:
         if(CopyBuffer(handle,4,shift,1,buf)>0)
            return(buf[0]);
         break;
      default:
         break;
     }
   return(EMPTY_VALUE);
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int IndicatorCountedMQL4()
  {
   if(prev_calculated_global>0)
      return(prev_calculated_global-1);
   if(prev_calculated_global==0)
      return(0);
   return(0);
  }
//+------------------------------------------------------------------+

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

You made a BIG mistake: you create an indicator handle on every tick.

Correctly, you need to do this: you need to get the indicator handle ONCE and you need to do this in OnInit.

 
weyhub: Hey, I'm having a issue on a ATR indicator. Even though the codes don't have any problem when compiling, it doesn't plot on the screen. I think there is a thing that I didn't get on PlotIndexes. I also checked the datas of arrays(ind_buffer1, ind_buffer2) and nothing is wrong, the data is correct while I'm printing and checking it in the EA, but on Data Window it's different than the indicator shows me. I didn't get the logic here. Anyone can illuminate me or show me where I'm incorrect?

Don't rely on MQL4 to MQL5 kludge conversion tactics. It is just going to complicate things and you will end up not properly understanding MQL5.

Do away with the MQL4 stuff and code it properly in the MQL5 way!