Equivalent of BarsCalculated() in MQL4

 

Hi all

I'm converting a code from MQL5 to MQL4. In code, i have faced BarsCalculated() which i need help to convert it to MQL4.
This is the code which computes and draws Zigzag on RSI indicator (=Zigzag with input of RSI values, rather than price values).


//+------------------------------------------------------------------+
//|                                                   ZigZag_RSI.mq5 |
//|                      Copyright © 2016, MetaQuotes Software Corp. |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+ 
//---- авторство индикатора
#property copyright "Copyright © 2016, MetaQuotes Software Corp."
//---- ссылка на сайт автора
#property link      "http://www.metaquotes.net/"
//---- номер версии индикатора
#property version   "1.00"
#property description "ZigZag" 
//---- отрисовка индикатора в отдельном окне
#property indicator_separate_window 
//---- для расчёта и отрисовки индикатора использовано 3 буфера
#property indicator_buffers 3
//---- использовано всего 2 графических построения
#property indicator_plots   2
//+----------------------------------------------+
//|  Параметры отрисовки осциллятора             |
//+----------------------------------------------+
//---- отрисовка индикатора 1 в виде линии
#property indicator_type1   DRAW_LINE
//---- в качестве цвета линии индикатора использован DodgerBlue цвет
#property indicator_color1  clrDodgerBlue
//---- линия индикатора 1 - непрерывная кривая
#property indicator_style1  STYLE_SOLID
//---- толщина линии индикатора 1 равна 1
#property indicator_width1  1
//---- отображение бычей метки индикатора
#property indicator_label1  "RSI Oscillator"
//+----------------------------------------------+ 
//|  Параметры отрисовки зигзага                 |
//+----------------------------------------------+
//---- в качестве индикатора использован ZIGZAG
#property indicator_type2   DRAW_ZIGZAG
//---- отображение метки индикатора
#property indicator_label2  "ZigZag_RSI"
//---- в качестве цвета линии индикатора использован MediumSlateBlue цвет
#property indicator_color2 clrMediumSlateBlue
//---- линия индикатора - непрерывная кривая
#property indicator_style2  STYLE_SOLID
//---- толщина линии индикатора равна 2
#property indicator_width2  2
//+----------------------------------------------+
//|  объявление констант                         |
//+----------------------------------------------+
#define RESET  0 // Константа для возврата терминалу команды на пересчёт индикатора
//+----------------------------------------------+ 
//| Входные параметры индикатора                 |
//+----------------------------------------------+ 
//---- входные параметры осциллятора RSI
input uint RSI_period=13;                                  // период RSI  
input ENUM_APPLIED_PRICE   RSIPrice=PRICE_CLOSE;           // ценовой входной ряд RSI
//---- входные параметры зигзага
input uint ExtDepth=3;
input uint ExtDeviation=3;
input uint ExtBackstep=3;
input uint  HighLevel=70;                                 // уровень перезакупа
input uint  LowLevel=30;                                  // уровень перепроданности
//+----------------------------------------------+
//---- объявление динамических массивов, которые будут в 
// дальнейшем использованы в качестве индикаторных буферов
double LowestBuffer[],HighestBuffer[],RSIBuffer[];

//---- Declaring memory variables for recalculating the indicator only on uncounted bars
int LASTlowpos,LASThighpos,LASTColor;
double LASTlow0,LASTlow1,LASThigh0,LASThigh1;

