//+------------------------------------------------------------------+
//| fatl adaptive smoother
//|
//+------------------------------------------------------------------+
//------------------------------------------------------------------
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"
//------------------------------------------------------------------

#property indicator_separate_window
#property indicator_buffers    5
#property indicator_color1     Blue
#property indicator_color2     Magenta
#property indicator_color3     Yellow  
#property indicator_color4     Red
#property indicator_color5     DarkSlateGray
#property indicator_width1     4
#property indicator_width2     4
#property indicator_width5     2
#property indicator_levelcolor SlateBlue

//
//
//
//
//

extern int SmoothLength = 1;
extern int SignalPeriod = 5;
extern int SignalMethod = MODE_LWMA;

//
//
//
//
//

double jfatl[];
double diff[];
double diffhuu[];
double diffhdd[];
double slope[];
double trend[];
double upArr[];
double dnArr[];

//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,diffhuu); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,diffhdd); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,upArr);   SetIndexStyle(2,DRAW_ARROW); SetIndexArrow(2,233);
   SetIndexBuffer(3,dnArr);   SetIndexStyle(3,DRAW_ARROW); SetIndexArrow(3,234);
   SetIndexBuffer(4,diff);
   SetIndexBuffer(5,jfatl);
   SetIndexBuffer(6,slope);
   SetIndexBuffer(7,trend);
   SetLevelValue(0,0);
   IndicatorShortName("Fatl Smoother Slope Speed"); 

return(0);
}
//+------------------------------------------------------------------+
//| FATL |
//+------------------------------------------------------------------+
int start()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
           int limit=MathMin(Bars-counted_bars,Bars-1);
       
   //
   //
   //
   //
   //

   for (int i=limit; i>=0; i--)
   {
      double fatl = +0.4360409450*Close[i+0]  +0.3658689069*Close[i+1]  +0.2460452079*Close[i+2]  +0.1104506886*Close[i+3]  -0.0054034585*Close[i+4]
                    -0.0760367731*Close[i+5]  -0.0933058722*Close[i+6]  -0.0670110374*Close[i+7]  -0.0190795053*Close[i+8]  +0.0259609206*Close[i+9]
                    +0.0502044896*Close[i+10] +0.0477818607*Close[i+11] +0.0249252327*Close[i+12] -0.0047706151*Close[i+13] -0.0272432537*Close[i+14]
                    -0.0338917071*Close[i+15] -0.0244141482*Close[i+16] -0.0055774838*Close[i+17] +0.0128149838*Close[i+18] +0.0226522218*Close[i+19] 
                    +0.0208778257*Close[i+20] +0.0100299086*Close[i+21] -0.0036771622*Close[i+22] -0.0136744850*Close[i+23] -0.0160483392*Close[i+24]
                    -0.0108597376*Close[i+25] -0.0016060704*Close[i+26] +0.0069480557*Close[i+27] +0.0110573605*Close[i+28] +0.0095711419*Close[i+29]
                    +0.0040444064*Close[i+30] -0.0023824623*Close[i+31] -0.0067093714*Close[i+32] -0.0072003400*Close[i+33] -0.0047717710*Close[i+34]
                    +0.0005541115*Close[i+35] +0.0007860160*Close[i+36] +0.0130129076*Close[i+37] +0.0040364019*Close[i+38];
                    jfatl[i] = iSmooth(fatl,SmoothLength,i,0);
                    diff[i]  = jfatl[i]-jfatl[i+1];
                    
                    //
                    //
                    //
                    //
                    //
                    
                    diffhuu[i] = EMPTY_VALUE;
                    diffhdd[i] = EMPTY_VALUE;     
                    slope[i]   = slope[i+1];
                      if (diff[i] > diff[i+1]) slope[i] =  1;
                      if (diff[i] < diff[i+1]) slope[i] = -1;
                      if (slope[i]== 1) diffhuu[i] = diff[i];
                      if (slope[i]==-1) diffhdd[i] = diff[i];
                      
                      //
                      //
                      //
                      //
                      //
                      
                      trend[i] = trend[i+1];  
                         if (diff[i] > 0) trend[i] =  1;
                         if (diff[i] < 0) trend[i] = -1;
                         
                         //
                         //
                         //
                         //
                         //
                         
                         upArr[i] = EMPTY_VALUE;
                         dnArr[i] = EMPTY_VALUE;
                         if (trend[i] !=trend[i+1])
                         if (trend[i] == 1)
                               upArr[i] = diff[i] - iATR(NULL,0,20,i)/2.0;
                         else  dnArr[i] = diff[i] + iATR(NULL,0,20,i)/2.0; 
                      
                          
      }
  return(0);
  }
   
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workSmooth[][5];
double iSmooth(double price, double length, int r, int instanceNo=0)
{
   if (ArrayRange(workSmooth,0)!=Bars) ArrayResize(workSmooth,Bars); instanceNo *= 5; r = Bars-r-1;
 	if(r<=2) { workSmooth[r][instanceNo] = price; workSmooth[r][instanceNo+2] = price; workSmooth[r][instanceNo+4] = price; return(price); }
   
   //
   //
   //
   //
   //
   
	double alpha = 0.45*(length-1.0)/(0.45*(length-1.0)+2.0);
   	  workSmooth[r][instanceNo+0] =  price+alpha*(workSmooth[r-1][instanceNo]-price);
	     workSmooth[r][instanceNo+1] = (price - workSmooth[r][instanceNo])*(1-alpha)+alpha*workSmooth[r-1][instanceNo+1];
	     workSmooth[r][instanceNo+2] =  workSmooth[r][instanceNo+0] + workSmooth[r][instanceNo+1];
	     workSmooth[r][instanceNo+3] = (workSmooth[r][instanceNo+2] - workSmooth[r-1][instanceNo+4])*MathPow(1.0-alpha,2) + MathPow(alpha,2)*workSmooth[r-1][instanceNo+3];
	     workSmooth[r][instanceNo+4] =  workSmooth[r][instanceNo+3] + workSmooth[r-1][instanceNo+4]; 
   return(workSmooth[r][instanceNo+4]);
}