//+------------------------------------------------------------------+
//|                                              UniMACD_v2 600+.mq4 |
//|                                Copyright © 2014, TrendLaboratory |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
// List of Prices:
// Price    = 0 - Close  
// Price    = 1 - Open  
// Price    = 2 - High  
// Price    = 3 - Low  
// Price    = 4 - Median Price   = (High+Low)/2  
// Price    = 5 - Typical Price  = (High+Low+Close)/3  
// Price    = 6 - Weighted Close = (High+Low+Close*2)/4

 
#property copyright "Copyright © 2014, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Maroon
#property indicator_color3 LimeGreen
#property indicator_color4 Green
#property indicator_color5 DimGray
#property indicator_color6 Yellow
#property indicator_color7 DimGray
#property indicator_width1 2
#property indicator_width2 1
#property indicator_width3 2
#property indicator_width4 1
#property indicator_width5 1
#property indicator_width6 1
#property indicator_style6 2  
#property indicator_width7 1

#property indicator_level1 0
#property indicator_levelcolor DimGray
//---- 

extern int     TimeFrame             =   0;   //TimeFrame in min
extern int     FastPrice             =   0;   //Fast Price Mode (0...6)
extern int     FastLength            =  12;   //Fast Period of smoothing
extern int     FastPole              =   2;   //Fast Pole: 1-EMA(1 pole),2-DEMA(2 poles),3-TEMA(3 poles),4-QEMA(4 poles)...
extern int     FastOrder             =   1;   //Fast Smoothing Order(min. 1)
extern double  FastWeightFactor      =   2;   //Fast Weight Factor (ex.Wilder=1,EMA=2)   
extern double  FastDampingFactor     =   1;   //Fast Damping Factor

extern int     SlowPrice             =   0;   //Slow Price Mode (0...6)
extern int     SlowLength            =  24;   //Slow Period of smoothing
extern int     SlowPole              =   2;   //Slow Pole: 1-EMA(1 pole),2-DEMA(2 poles),3-TEMA(3 poles),4-QEMA(4 poles)...
extern int     SlowOrder             =   1;   //Slow Smoothing Order(min. 1)
extern double  SlowWeightFactor      =   2;   //Slow Weight Factor (ex.Wilder=1,EMA=2)   
extern double  SlowDampingFactor     =   1;   //Slow Damping Factor

extern int     SignalLength          =   1;   //Signal Period(<1 - off)  
extern int     OscillatorMode        =   0;   //0-off,1-on 



double DnBuffer1[];
double DnBuffer2[];
double UpBuffer1[];
double UpBuffer2[];
double Diff[];
double Signal[];
double Osc[];
double trend[];

double uniema_tmp[][2];
int    uniema_prevtime[], uniema_size;
string IndicatorName, TF;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
{
   if(TimeFrame <= Period()) TimeFrame = Period();
   IndicatorDigits(Digits+2);
   IndicatorBuffers(8);
   
   SetIndexBuffer(0,DnBuffer1); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,DnBuffer2); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,UpBuffer1); SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(3,UpBuffer2); SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(4,     Diff); SetIndexStyle(4,DRAW_LINE);
   SetIndexBuffer(5,   Signal); SetIndexStyle(5,DRAW_LINE); 
   SetIndexBuffer(6,      Osc); SetIndexStyle(6,DRAW_LINE);
   SetIndexBuffer(7,    trend);
   
   switch(TimeFrame)
   {
   case 1     : TF = "M1" ; break;
   case 5     : TF = "M5" ; break;
   case 15    : TF = "M15"; break;
   case 30    : TF = "M30"; break;
   case 60    : TF = "H1" ; break;
   case 240   : TF = "H4" ; break;
   case 1440  : TF = "D1" ; break;
   case 10080 : TF = "W1" ; break;
   case 43200 : TF = "MN1"; break;
   } 
     
   
   IndicatorName = WindowExpertName();
   
   IndicatorShortName(IndicatorName+"["+TF+"]("+FastLength+","+SlowLength+")");
   SetIndexLabel(0,"DnTrend Increasing");
   SetIndexLabel(1,"DnTrend Decreasing");
   SetIndexLabel(2,"UpTrend Increasing");
   SetIndexLabel(3,"UpTrend Decreasing");
   SetIndexLabel(4,"UniMACD");   
   SetIndexLabel(5,"UniMACD Signal");
   SetIndexLabel(6,"UniMACD Oscillator");  
   
   SetIndexDrawBegin(0,2);
   SetIndexDrawBegin(1,2);
   SetIndexDrawBegin(2,2);
   SetIndexDrawBegin(3,2);
   SetIndexDrawBegin(4,2);
    
   uniema_size = MathMax(MathMax(FastPole,SlowPole),2)*MathMax(MathMax(FastOrder,SlowOrder),3);   
   ArrayResize(uniema_tmp,uniema_size*4);
   ArrayResize(uniema_prevtime,4);
   
   
   
   return(0);
}
//-----
int deinit()
{
   Comment("");
   return(0);
}


//+------------------------------------------------------------------+
//|  UniMACD_v2                                                      |
//+------------------------------------------------------------------+

