//+------------------------------------------------------------------+
//|                                                  DemoBuffers.mq5 |
//|                                                      Bohdan Klok |
//|                             https://www.mql5.com/en/users/kbposht |
//+------------------------------------------------------------------+
#property copyright   "Bohdan Klok"
#property link        "https://www.mql5.com/en/users/kbposht"
#property version     "1.00"
#property description "Article example: one indicator with every kind of buffer - a line, arrows,"
#property description "a colour line with its colour index, and a calculation buffer that is not drawn."
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   3
//--- plot 0: a plain line (buffer 0)
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrSilver
#property indicator_width1  1
//--- plot 1: arrows (buffer 1), drawn only where the close crosses the SMA upward
#property indicator_label2  "Cross up"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrDodgerBlue
#property indicator_width2  2
//--- plot 2: a colour line (buffer 2 = value, buffer 3 = colour index)
#property indicator_label3  "Trend EMA"
#property indicator_type3   DRAW_COLOR_LINE
#property indicator_color3  clrSeaGreen,clrOrangeRed
#property indicator_width3  2
//--- input parameters
input int InpSmaPeriod=20;   // SMA period
input int InpEmaPeriod=50;   // EMA period
//--- indicator buffers
double ExtSma[];             // 0: line
double ExtCross[];           // 1: arrows, EMPTY_VALUE where there is none
double ExtEma[];             // 2: colour line value
double ExtEmaColor[];        // 3: colour index, 0 rising, 1 falling
double ExtSlope[];           // 4: calculations, EMA change over one bar
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,ExtSma,INDICATOR_DATA);
   SetIndexBuffer(1,ExtCross,INDICATOR_DATA);
   SetIndexBuffer(2,ExtEma,INDICATOR_DATA);
   SetIndexBuffer(3,ExtEmaColor,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4,ExtSlope,INDICATOR_CALCULATIONS);
   PlotIndexSetInteger(1,PLOT_ARROW,233);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpSmaPeriod);
   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpEmaPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME,StringFormat("DemoBuffers(%d,%d)",InpSmaPeriod,InpEmaPeriod));
   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[])
  {
   if(rates_total<InpEmaPeriod+2)
      return(0);
   const double k=2.0/(InpEmaPeriod+1.0);
   int start=(prev_calculated>1) ? prev_calculated-1 : 1;
   if(prev_calculated==0)
     {
      ExtEma[0]=close[0];
      ExtSlope[0]=0.0;
      ExtEmaColor[0]=0.0;
     }
   for(int i=start; i<rates_total; i++)
     {
      //--- SMA, empty until there are enough bars
      if(i>=InpSmaPeriod-1)
        {
         double sum=0.0;
         for(int j=0; j<InpSmaPeriod; j++)
            sum+=close[i-j];
         ExtSma[i]=sum/InpSmaPeriod;
        }
      else
         ExtSma[i]=EMPTY_VALUE;
      //--- EMA, its slope and the colour of the slope
      ExtEma[i]=ExtEma[i-1]+k*(close[i]-ExtEma[i-1]);
      ExtSlope[i]=ExtEma[i]-ExtEma[i-1];
      ExtEmaColor[i]=(ExtSlope[i]>=0.0) ? 0.0 : 1.0;
      //--- an arrow under the bar where the close crosses the SMA upward
      ExtCross[i]=EMPTY_VALUE;
      if(i>=InpSmaPeriod && ExtSma[i-1]!=EMPTY_VALUE && close[i-1]<ExtSma[i-1] && close[i]>=ExtSma[i])
         ExtCross[i]=low[i];
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+
