//+------------------------------------------------------------------+
//|   AdaptiveLaguerreFilter.mq4
//|
//+------------------------------------------------------------------+
#property indicator_chart_window
#include <stdlib.mqh>
#property indicator_buffers 6
#property indicator_color1 DodgerBlue

extern int LookBack = 20;
extern int Median = 5;
extern int PriceType = PRICE_MEDIAN;
extern color Color1 = DodgerBlue;
extern bool alpha_with_average = false;
extern int MaxBars = 50000;

int ZeroCount;
int i,j;
double Price,HH,LL;
double alpha;

double Filter[];
double Diff[];
double L0[];
double L1[];
double L2[];
double L3[];

double sortDiff[];

int init() 
{

   IndicatorBuffers(6);

   SetIndexBuffer(0,Filter);
   //SetIndexStyle(0,DRAW_LINE,0,2,Color1);
   SetIndexLabel(0,"ALF");

   SetIndexBuffer(1,Diff);
   SetIndexStyle(1,DRAW_NONE);

   SetIndexBuffer(2,L0);
   SetIndexStyle(2,DRAW_NONE);

   SetIndexBuffer(3,L1);
   SetIndexStyle(3,DRAW_NONE);

   SetIndexBuffer(4,L2);
   SetIndexStyle(4,DRAW_NONE);

   SetIndexBuffer(5,L3);
   SetIndexStyle(5,DRAW_NONE);

   ArrayResize(sortDiff,Median);
      
   return (0);
}
  

int start()
{
   int countedBars = IndicatorCounted();
   int limit = Bars-countedBars-1;
   if (MaxBars==0) MaxBars=200;
   if (limit>MaxBars) limit=MaxBars;
   
   for (i=limit;i>=0;i--)
   {
      Price = iMA(NULL,0,1,0,MODE_SMA,PriceType,i);

      Diff[i] = MathAbs(Price - Filter[i+1]);

      HH = Diff[i];
      LL = Diff[i];

      for (j=0;j<LookBack;j++)
      {
         if (Diff[i+j] > HH)
         {HH = Diff[i+j];}
         
         if (Diff[i+j] < LL)
         {LL = Diff[i+j];}
      }

      if (!CompareDoubles(HH-LL,0))
      {
       if (!alpha_with_average) {
         for (int j=0;j<Median;j++)
         {
            sortDiff[j] = (Diff[i+j] - LL) / (HH - LL);
         }
         ArraySort(sortDiff,WHOLE_ARRAY,0,MODE_ASCEND);
         if (MathMod(Median,2.0) != 0)
         {
            alpha = sortDiff[Median/2];         
         }
         else
         {
            alpha = (sortDiff[Median/2]+sortDiff[(Median/2)-1])/2;
         }   

        } else {
         double sum=0;
         for (j=0;j<Median;j++) sum += (Diff[i+j] - LL);
         alpha = sum / (HH - LL) / Median;
        }
      }
      
      L0[i] = alpha*Price + (1 - alpha)*L0[i+1];
      L1[i] = -(1 - alpha)*L0[i] + L0[i+1] + (1 - alpha)*L1[i+1];
      L2[i] = -(1 - alpha)*L1[i] + L1[i+1] + (1 - alpha)*L2[i+1];
      L3[i] = -(1 - alpha)*L2[i] + L2[i+1] + (1 - alpha)*L3[i+1];
      Filter[i] = (L0[i] + 2.0 * L1[i] + 2.0 * L2[i] + L3[i]) / 6.0;
      
   }
      
   return (0);   
}



