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

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1  PaleVioletRed
#property indicator_color2  PaleVioletRed
#property indicator_color3  DeepSkyBlue
#property indicator_color4  DeepSkyBlue
#property indicator_width1  2
#property indicator_width3  2

//
//
//
//
//

extern int    SZPeriod         = 99;
extern double SZFactor         = 2.0;
extern int    EmaPeriod        = 13;
extern int    MacdFastPeriod   = 12;
extern int    MacdSlowPeriod   = 26;
extern int    MacdSignalPeriod =  9;
extern int    TimeRatio        =  5;
extern int    Price            = PRICE_CLOSE;

//
//
//
//
//

double szdnLine[];
double szdnDots[];
double szupLine[];
double szupDots[];

//+------------------------------------------------------------------+
//|                                                                  |
//|------------------------------------------------------------------|
//
//
//
//
//

int init()
{
   IndicatorDigits(7);
   SetIndexBuffer(0,szdnLine);
   SetIndexBuffer(1,szdnDots); SetIndexStyle(1,DRAW_ARROW); SetIndexArrow(1,159);
   SetIndexBuffer(2,szupLine);
   SetIndexBuffer(3,szupDots); SetIndexStyle(3,DRAW_ARROW); SetIndexArrow(3,159);

      IndicatorShortName("Elder safe zone");
   return(0);
}
int deinit() { return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double worksz[][2];
#define _sstop 0
#define _bstop 1

//
//
//
//
//

int start()
{
   int i,r,limit,counted_bars=IndicatorCounted();
   
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1);
           if (ArrayRange(worksz,0) != Bars) ArrayResize(worksz,Bars);
 
   //
   //
   //
   //
   //

   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      if (r==0)
      { 
         worksz[r][_sstop]=0;
         worksz[r][_bstop]=0;
         continue;
      }  
      worksz[r][_sstop] = worksz[r-1][_sstop];
      worksz[r][_bstop] = worksz[r-1][_bstop];
      
      //
      //
      //
      //
      //

         double sumN = 0; double cntN = 0;
         double sumP = 0; double cntP = 0;
   
            for (int k=0; k<SZPeriod; k++)
            {
               if (Low[i+k]<Low[i+k+1])   { sumN += (Low[i+k]-Low[i+k+1]);   cntN++; }
               if (High[i+k]>High[i+k+1]) { sumP += (High[i+k]-High[i+k+1]); cntP++; }
            }
   
         double upP    = 0; if (cntP>0) upP = sumP/cntP;
         double dnP    = 0; if (cntN>0) dnP = sumN/cntN;
         double pSStop = Low[i] + SZFactor*dnP;
         double pBStop = High[i]+ SZFactor*upP;

         double longTrend  = Elder_Impulse(i,0,TimeRatio);
         double shortTrend = Elder_Impulse(i,1,1);

      //
      //
      //
      //
      //

         if (worksz[r-1][_sstop] == 0 || Low[i]<=worksz[r-1][_sstop])
            {
               if (shortTrend != -1 && longTrend != -1)
                     worksz[r][_sstop] = pSStop;
               else  worksz[r][_sstop] = 0;
            }               
         else
            if (pSStop>worksz[r-1][_sstop]) worksz[r][_sstop] = pSStop;

         //
         //
         //
         //
         //
                     
         if (worksz[r-1][_bstop] == 0 || High[i]>=worksz[r-1][_bstop])
            {
               if (shortTrend != 1 && longTrend != 1)
                     worksz[r][_bstop] = pBStop;
               else  worksz[r][_bstop] = 0;
            }
         else
            if (pBStop<worksz[r-1][_bstop]) worksz[r][_bstop] = pBStop;
         
      //
      //
      //
      //
      //
         
         szdnLine[i] = EMPTY_VALUE;
         szdnDots[i] = EMPTY_VALUE;
         szupLine[i] = EMPTY_VALUE;
         szupDots[i] = EMPTY_VALUE;
         if (worksz[r-1][_bstop]>0) szdnLine[i]=worksz[r-1][_bstop]; if (szdnLine[i+1]==EMPTY_VALUE) szdnDots[i] = szdnLine[i];
         if (worksz[r-1][_sstop]>0) szupLine[i]=worksz[r-1][_sstop]; if (szupLine[i+1]==EMPTY_VALUE) szupDots[i] = szupLine[i];
   }
   return(0);         
}



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double work[][8];
#define _ema   0
#define _macdv 1
#define _macds 2
#define _macdo 3


double Elder_Impulse(int i, int forValue, double timeRatio)
{
   if (ArrayRange(work,0) != Bars) ArrayResize(work,Bars);
   double alpha = 2.0 / (1.0+MacdSignalPeriod*timeRatio);

   //
   //
   //
   //
   //
   
   int s = forValue*4;
   int r = Bars-i-1;
   
      work[r][s+_ema]   = iMA(NULL,0,EmaPeriod*timeRatio,0,MODE_EMA,Price,i); 
      work[r][s+_macdv] = iMA(NULL,0,MacdFastPeriod*timeRatio,0,MODE_EMA,Price,i)-iMA(NULL,0,MacdSlowPeriod*timeRatio,0,MODE_EMA,Price,i);
      work[r][s+_macds] = work[r-1][s+_macds]+alpha*(work[r][s+_macdv]-work[r-1][s+_macds]);
      work[r][s+_macdo] = work[r][s+_macdv]-work[r][s+_macds];
       
   //
   //
   //
   //
   //

   double answer = 0;         
      if (work[r][s+_ema]<work[r-1][s+_ema] && work[r][s+_macdo]<work[r-1][s+_macdo]) answer = -1;
      if (work[r][s+_ema]>work[r-1][s+_ema] && work[r][s+_macdo]>work[r-1][s+_macdo]) answer =  1;
   return(answer);      
}