//+------------------------------------------------------------------+
//|                                                    MACD tape.mq5 |
//|                                                 Copyright mladen |
//|                                               mladenfx@gmail.com |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"
#property version   "1.00"


#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   1

//
//
//
//
//

#property indicator_label1  "MACD tape"
#property indicator_type1   DRAW_FILLING
#property indicator_color1  Green,Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//
//
//
//
//

input int                FastEMA   = 12;          // MACD fast EMA period
input int                SlowEMA   = 26;          // MACD slow EMA period
input int                SignalEMA =  9;          // Signal EMA period
input ENUM_APPLIED_PRICE Price     = PRICE_CLOSE; // Aplied price

//
//
//
//
//

double macd[];
double signal[];
double fastMA[];
double slowMA[];

int FastMaHandle;
int SlowMaHandle;


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

int OnInit()
{
   SetIndexBuffer(0,macd  ,INDICATOR_DATA);         ArraySetAsSeries(macd  ,true);
   SetIndexBuffer(1,signal,INDICATOR_DATA);         ArraySetAsSeries(signal,true);
   SetIndexBuffer(2,fastMA,INDICATOR_CALCULATIONS); ArraySetAsSeries(fastMA,true);
   SetIndexBuffer(3,slowMA,INDICATOR_CALCULATIONS); ArraySetAsSeries(slowMA,true);

   //
   //
   //
   //
   //
   
   IndicatorSetString(INDICATOR_SHORTNAME,"MACD tape ("+(string)FastEMA+","+(string)SlowEMA+","+(string)SignalEMA+")");
   
   FastMaHandle=iMA(NULL,0,FastEMA,0,MODE_EMA,Price);
   SlowMaHandle=iMA(NULL,0,SlowEMA,0,MODE_EMA,Price);
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

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<SlowEMA)                                  return(0);
      if (!checkCalculated(FastMaHandle,rates_total,"fast MA")) return(0);
      if (!checkCalculated(SlowMaHandle,rates_total,"slow MA")) return(0);
   
         int to_copy;
            if(prev_calculated>rates_total || prev_calculated<0) to_copy=rates_total;
            else
            {
               to_copy=rates_total-prev_calculated;
               if(prev_calculated>0) to_copy++;
            }
            
      if (!doCopy(FastMaHandle,fastMA,0,to_copy,"fast MA buffer")) return(0);
      if (!doCopy(SlowMaHandle,slowMA,0,to_copy,"slow MA buffer")) return(0);
   

   //
   //
   //
   //
   //
   
      double alpha = 2.0/(1.0+SignalEMA);
      int    limit = rates_total-prev_calculated;;
         
            if (prev_calculated > 0) limit++;
            if (prev_calculated ==0)
            {
               limit -= 2;
                  for (int i=1; i<=SignalEMA; i++) signal[rates_total-i] = 0;
            }
   //
   //
   //
   //
   //
   
   for (int i=limit; i>=0; i--) { macd[i] = fastMA[i]-slowMA[i]; signal[i] = signal[i+1]+alpha*(macd[i]-signal[i+1]);}
   return(rates_total);
}


  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

bool checkCalculated(int bufferHandle, int total, string checkDescription)
{
   int calculated=BarsCalculated(bufferHandle);
   if (calculated<total)
   {
      Print("Not all data of "+checkDescription+" is calculated (",calculated,"bars ). Error",GetLastError());
      return(false);
   }
   return(true);
}

//
//
//
//
//

bool doCopy(int bufferHandle, double& buffer[], const int buffNum, const int copyCount, string copyDescription)
{
   if(CopyBuffer(bufferHandle,buffNum,0,copyCount,buffer)<=0)
   {
      Print("Getting "+copyDescription+" failed! Error",GetLastError());
      return(false);
   }
   return(true);
}