//---- Declaring integer data origin variables
int min_rates_1,min_rates_total,RSI_Handle;
//+------------------------------------------------------------------+ 
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+ 
int OnInit()
  {
//--- getting the handle of the iRSI indicator
   RSI_Handle=iRSI(NULL,0,RSI_period,RSIPrice,0);
   if(RSI_Handle==INVALID_HANDLE)
     {
      Print(" Не удалось получить хендл индикатора iRSI");
      return(INIT_FAILED);
     }
//---- Initializing data origin variables
   min_rates_1=int(RSI_period);
   min_rates_total=int(min_rates_1+ExtDepth+ExtBackstep);

//---- transformation of dynamic arrays into indicator buffers
   SetIndexBuffer(0,RSIBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,LowestBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,HighestBuffer,INDICATOR_DATA);
//---- prohibiting the indicator from drawing empty values
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//---- индексация элементов в буферах как в таймсериях   
   ArraySetAsSeries(LowestBuffer,true);
   ArraySetAsSeries(HighestBuffer,true);
   ArraySetAsSeries(RSIBuffer,true);
//---- indexing elements in buffers as in timeseries
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,min_rates_1);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,min_rates_total);
//---- Setting the indicator display precision format
   IndicatorSetInteger(INDICATOR_DIGITS,0);
//---- имя для окон данных и лэйба для субъокон 
   IndicatorSetString(INDICATOR_SHORTNAME,"ZigZag_RSI");
//---- number of horizontal levels of the indicator 3
   IndicatorSetInteger(INDICATOR_LEVELS,3);
//---- values of the horizontal levels of the indicator
   IndicatorSetDouble(INDICATOR_LEVELVALUE,0,HighLevel);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,1,50);
   IndicatorSetDouble(INDICATOR_LEVELVALUE,2,LowLevel);
