//+------------------------------------------------------------------+
//|                                            GaussianFilter_v1.mq4 |
//|                           Copyright © 2008, TrendLaboratory Ltd. |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, TrendLaboratory Ltd."
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"
//---- indicator settings
#property indicator_chart_window 
#property indicator_buffers 3 
#property indicator_color1 Yellow 
#property indicator_color2 LightBlue 
#property indicator_color3 Tomato 
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2 
//---- indicator parameters
extern int     Price          = 0;  //Price mode : 0-Close,1-Open,2-High,3-Low,4-Median,5-Typical,6-Weighted
extern int     Order          = 3;  //Filter Order: 1-1st,2-2nd,3-3rd,4-4th
extern int     FilterPeriod   =14;  //Filter Period 
extern int     PreSmooth      = 1;  //Pre-smoothing period
extern int     PreSmoothMode  = 0;  //Pre-smoothing MA Mode: 0-SMA,1-EMA,2-SMMA,3-LWMA
extern double  PctFilter      = 0;  //Dynamic filter in decimal(multiplier for StdDev)
extern int     ColorMode      = 0;  //Color Mode: 0-off,1-on
extern int     ColorBarBack   = 1;  //Should be 0 or 1 
extern int     AlertMode      = 0;  //Sound Alert switch (0-off,1-on) 
extern int     WarningMode    = 0;  //Sound Warning switch(0-off,1-on) 
//---- indicator buffers
double     Filter[];
double     UpTrend[];
double     DnTrend[];
double     Smoother[];
double     trend[];
double     Del[];
double     AvgDel[];

int        draw_begin;
bool       UpTrendAlert=false, DownTrendAlert=false;
double     pi = 3.1415926535, w, alf, bet;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- indicator buffers mapping
   IndicatorBuffers(7);
   SetIndexBuffer(0,Filter);
   SetIndexBuffer(1,UpTrend);
   SetIndexBuffer(2,DnTrend);
   SetIndexBuffer(3,Smoother);
   SetIndexBuffer(4,trend);  
   SetIndexBuffer(5,Del);
   SetIndexBuffer(6,AvgDel);
//---- drawing settings
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexStyle(2,DRAW_LINE);
   draw_begin = FilterPeriod + PreSmooth;
   SetIndexDrawBegin(0,draw_begin);
   SetIndexDrawBegin(1,draw_begin);
   SetIndexDrawBegin(2,draw_begin);
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+1);
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("GaussianFilter("+Order+","+FilterPeriod+")");
   SetIndexLabel(0,"GaussianFilter");
   SetIndexLabel(1,"UpTrend");
   SetIndexLabel(2,"DnTrend");
//----
   w = 2*pi/FilterPeriod;
	bet = (1 - MathCos(w))/(MathPow(1.414,2.0/Order) - 1);
	alf = -bet + MathSqrt(bet*bet + 2*bet);
//---- initialization done
   return(0);
}
//+------------------------------------------------------------------+
//| GaussianFilter_v1                                                 |
//+------------------------------------------------------------------+
int start()
{
   int limit, i, shift;
   int counted_bars=IndicatorCounted();
   
   
   if(counted_bars<1)
   for(i=1;i<=draw_begin;i++) 
   {
   Filter[Bars-i]=0; 
   UpTrend[Bars-i]=0; 
   DnTrend[Bars-i]=0;
   }
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;

   for(shift=limit; shift>=0; shift--)
   Smoother[shift] = iMA(NULL,0,PreSmooth,0,PreSmoothMode,Price,shift);
   
   for(shift=limit; shift>=0; shift--)
   {
      if(Order == 1) 
      Filter[shift] = alf*Smoother[shift] + (1-alf)*Filter[shift+1];
      else
		if(Order == 2) 
		Filter[shift] = MathPow(alf,2)*Smoother[shift] + 2*(1-alf)*Filter[shift+1] -   MathPow(1-alf,2)*Filter[shift+2];
		else
		if(Order == 3) 
		Filter[shift] = MathPow(alf,3)*Smoother[shift] + 3*(1-alf)*Filter[shift+1] - 3*MathPow(1-alf,2)*Filter[shift+2] + MathPow(1-alf,3)*Filter[shift+3];
		else
		if(Order == 4) 
		Filter[shift] = MathPow(alf,4)*Smoother[shift] + 4*(1-alf)*Filter[shift+1] - 6*MathPow(1-alf,2)*Filter[shift+2] + 4*MathPow(1-alf,3)*Filter[shift+3] - MathPow(1-alf,4)*Filter[shift+4];
		
  
   int Length = FilterPeriod;
      
      if (PctFilter>0)
      {
      Del[shift] = MathAbs(Filter[shift] - Filter[shift+1]);
   
      double sumdel=0;
      for (int j=0;j<=Length-1;j++) sumdel = sumdel+Del[shift+j];
      AvgDel[shift] = sumdel/Length;
    
      double sumpow = 0;
      for (j=0;j<=Length-1;j++) sumpow+=MathPow(Del[j+shift]-AvgDel[j+shift],2);
      double StdDev = MathSqrt(sumpow/Length); 
     
      double filter = PctFilter * StdDev;
     
      if(MathAbs(Filter[shift]-Filter[shift+1]) < filter ) Filter[shift]=Filter[shift+1];
      }
      else
      filter=0;
   
      
      if (ColorMode>0)
      {
         trend[shift] = trend[shift+1];
         if (Filter[shift] - Filter[shift+1] > filter) trend[shift] = 1;
         if (Filter[shift+1] - Filter[shift] > filter) trend[shift] =-1;
    
         if (trend[shift]>0)
         {
            UpTrend[shift] = Filter[shift]; 
            if (trend[shift+ColorBarBack]<0) UpTrend[shift+ColorBarBack]=Filter[shift+ColorBarBack];
            DnTrend[i] = EMPTY_VALUE;
            if (WarningMode>0 && trend[shift+1]<0 && shift==0) PlaySound("alert2.wav");
         }
         else              
         if (trend[shift]<0)
         { 
            DnTrend[shift] = Filter[shift]; 
            if (trend[shift+ColorBarBack]>0) DnTrend[shift+ColorBarBack]=Filter[shift+ColorBarBack];
            UpTrend[shift] = EMPTY_VALUE;
            if (WarningMode>0 && trend[shift+1]>0 && shift==0) PlaySound("alert2.wav");
         }               
      }
   }         
//----------   
   string Message;
   
   if ( trend[2]<0 && trend[1]>0 && Volume[0]>1 && !UpTrendAlert)
	{
	Message = " "+Symbol()+" M"+Period()+": HMA Signal for BUY";
	if ( AlertMode>0 ) Alert (Message); 
	UpTrendAlert=true; DownTrendAlert=false;
	} 
	 	  
	if ( trend[2]>0 && trend[1]<0 && Volume[0]>1 && !DownTrendAlert)
	{
	Message = " "+Symbol()+" M"+Period()+": HMA Signal for SELL";
	if ( AlertMode>0 ) Alert (Message); 
	DownTrendAlert=true; UpTrendAlert=false;
	} 	         
//---- done
   return(0);
}