int start()
{
   int shift,limit, counted_bars=IndicatorCounted();
      
   if (counted_bars > 0)  limit=Bars-counted_bars-1;
   if (counted_bars < 0)  return(0);
   if (counted_bars < 1)
   { 
   limit = Bars-1;   
      for(int i=limit;i>=0;i--) 
      {
      UpBuffer1[i] = EMPTY_VALUE;
      UpBuffer2[i] = EMPTY_VALUE;
      DnBuffer1[i] = EMPTY_VALUE;
      DnBuffer2[i] = EMPTY_VALUE;
      Signal   [i] = EMPTY_VALUE;
      Diff     [i] = EMPTY_VALUE;
      Osc      [i] = EMPTY_VALUE;
      }
   }   
   
   if(TimeFrame != Period())
   {
   limit = MathMax(limit,TimeFrame/Period());   
      
      for(shift = 0;shift < limit;shift++) 
      {	
      int y = iBarShift(NULL,TimeFrame,Time[shift]);
	   
	   DnBuffer1[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,0,y);
      DnBuffer2[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,1,y);
	   UpBuffer1[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,2,y);
      UpBuffer2[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,3,y);
      Diff[shift]      = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,4,y);
	   Signal[shift]    = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,5,y);
	   Osc[shift]       = iCustom(NULL,TimeFrame,IndicatorName,0,FastPrice,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,
	                              SlowPrice,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,SignalLength,OscillatorMode,6,y);
	   }
	
	return(0);
	}
   else UniMACD(limit);
   
   
   
   return(0);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

void UniMACD(int limit)
{
      
   for(int shift=limit;shift>=0;shift--) 
   {
   double f_price = iMA(NULL,0,1,0,0,FastPrice,shift);
   double s_price = iMA(NULL,0,1,0,0,SlowPrice,shift);  
       
   double fastUniEMA = UniXMA(0,f_price,FastLength,FastPole,FastOrder,FastWeightFactor,FastDampingFactor,shift);  
   double slowUniEMA = UniXMA(1,s_price,SlowLength,SlowPole,SlowOrder,SlowWeightFactor,SlowDampingFactor,shift); 
   
   Diff[shift] = fastUniEMA - slowUniEMA;
   
      if(SignalLength > 0) 
      {
      if(SignalLength >  1) Signal[shift] = UniXMA(2,Diff[shift],SignalLength,2,1,2,0.7,shift);
      if(SignalLength == 1) Signal[shift] = Diff[shift+1];
      }
   
       
   if(OscillatorMode == 1) Osc[shift] = Diff[shift] - Signal[shift]; else Osc[shift] = EMPTY_VALUE;
   
   UpBuffer1[shift] = EMPTY_VALUE;
   UpBuffer2[shift] = EMPTY_VALUE;
   DnBuffer1[shift] = EMPTY_VALUE;
   DnBuffer2[shift] = EMPTY_VALUE;
   
   
   trend[shift] = trend[shift+1];
   
      if(OscillatorMode == 0)
      {    
      if(Diff[shift] > Diff[shift+1]) trend[shift] =  1;
      if(Diff[shift] < Diff[shift+1]) trend[shift] = -1;
   
         if(Diff[shift] > 0)
            if(trend[shift] > 0) UpBuffer1[shift] = Diff[shift];
            else  UpBuffer2[shift] = Diff[shift];
         else               
            if(trend[shift] > 0) DnBuffer2[shift] = Diff[shift];
            else  DnBuffer1[shift] = Diff[shift];
      }
      else
      {
      if(Osc[shift] > Osc[shift+1]) trend[shift] =  1;
      if(Osc[shift] < Osc[shift+1]) trend[shift] = -1;
   
         if(Osc[shift] > 0)
            if(trend[shift] > 0) UpBuffer1[shift] = Osc[shift];
            else  UpBuffer2[shift] = Osc[shift];
         else               
            if(trend[shift] > 0) DnBuffer2[shift] = Osc[shift];
            else  DnBuffer1[shift] = Osc[shift];
      }     
   }
}

//------

double UniXMA(int index,double price,int len,int Pole,int order,double wf,double df,int bar)
{
   int m = index*uniema_size; 
   double alpha = (wf*order)/(len + wf*order-1); 
         
   if(uniema_prevtime[index] != Time[bar])
   {
   for(int k=0;k<order;k++) 
      for(int j=0;j<Pole;j++) uniema_tmp[m+Pole*k+j][1] = uniema_tmp[m+Pole*k+j][0];
   
   uniema_prevtime[index] = Time[bar];
   }
   
   if(bar >= Bars-2) 
   {
   for(k=0;k<order;k++) 
      for(j=0;j<Pole;j++) uniema_tmp[m+Pole*k+j][0] = price; 
   }
   else  
   {
      for(k=0;k<order;k++)
      {
         for(j=0;j<Pole;j++)
         {   
         uniema_tmp[m+Pole*k+j][0] = (1 - alpha)*uniema_tmp[m+Pole*k+j][1] + alpha*price; 
         if(j > 0) price = price + df*(uniema_tmp[m+Pole*k][0] - uniema_tmp[m+Pole*k+j][0]);
         else price = uniema_tmp[m+Pole*k+j][0];
         }
      }   
   }
   
   return(price); 
}
   