//+------------------------------------------------------------------+
//|                                             AdvancedAMA_v1.3.mq4 |
//|                             Copyright © 2008-09, TrendLaboratory |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008-09, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 Linen
#property indicator_width1 1
#property indicator_color2 SkyBlue
#property indicator_width2 1
#property indicator_color3 Tomato
#property indicator_width3 1
#property indicator_color4 SkyBlue
#property indicator_width4 2
#property indicator_color5 Tomato
#property indicator_width5 2
//---- input parameters
extern int     Price        =   0;
extern int     AMA_Period   =  20;
extern int     N_fast       =   2;
extern int     N_slow       =  30;
extern int     ER_smooth    =   1;
extern int     ER_mode      =   1;
extern double  SC_power     =   2;
extern double  PctFilter    = 1.0; 
extern int     Color        =   1;  //Switch of Color mode (1-color)
extern int     ColorBarBack =   0;  //Bar back for color mode
extern int     SignalMode   =   2;
extern int     AlertMode    =   0;  //Sound Alert switch 
extern int     WarningMode  =   0;
//---- buffers
double AMA[];
double UpTrend[];
double DnTrend[];
double UpSignal[];
double DnSignal[];
double ER[];
double trend[];
double price[];

double smlRange[], smlSumm[];
bool   UpTrendAlert=false, DnTrendAlert=false;
double lastLo, lastHi;
datetime pTime;  
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   IndicatorBuffers(8);
   
   SetIndexBuffer(0,AMA);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(1,UpTrend);   
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(2,DnTrend);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(3,UpSignal);
   SetIndexStyle(3,DRAW_ARROW);
   SetIndexArrow(3,159);
   SetIndexBuffer(4,DnSignal);
   SetIndexArrow(4,159);
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexBuffer(5,ER);
   SetIndexBuffer(6,trend);
   SetIndexBuffer(7,price);
   
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS+2));
//---- name for DataWindow and indicator subwindow label
   string short_name="AdvancedAMA("+AMA_Period+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"Advanced AMA");
   SetIndexLabel(1,"UpTrend");
   SetIndexLabel(2,"DnTrend");
   SetIndexLabel(3,"UpSignal");
   SetIndexLabel(4,"DnSignal");
//----
   SetIndexDrawBegin(0,AMA_Period+N_slow);
   SetIndexDrawBegin(1,AMA_Period+N_slow);
   SetIndexDrawBegin(2,AMA_Period+N_slow);
   SetIndexDrawBegin(3,AMA_Period+N_slow);
   SetIndexDrawBegin(4,AMA_Period+N_slow);
//----

   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| AdvancedAMA_v1.3                                                 |