//---- as colors of lines of horizontal levels used
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,clrLimeGreen);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,1,clrGray);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,2,clrRed);
//----a short dash-dotted line is used in the horizontal level line
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,0,STYLE_DASHDOTDOT);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,1,STYLE_DASHDOTDOT);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,2,STYLE_DASHDOTDOT);
//---   
   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[])
  {
//---- checking the number of bars for sufficiency for calculation
   if(BarsCalculated(RSI_Handle)<rates_total || rates_total<min_rates_total) return(RESET);

//---- оlocal variable declarations
   int to_copy,limit,climit,bar,back,lasthighpos,lastlowpos;
   double curlow,curhigh,lasthigh0=EMPTY_VALUE,lastlow0=EMPTY_VALUE,lasthigh1,lastlow1,val,res;

//---- calculation of the start number limit for the bar recalculation cycle and start initialization of variables
   if(prev_calculated>rates_total || prev_calculated<=0)// check for the first start of the indicator calculation
     {
      limit=rates_total-min_rates_total; // start number for calculating all bars
      lastlow1=-1;
      lasthigh1=-1;
      lastlowpos=-1;
      lasthighpos=-1;
     }
   else
     {
      limit=rates_total-prev_calculated; //start number for calculating new bars
      climit=limit+min_rates_total; // start number for coloring the indicator

      //---- restoring the values of variables
      lastlow0=LASTlow0;
      lasthigh0=LASThigh0;

      lastlow1=LASTlow1;
      lasthigh1=LASThigh1;

      lastlowpos=LASTlowpos+limit;
      lasthighpos=LASThighpos+limit;
     }
    to_copy=limit+1;

//--- copy the newly appeared data into an array
   //if(CopyBuffer(RSI_Handle,0,0,to_copy,RSIBuffer)<=0) return(RESET);
   
   //if(ArrayCopy(RSIBuffer,RSI_Handle,0,0,to_copy)<=0) return(RESET);
   
   for(int i=0;i<to_copy;i++)
   {
     RSIBuffer[i]=iRSI(NULL,0,RSI_period,RSIPrice,i);
   }

//----The first big cycle of indicator calculation
   for(bar=limit; bar>=0 && !IsStopped(); bar--)
     {
      //---- remember the values of variables before runs on the current bar
      if(rates_total!=prev_calculated && bar==0)
        {
         LASTlow0=lastlow0;
         LASThigh0=lasthigh0;
        }
      LowestBuffer[bar]=EMPTY_VALUE;
      HighestBuffer[bar]=EMPTY_VALUE;
      //--- low
      val=RSIBuffer[ArrayMinimum(RSIBuffer,bar,ExtDepth)];
      if(val==lastlow0) val=EMPTY_VALUE;
      else
        {
         lastlow0=val;
         if(RSIBuffer[bar]-val>ExtDeviation) val=EMPTY_VALUE;
         else
           {
            for(back=1; back<=int(ExtBackstep); back++)
              {
               res=LowestBuffer[bar+back];
               if(res!=EMPTY_VALUE && res>val) LowestBuffer[bar+back]=EMPTY_VALUE;
              }
           }
        }
      LowestBuffer[bar]=val;

      //--- high
      val=RSIBuffer[ArrayMaximum(RSIBuffer,bar,ExtDepth)];
      if(val==lasthigh0) val=EMPTY_VALUE;
      else
        {
         lasthigh0=val;
         if(val-RSIBuffer[bar]>ExtDeviation) val=EMPTY_VALUE;
         else
           {
            for(back=1; back<=int(ExtBackstep); back++)
              {
               res=HighestBuffer[bar+back];
               if(res!=EMPTY_VALUE && res<val) HighestBuffer[bar+back]=EMPTY_VALUE;
              }
           }
        }
      HighestBuffer[bar]=val;
     }

//---- The second big cycle of the indicator calculation
   for(bar=limit; bar>=0 && !IsStopped(); bar--)
     {
      //---- remember the values of variables before runs on the current bar
      if(rates_total!=prev_calculated && bar==0)
        {
         LASTlow1=lastlow1;
         LASThigh1=lasthigh1;
         //----
         LASTlowpos=lastlowpos;
         LASThighpos=lasthighpos;
        }

      curlow=LowestBuffer[bar];
      curhigh=HighestBuffer[bar];
      //---
      if(curlow==EMPTY_VALUE && curhigh==EMPTY_VALUE) continue;
      //---
      if(curhigh!=EMPTY_VALUE)
        {
         if(lasthigh1>0)
           {
            if(lasthigh1<curhigh) HighestBuffer[lasthighpos]=EMPTY_VALUE;
            else HighestBuffer[bar]=EMPTY_VALUE;
           }
         //---
         if(lasthigh1<curhigh || lasthigh1<0 || curhigh==EMPTY_VALUE || lasthigh1==EMPTY_VALUE)
           {
            lasthigh1=curhigh;
            lasthighpos=bar;
           }
         lastlow1=-1;
        }
      //----
      if(curlow!=EMPTY_VALUE)
        {
         if(lastlow1>0)
           {
            if(lastlow1>curlow) LowestBuffer[lastlowpos]=EMPTY_VALUE;
            else LowestBuffer[bar]=EMPTY_VALUE;
           }
         //---
         if(curlow<lastlow1 || lastlow1<0 || curlow==EMPTY_VALUE || lastlow1==EMPTY_VALUE)
           {
            lastlow1=curlow;
            lastlowpos=bar;
           }
         lasthigh1=-1;
        }
     }
//----     
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
srh124:

Hi all

I'm converting a code from MQL5 to MQL4. In code, i have faced BarsCalculated() which i need help to convert it to MQL4.
This is the code which computes and draws Zigzag on RSI indicator (=Zigzag with input of RSI values, rather than price values).


MQL4 doesn't have handles and the inbuilt iRSI function gives a value directly. So there is no BarsCalculated() or equivalent in MQL4 

 
Navdeep Singh #:

MQL4 doesn't have handles and the inbuilt iRSI function gives a value directly. So there is no BarsCalculated() or equivalent in MQL4 

So, How is it possible to reproduce that line of code in MQL4?
 
srh124 #:
So, How is it possible to reproduce that line of code in MQL4?

Why you need to reproduce that line?

 
It's not possible because there is no need for it; call the function, get the value.
 

Thanks all

Finally, I can get it to work. In fact, I left alone converting above code to MQL4 and tried changing original version of available zigzag in MT4.

This is my code of Zigzag RSI:

//+------------------------------------------------------------------+
//|                                                    ZigZagRSI.mq4 |
//|                   Copyright 2006-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright "2006-2014, MetaQuotes Software Corp."
#property link      "http://www.mql4.com"
#property strict

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1  Yellow
#property indicator_color2  Red
//---- indicator parameters
input int InpDepth=12;     // Depth
input int InpDeviation=5;  // Deviation
input int InpBackstep=3;   // Backstep
input int InpRSIPeroid=8;   // RSI Period
//---- indicator buffers
double ExtZigzagBuffer[];
double ExtHighBuffer[];
double ExtLowBuffer[];
double RSIBuffer[];
//--- globals
int    ExtLevel=3; // recounting's depth of extremums
double outVal =101.0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(InpBackstep>=InpDepth)
     {
      Print("Backstep cannot be greater or equal to Depth");
      return(INIT_FAILED);
     }
//--- 2 additional buffers
   IndicatorBuffers(4);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
   SetIndexStyle(1,DRAW_SECTION);
//---- indicator buffers
   SetIndexBuffer(0,RSIBuffer);
   SetIndexBuffer(1,ExtZigzagBuffer);
   SetIndexBuffer(2,ExtHighBuffer);
   SetIndexBuffer(3,ExtLowBuffer);
   
   SetIndexEmptyValue(0,outVal);
   SetIndexEmptyValue(1,outVal);
//---- indicator short name
   IndicatorShortName("ZigZag("+string(InpDepth)+","+string(InpDeviation)+","+string(InpBackstep)+")");
//---- initialization done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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    i,limit,counterZ,whatlookfor=0;
   int    back,pos,lasthighpos=0,lastlowpos=0;
   double extremum;
   double curlow=outVal,curhigh=outVal,lasthigh=outVal,lastlow=outVal;
//--- check for history and inputs
   if(rates_total<InpDepth || InpBackstep>=InpDepth)
      return(0);
//--- first calculations
   if(prev_calculated==0)
   {
      limit=InitializeAll();
      for(i=0;i<rates_total;i++)
      {
        RSIBuffer[i]=iRSI(NULL,0,InpRSIPeroid,PRICE_CLOSE,i);
      }
   }   
   else 
     {
      //--- find first extremum in the depth ExtLevel or 100 last bars
      i=counterZ=0;
      while(counterZ<ExtLevel && i<100)
        {
         if(ExtZigzagBuffer[i]!=outVal)
            counterZ++;
         i++;
        }
      //--- no extremum found - recounting all from begin
      if(counterZ==0)
         limit=InitializeAll();
      else
        {
         //--- set start position to found extremum position
         limit=i-1;
         //--- what kind of extremum?
         if(ExtLowBuffer[i]!=outVal) 
           {
            //--- low extremum
            curlow=ExtLowBuffer[i];
            //--- will look for the next high extremum
            whatlookfor=1;
           }
         else
           {
            //--- high extremum
            curhigh=ExtHighBuffer[i];
            //--- will look for the next low extremum
            whatlookfor=-1;
           }
         //--- clear the rest data
         for(i=limit-1; i>=0; i--)  
           {
            ExtZigzagBuffer[i]=outVal;  
            ExtLowBuffer[i]=outVal;
            ExtHighBuffer[i]=outVal;
           }
        }
     }
//--- main loop      
   for(i=limit; i>=0; i--)
     {
      //--- find lowest low in depth of bars
      //int index1 = ArrayMinimum(RSIBuffer,InpDepth,i);
      extremum=RSIBuffer[ArrayMinimum(RSIBuffer,InpDepth,i)]; //low[iLowest(NULL,0,MODE_LOW,InpDepth,i)];
      //--- this lowest has been found previously
      if(extremum==lastlow)
         extremum=outVal;
      else 
        { 
         //--- new last low
         lastlow=extremum; 
         //--- discard extremum if current low is too high
         if(RSIBuffer[i]-extremum>InpDeviation*Point)
            extremum=outVal;
         else
           {
            //--- clear previous extremums in backstep bars
            for(back=1; back<=InpBackstep; back++)
              {
               pos=i+back;
               if(ExtLowBuffer[pos]!=0 && ExtLowBuffer[pos]>extremum)
                  ExtLowBuffer[pos]=outVal; 
              }
           }
        } 
      //--- found extremum is current low
      if(RSIBuffer[i]==extremum)
         ExtLowBuffer[i]=extremum;
      else
         ExtLowBuffer[i]=outVal;
      //--- find highest high in depth of bars
      extremum=RSIBuffer[ArrayMaximum(RSIBuffer,InpDepth,i)]; //high[iHighest(NULL,0,MODE_HIGH,InpDepth,i)];
      //--- this highest has been found previously
      if(extremum==lasthigh)
         extremum=outVal;
      else 
        {
         //--- new last high
         lasthigh=extremum;
         //--- discard extremum if current high is too low
         if(extremum-RSIBuffer[i]>InpDeviation*Point)
            extremum=outVal;
         else
           {
            //--- clear previous extremums in backstep bars
            for(back=1; back<=InpBackstep; back++)
              {
               pos=i+back;
               if(ExtHighBuffer[pos]!=0 && ExtHighBuffer[pos]<extremum)
                  ExtHighBuffer[pos]=outVal; 
              } 
           }
        }
      //--- found extremum is current high
      if(RSIBuffer[i]==extremum)
         ExtHighBuffer[i]=extremum;
      else
         ExtHighBuffer[i]=outVal;
     }
//--- final cutting 
   if(whatlookfor==0)
     {
      lastlow=outVal;
      lasthigh=outVal;  
     }
   else
     {
      lastlow=curlow;
      lasthigh=curhigh;
     }
   for(i=limit; i>=0; i--)
     {
      switch(whatlookfor)
        {
         case 0: // look for peak or lawn 
            if(lastlow==outVal && lasthigh==outVal)
              {
               if(ExtHighBuffer[i]!=outVal)
                 {
                  lasthigh=RSIBuffer[i];
                  lasthighpos=i;
                  whatlookfor=-1;
                  ExtZigzagBuffer[i]=lasthigh;
                 }
               if(ExtLowBuffer[i]!=outVal)
                 {
                  lastlow=RSIBuffer[i];
                  lastlowpos=i;
                  whatlookfor=1;
                  ExtZigzagBuffer[i]=lastlow;
                 }
              }
             break;  
         case 1: // look for peak
            if(ExtLowBuffer[i]!=outVal && ExtLowBuffer[i]<lastlow && ExtHighBuffer[i]==outVal)
              {
               ExtZigzagBuffer[lastlowpos]=outVal;
               lastlowpos=i;
               lastlow=ExtLowBuffer[i];
               ExtZigzagBuffer[i]=lastlow;
              }
            if(ExtHighBuffer[i]!=outVal && ExtLowBuffer[i]==outVal)
              {
               lasthigh=ExtHighBuffer[i];
               lasthighpos=i;
               ExtZigzagBuffer[i]=lasthigh;
               whatlookfor=-1;
              }   
            break;               
         case -1: // look for lawn
            if(ExtHighBuffer[i]!=outVal && ExtHighBuffer[i]>lasthigh && ExtLowBuffer[i]==outVal)
              {
               ExtZigzagBuffer[lasthighpos]=outVal;
               lasthighpos=i;
               lasthigh=ExtHighBuffer[i];
               ExtZigzagBuffer[i]=lasthigh;
              }
            if(ExtLowBuffer[i]!=outVal && ExtHighBuffer[i]==outVal)
              {
               lastlow=ExtLowBuffer[i];
               lastlowpos=i;
               ExtZigzagBuffer[i]=lastlow;
               whatlookfor=1;
              }   
            break;               
        }
     }
//--- done
   string tt;
   for(i=0; i<=100; i++)
   {
     
      if (ExtZigzagBuffer[i]!=outVal)
      {
         tt += i + "-" + ExtZigzagBuffer[i]+ "; ";
      }
   }
   Comment(tt);
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int InitializeAll()
  {
   ArrayInitialize(ExtZigzagBuffer,outVal);
   ArrayInitialize(ExtHighBuffer,outVal);
   ArrayInitialize(ExtLowBuffer,outVal);
//--- first counting position
   return(Bars-InpDepth);
  }
//+------------------------------------------------------------------+