//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www.forex-tsd.com"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1  LimeGreen
#property indicator_color2  Orange
#property indicator_color3  Orange
#property indicator_width1  2
#property indicator_width2  2
#property indicator_width3  2

//
//
//
//
//

extern string TimeFrame   = "Current time frame";
extern int    period      = 14;          // Calculating period
extern int    Price       = PRICE_CLOSE; // Price
extern double Divisor     = 3;           // Divisor to use for "ema" calculation
extern double Filter      = 1;           // Filter 
extern color  color_ray   = Linen;
extern int    width_ray   = 1;
extern string UniqueID    = "ema variation filter ray1";
extern bool   Interpolate = true;

double buffer[];
double bufferda[];
double bufferdb[];
double trend[];
string indicatorFileName;
bool   returnBars;
int    timeFrame;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,buffer);
   SetIndexBuffer(1,bufferda);
   SetIndexBuffer(2,bufferdb);
   SetIndexBuffer(3,trend);
      indicatorFileName = WindowExpertName();
      returnBars        = TimeFrame == "returnBars";     if (returnBars)     return(0);
      timeFrame         = stringToTimeFrame(TimeFrame);
   return(0);
}
int deinit()
{
   ObjectDelete(UniqueID);
   return(0);
}


//
//
//
//
//

double work[][2];
#define _change 0
#define _achang 1
int start()
{
   int i,r,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
           int limit=MathMin(Bars-counted_bars,Bars-2);
           if (returnBars) { buffer[0] = limit+1; return(0); }
           if (timeFrame != Period())
           {
               limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
               if (trend[limit]==-1) CleanPoint(limit,bufferda,bufferdb);
               for(i=limit; i>=0; i--)
               {
                  int y = iBarShift(NULL,timeFrame,Time[i]);               
                     buffer[i]   = iCustom(NULL,timeFrame,indicatorFileName,"",period,Price,Divisor,Filter,color_ray,width_ray,UniqueID,0,y);
                     trend[i]    = iCustom(NULL,timeFrame,indicatorFileName,"",period,Price,Divisor,Filter,color_ray,width_ray,UniqueID,3,y);
                     bufferda[i] = EMPTY_VALUE;
                     bufferdb[i] = EMPTY_VALUE;
                     if (!Interpolate || y==iBarShift(NULL,timeFrame,Time[i-1])) continue;
   
                     //
                     //
                     //
                     //
                     //

                     datetime time = iTime(NULL,timeFrame,y);
                        for(int n = 1; i+n < Bars && Time[i+n] >= time; n++) continue;	
                        for(int m = 1; m < n; m++)
                           buffer[i+m] = buffer[i] + (buffer[i+n] - buffer[i]) * m/n;
               }
               for(i=limit; i>=0; i--) if (trend[i] == -1) PlotPoint(i,bufferda,bufferdb,buffer);
               return(0);
            }
            if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);

   //
   //
   //
   //
   //

   if (trend[limit]==-1) CleanPoint(limit,bufferda,bufferdb);
   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      buffer[i]   = iEma(iEma(iMA(NULL,0,1,0,MODE_SMA,Price,i),period/Divisor,Bars,i,0),period/Divisor,Bars,i,1);
      bufferda[i] = EMPTY_VALUE;
      bufferdb[i] = EMPTY_VALUE;
      trend[i]    = trend[i+1];
      
         //
         //
         //
         //
         //
         
         if (Filter>0)
         {
            work[r][_change] = MathAbs(buffer[i]-buffer[i+1]);
            work[r][_achang] = work[r][_change];
            for (int k=1; k<period && (r-k)>=0; k++) work[r][_achang] += work[r-k][_change];
                                                     work[r][_achang] /= 1.0*period;
    
            double stddev = 0; for (k=0;  k<period && (r-k)>=0; k++) stddev += MathPow(work[r-k][_change]-work[r-k][_achang],2);
                   stddev = MathSqrt(stddev/period); 
            double filter = Filter * stddev;
            if( MathAbs(buffer[i]-buffer[i+1]) < filter ) buffer[i]=buffer[i+1];
         }
         if (buffer[i]>buffer[i+1]) trend[i] =  1;
         if (buffer[i]<buffer[i+1]) trend[i] = -1;
         if (trend[i] == -1) PlotPoint(i,bufferda,bufferdb,buffer);
   }
    ObjectCreate(UniqueID,OBJ_TREND,0,0,0,0,0);
         ObjectSet(UniqueID,OBJPROP_RAY,true);
         ObjectSet(UniqueID,OBJPROP_COLOR,color_ray);
         ObjectSet(UniqueID,OBJPROP_WIDTH,width_ray);
         ObjectSet(UniqueID,OBJPROP_TIME1,Time[1]);
         ObjectSet(UniqueID,OBJPROP_PRICE1,buffer[1]);
         ObjectSet(UniqueID,OBJPROP_TIME2,Time[0]);
         ObjectSet(UniqueID,OBJPROP_PRICE2,buffer[0]);     
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workEma[][2];
double iEma(double price, double eperiod, int bars, int r, int instanceNo=0)
{
   if (ArrayRange(workEma,0)!= bars) ArrayResize(workEma,bars); r = bars-r-1;

   //
   //
   //
   //
   //
      
   double alpha = 2.0 / (1.0+eperiod);
          workEma[r][instanceNo] = workEma[r-1][instanceNo]+alpha*(price-workEma[r-1][instanceNo]);
   return(workEma[r][instanceNo]);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

//
//
//
//
//

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (first[i+1] == EMPTY_VALUE)
         {
            if (first[i+2] == EMPTY_VALUE) 
                  { first[i]  = from[i]; first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
            else  { second[i] = from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
         }
   else  { first[i] = from[i]; second[i] = EMPTY_VALUE; }
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string stringUpperCase(string str) { StringToUpper(str); return(str); }