//+------------------------------------------------------------------+
//|                                                     AG_Renko.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   3
//--- plot Direct
#property indicator_label1  "Renko"
#property indicator_label2  "Renko"
#property indicator_label3  "Close"
//#property indicator_color1  clrYellow
#property indicator_color1  clrRoyalBlue
#property indicator_color2  clrRed
#property indicator_color3  clrSilver

//--- indicator buffers
double         Direct[];
double         Status[];
double         Renko[];
double         RenkoUP[];
double         RenkoDN[];
double         CLOSE[];

input int Step=250;
double step;
int TF=0;
      double Lewel; // Круглый текущий уровень
      double LewelX; // Последний круглый уровень в движении ренко
      double xmax;   // Круглый уровень верхний
      double xmin;    //Круглый уровень нижний
      double xrew;   // Круглый уровень для реверса

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   
   IndicatorBuffers(6);
//--- indicator buffers mapping


//   Буферы для вывода ренко
   SetIndexBuffer(5,Renko);
   SetIndexStyle(5,DRAW_NONE,STYLE_SOLID,3,clrYellow);
   SetIndexBuffer(0,RenkoUP);
   SetIndexStyle(0,DRAW_LINE,STYLE_SOLID,3,clrRoyalBlue);
   SetIndexBuffer(1,RenkoDN);
   SetIndexStyle(1,DRAW_LINE,STYLE_SOLID,3,clrRed);
   SetIndexBuffer(2,CLOSE);
   SetIndexStyle(2,DRAW_ARROW,STYLE_SOLID,1,clrSilver);
   SetIndexArrow(2,224);
   
// Буфер направления
   SetIndexBuffer(3,Direct);
   SetIndexStyle(3,DRAW_NONE);
// Буфер накопления   
   SetIndexBuffer(4,Status);
   SetIndexStyle(4,DRAW_NONE);
//   SetIndexEmptyValue(0,0);
   
//---
   step=Step*Point; // Пересчет кубика из пунктов в приращение цены
   IndicatorShortName(_Symbol+" RencoChart TF="+(string)Period());
   IndicatorDigits(Digits);
   
   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[])
  {
//---
      
// Считаем от первого доступного бара
      
      int limit=Bars-2;
      double c=0; // Цена закрытия
      
      if (prev_calculated==0) //Считаем от начала при запуске индикатора
      {
         c=iClose(_Symbol,TF,Bars-1);
         Direct[Bars-1]=1;
         Lewel=NormalizeDouble(MathRound(c/step)*step,Digits);
         Status[Bars-1]=0;
         xmax=NormalizeDouble(Lewel+step,Digits);
         xmin=NormalizeDouble(Lewel-step,Digits);
         xrew=NormalizeDouble(Lewel-2*step,Digits);
      }
      else limit=1;//Bars-2;

// 
      ArrayInitialize(CLOSE,EMPTY_VALUE);
      for (int i=limit;i>=1;i--)
      {
         c=iClose(_Symbol,TF,i);
         CLOSE[0]=c;
         Lewel=NormalizeDouble(MathRound(c/step)*step,Digits);
         Direct[i]=Direct[i+1];
         Status[i]=Status[i+1];

         if (Direct[i]>0) //Текущий тренд вверх - кирпичики прибавляются вверх
         { 
            if (c>=xmax)
            {
               if (Lewel>LewelX) LewelX=Lewel; // Ренко увеличивается
               if (Lewel>xmax) //Пробой вверх по тренду
               {
                  Status[i]=Status[i+1]+MathRound((Lewel-xmax)/step);
                  xmax=NormalizeDouble(Lewel,Digits);
               }
               xmin=NormalizeDouble(xmax-step,Digits);
               xrew=NormalizeDouble(xmax-2*step,Digits);

            }
            
            if (c<=xrew) //Пробой вниз против тренда
            {
               LewelX=Lewel; //Ренко переворачивается
               Direct[i]=-1;
               xmin=NormalizeDouble(Lewel,Digits);
               xmax=NormalizeDouble(xmin+step,Digits);
               xrew=NormalizeDouble(xmin+2*step,Digits);
               Status[i]=Status[i+1]-2;
            }
         }

         else if (Direct[i]<0) //Текущий тренд вниз - кирпичики прибавляются вниз
         { 
            if (c<=xmin)
            {
               if (Lewel<LewelX) LewelX=Lewel; // Ренко уменьшается
               if (Lewel<xmin) //Пробой вниз по тренду
               {
                  Status[i]=Status[i+1]+MathRound((Lewel-xmin)/step);
                  xmin=NormalizeDouble(Lewel,Digits);
               }
               xmax=NormalizeDouble(xmin+step,Digits);
               xrew=NormalizeDouble(xmin+2*step,Digits);
            }
            if (c>=xrew)
            {
               LewelX=Lewel; //Ренко переворачивается
               Direct[i]=1; //Пробой вверх против тренда
               xmax=NormalizeDouble(Lewel,Digits);
               xmin=NormalizeDouble(xmax-step,Digits);
               xrew=NormalizeDouble(xmax-2*step,Digits);
               Status[i]=Status[i+1]+2;
            }
         }

      }

      Status[0]=Status[1];
// Буферы направления и накопительный посчитаны, рассчитаем ренко
// Считаем справа налево по текущему графику

//return(0);

      ArrayInitialize(Renko,EMPTY_VALUE);
      ArrayInitialize(RenkoUP,EMPTY_VALUE);
      ArrayInitialize(RenkoDN,EMPTY_VALUE);
      
      Renko[0]=LewelX;RenkoUP[0]=LewelX;RenkoDN[0]=LewelX; //Ренко на правом краю
      int j=0; int i=1; 
      
      string s="";
      while (j<200 && i<Bars-1) // задано 200 кирпичиков ренко и контроль, чтобы хватило баров
      {
         int k=(int)MathRound(Status[i]-Status[i-1]); //Приращение в накопительном буфере
         if (k==0) {i++;continue;} //Если накопительный буфер не поменялся - ничего не делаем
         
         int l=0;
         if (k<0) l=-1;if (k>0) l=1; //Направление приращения в накопительном буфере
         k=MathAbs(k);
          
         // Чтобы не было разрывов на индикаторе   
            if (l<0) RenkoUP[j]= Renko[j];
            if (l>0) RenkoDN[j]= Renko[j];
         
         for (int n=1;n<=k;n++) // Размер приращения в буфере переведем в количество кирпичиков
         {
            j++;
            Renko[j]=Renko[j-1]+l*step;
            if (l<0) RenkoUP[j]= Renko[j];
            if (l>0) RenkoDN[j]= Renko[j];
//            s=s+"  "+(string)j+"  "+(string)Renko[j]+"  "+(string)k+"  "+i+"\n";
         }
         i++;
      }

// Для сведения - сколько баров на графике, сколько использовано для расчета ренко, сколько получилось кирпичиков
//Comment (s);
Comment ("TotalBars=",Bars, "  UsedBars=",i, "  RencoBars=",j);

// Отрисовка уровней в индикаторе
      SetLevelStyle(STYLE_DOT,0,clrDimGray);

      SetLevelValue(0,Lewel);
      for (i=1;i<=15;i++)
      {
         SetLevelValue(i,Lewel+i*step);
         SetLevelValue(i+15,Lewel-i*step);
      }


//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