//+------------------------------------------------------------------+
int start()
{
   int    i,shift, counted_bars=IndicatorCounted(),limit;
   double direction,noise,SumER,ERsmooth,SC;      
   int FilterPeriod = 20, FDCount = 2;
   
   SetEmulationIndexBuffer(smlRange);
   SetEmulationIndexBuffer(smlSumm);
   
   if ( counted_bars > 0 )  limit=Bars-counted_bars;
   if ( counted_bars < 0 )  return(0);
   if ( counted_bars ==0 )  limit=Bars-1; 
   if ( counted_bars < 1 ) 
   
   for(i=0;i<Bars;i++) 
   {
   AMA[Bars-i] = iMA(NULL,0,1,0,1,Price,i);    
   UpTrend[Bars-i] = iMA(NULL,0,1,0,1,Price,i);  
   DnTrend[Bars-i] = iMA(NULL,0,1,0,1,Price,i);
   ER[Bars-i]=0; 
   price[Bars-i]=iMA(NULL,0,1,0,1,Price,i);
   }
   
   for(shift=limit;shift>=0;shift--) 
   {	
   price[shift]=iMA(NULL,0,1,0,0,Price,shift);   
      if(ER_mode == 0) 
      {
      direction = MathAbs(price[shift]-price[shift+AMA_Period]);	
  
      noise = 0;
      for (i=0;i<=AMA_Period-1;i++)
      noise += MathAbs(price[i+shift]-price[i+shift+1]);  
   
      if (noise==0) noise=0.000001;     
      if (noise>0) ER[shift] = direction/noise;   
      }
      else
      if(ER_mode == 1)
      { 
      ER[shift] = 2 - iFD(AMA_Period,FDCount,shift); 
      if(ER[shift] > 1.0) ER[shift] = 1.0;
      }
      
      SumER=0;
      for (i=0;i<=ER_smooth-1;i++) SumER += ER[shift+i];
      
      ERsmooth = SumER/ER_smooth;
      
      SC = ERsmooth*(2.0/(1.0+N_fast) - 2.0/(1.0+N_slow)) + 2.0/(1.0+N_slow);
   
   AMA[shift] = AMA[shift+1] + MathPow(SC,SC_power)*(price[shift]-AMA[shift+1]);
   
      if (Color>0)
      {
         if (PctFilter>0)
         {
         double sumdel=0;
         for (i=0;i<FilterPeriod;i++) sumdel = sumdel+MathAbs(AMA[shift+i] - AMA[shift+i+1]);
         double AvgDel = sumdel/FilterPeriod;
    
         double sumpow = 0;
         for (i=0;i<FilterPeriod;i++) sumpow+=MathPow(MathAbs(AMA[shift+i] - AMA[shift+i+1])-AvgDel,2);
         double StdDev = MathPow(sumpow/FilterPeriod,0.5); 
     
         double Filter = PctFilter * StdDev;
         }
         else Filter = 0;
           
      trend[shift]=trend[shift+1];
      
      if (AMA[shift]-AMA[shift+1]>Filter && trend[shift+1]<=0) {trend[shift]= 1; lastLo = AMA[shift+1];}
      if (AMA[shift+1]-AMA[shift]>Filter && trend[shift+1]>=0) {trend[shift]=-1; lastHi = AMA[shift+1];} 
            
         if (trend[shift]>0)
         {  
            if (AMA[shift] > AMA[shift+1] && AMA[shift] - lastLo > Filter && lastLo > 0)
            {
            UpTrend[shift] = AMA[shift];
            if (trend[shift+ColorBarBack]<0) UpTrend[shift+ColorBarBack]=AMA[shift+ColorBarBack];
            DnTrend[shift] = EMPTY_VALUE;
            if (SignalMode>0 && AMA[shift+1] - lastLo <= Filter && UpTrend[shift+1]==EMPTY_VALUE) UpSignal[shift] = AMA[shift];
            else UpSignal[shift] = EMPTY_VALUE; 
            if (WarningMode>0 && AMA[1] - lastLo <= Filter && UpTrend[1]==EMPTY_VALUE && shift==0) PlaySound("alert2.wav");
            }
            else
            {
            UpTrend[shift] = EMPTY_VALUE;
            DnTrend[shift] = EMPTY_VALUE;
            UpSignal[shift]= EMPTY_VALUE; 
            DnSignal[shift]= EMPTY_VALUE;
            }
         }
         else
         if (trend[shift]<0) 
         {
            if (AMA[shift] < AMA[shift+1] && lastHi - AMA[shift] > Filter)
            {
            DnTrend[shift] = AMA[shift];
            if (trend[shift+ColorBarBack]>0) DnTrend[shift+ColorBarBack]=AMA[shift+ColorBarBack];
            UpTrend[shift] = EMPTY_VALUE;
            if (SignalMode>0 && lastHi - AMA[shift+1] <= Filter && DnTrend[shift+1]==EMPTY_VALUE) DnSignal[shift] = AMA[shift];
            else DnSignal[shift] = EMPTY_VALUE; 
            if (WarningMode>0 && lastHi - AMA[1] <= Filter && DnTrend[1]==EMPTY_VALUE && shift==0) PlaySound("alert2.wav");  
            }
            else
            {
            UpTrend[shift] = EMPTY_VALUE;
            DnTrend[shift] = EMPTY_VALUE;
            UpSignal[shift]= EMPTY_VALUE; 
            DnSignal[shift]= EMPTY_VALUE;
            }
         }
      }
   }
//----------   
   string Message;
   
   if (trend[1]>0 && AMA[1] > AMA[2] && AMA[1] - lastLo > Filter && lastLo >0 && ((!UpTrendAlert && AlertMode == 1) || (AlertMode == 2)))
	{
	Message = " "+Symbol()+" M"+Period()+":AdvancedAMA Signal for BUY";
	if (isNewBar()) Alert (Message); 
	UpTrendAlert=true; DnTrendAlert=false;
	} 
	else 	  
	if (trend[1]<0 && AMA[1] < AMA[2] && lastHi - AMA[1] > Filter && ((!DnTrendAlert && AlertMode == 1) || (AlertMode == 2)))
	{
	Message = " "+Symbol()+" M"+Period()+":AdvancedAMA Signal for SELL";
	if (isNewBar()) Alert (Message); 
	DnTrendAlert=true; UpTrendAlert=false;
	} 	         
 
//----
   
   return(0);
}

bool isNewBar()
{
   bool res=false;
   if (Time[0]!=pTime)
   {
   res=true;
   pTime=Time[0];
   }   
   return(res);
}

double iFD(int size, int count,int i)
{
   double bigRange = 0.00;
   int    window1  = size*(count-1);
   int    window2  = size* count;
   double nLog     = MathLog(count);
   
   smlRange[i] = MathMax(Close[size+i],maxHigh(size,i))
               - MathMin(Close[size+i],minLow(size,i));

   smlSumm[i] = smlSumm[i+1]+smlRange[i];               
   if ((Bars-i)>window1)
   {
         bigRange = MathMax(Close[window2+i],maxHigh(window2,i))
                  - MathMin(Close[window2+i],minLow(window2,i));

         smlSumm[i] -= smlRange[window1+i];
         return( 2 - MathLog(bigRange/(smlSumm[i]/window1))/nLog);
   }
   else return(1.5);
}

double minLow(int period,int shift)
{
   double minValue = Low[shift];
            for (int i=1; i<period; i++) minValue = MathMin(minValue,Low[shift+i]);
   return(minValue);
}

double maxHigh(int period,int shift)
{
   double maxValue = High[shift];
            for (int i=1; i<period; i++) maxValue = MathMax(maxValue,High[shift+i]);
   return(maxValue);
}

void SetEmulationIndexBuffer(double & Array[])
//----+
  {
    if (ArraySize(Array)<Bars)
                          ArraySetAsSeries(Array, false);
    ArrayResize(Array, Bars);
    ArraySetAsSeries(Array, true);
  }
//----+