//-------------------------------------------------------------------
//       original : ANG3110                                                           
//       this version : mladen
//-------------------------------------------------------------------

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 LightSlateGray
#property indicator_color2 DodgerBlue
#property indicator_color3 SandyBrown
#property indicator_color4 SandyBrown
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2

extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;
extern int period = 14;
extern int Level  = 25;
double ADX[],ADXLa[],ADXLb[],DI[],slope[];
string indicatorFileName;
bool   returnBars;

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,DI);
   SetIndexBuffer(1,ADX);
   SetIndexBuffer(2,ADXLa);
   SetIndexBuffer(3,ADXLb);
   SetIndexBuffer(4,slope);
      SetLevelValue(0,0);
      SetLevelValue(1, Level);
      SetLevelValue(2,-Level);
         indicatorFileName = WindowExpertName();
         returnBars        = (TimeFrame==-99);
         TimeFrame         = MathMax(TimeFrame,_Period);
   IndicatorShortName(timeFrameToString(TimeFrame)+" ADXm ("+period+")");
   return(0);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

double work[][4];
#define zdh    0
#define zdl    1
#define zdx    2
#define _slope 3

int start()
{
   int i,r,counted_bars = IndicatorCounted();
      if(counted_bars < 0) return(-1);
      if(counted_bars > 0) counted_bars--;
         double alpha = 2.0/(period+1);
         int limit    = MathMin(Bars-counted_bars,Bars-1);
         if (returnBars) { DI[0] = limit+1; return(0); }

   //
   //
   //
   //
   //
   
   if (TimeFrame == Period())
   {
      if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);
      if (work[limit][_slope]==-1) CleanPoint(limit,ADXLa,ADXLb);
      for (i=limit,r=Bars-i-1; i>=0; i--,r++)
      {
         if (i==Bars-1) { work[r][zdh] = 0; work[r][zdl] = 0; work[r][zdx] = 0;  continue; }
      
            double H  = High[i]; 
            double L  = Low[i];
            double dh = MathMax(H-High[i+1],0);
            double dl = MathMax(Low[i+1]-L ,0);
         
      if(dh==dl) {dh=0; dl=0;} else if(dh<dl) dh=0; else if(dl<dh) dl=0;
      
         double num1 = MathAbs(H-L);
         double num2 = MathAbs(H-Close[i+1]);
         double num3 = MathAbs(L-Close[i+1]);
         double tr   = MathMax(MathMax(num1,num2),num3);
         double dhk  = 0;
         double dlk  = 0;
      
            if(tr!=0) 
               { 
                  dhk=100.0*dh/tr; 
                  dlk=100.0*dl/tr;
               }
      
         work[r][zdh] = work[r-1][zdh]+alpha*(dhk-work[r-1][zdh]);
         work[r][zdl] = work[r-1][zdl]+alpha*(dlk-work[r-1][zdl]);
         DI[i]       = work[r][zdh]-work[r][zdl];

            double div  = MathAbs(work[r][zdh] + work[r][zdl]);
            double temp = 0; 
               if( div != 0.0) temp=100*(MathAbs(DI[i])/div); 
               if (work[r][zdh]<work[r][zdl]) temp = -temp;
      
         work[r][zdx]    = work[r-1][zdx]+alpha*(temp-work[r-1][zdx]);
         ADX[i]          = work[r][zdx];
         ADXLa[i]        = EMPTY_VALUE;
         ADXLb[i]        = EMPTY_VALUE;
         work[r][_slope] = work[r-1][_slope];
         if (ADX[i]>ADX[i+1]) work[r][_slope] =  1;
         if (ADX[i]<ADX[i+1]) work[r][_slope] = -1;
         if (work[r][_slope]==-1) PlotPoint(i,ADXLa,ADXLb,ADX);
            slope[i] = work[r][_slope];
      }
      return(0);
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   if (slope[limit]==-1) CleanPoint(limit,ADXLa,ADXLb);
   for(i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         DI[i]    = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,period,Level,0,y);
         ADX[i]   = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,period,Level,1,y);
         slope[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,period,Level,4,y);
         ADXLa[i] = EMPTY_VALUE;
         ADXLb[i] = EMPTY_VALUE;
         if (slope[i]==-1) PlotPoint(i,ADXLa,ADXLb,ADX);
   }               
   return(0);
         
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   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 (i>=Bars-2) return;
   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};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}