//+------------------------------------------------------------------+
//|                                                 Wilder's DMI.mq4 |
//|                                                  coded by mladen |
//|                                                                  |
//| Directional movement index was developed by Welles Wilder        |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property  indicator_buffers   3
#property indicator_color1     LimeGreen
#property indicator_color2     Red
#property indicator_color3     Orange
#property indicator_width3     2
#property indicator_minimum    0

//
//
//
//
//

enum enTimeFrames
{
   tf_cu  = 0,              // current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // daily
   tf_w1  = PERIOD_W1,      // weekly
   tf_mb1 = PERIOD_MN1      // monthly
};
enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted    // Weighted
};
enum enAdxType
{
   adx_wil, // Wilders DMI (ADX)
   adx_bui  // Built in ADX
};   

extern enTimeFrames TimeFrame          = tf_cu;
extern int          AdxPeriod          = 14;
extern enAdxType    AdxType            = adx_wil;
extern enPrices     PriceForBuiltInADX = pr_close;
extern double       Level              = 20.0;
extern bool         Show_Dmi_Only      = false; 

//
//
//
//
//

double DIp[];
double DIm[];
double ADX[];

string indicatorFileName;
bool   returnBars;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

int init()
{
   SetIndexBuffer(0,DIp);    SetIndexLabel(0,"DI+");
   SetIndexBuffer(1,DIm);    SetIndexLabel(1,"DI-");
   SetIndexBuffer(2,ADX);    SetIndexLabel(2,"ADX");
         for (int i=0;i<3;i++) SetIndexEmptyValue(i,0.00);
         SetLevelValue(0,Level);
         if (Show_Dmi_Only)
               SetIndexStyle(2,DRAW_NONE); 
         else  SetIndexStyle(2,DRAW_LINE);
   
         //
         //
         //
         //
         //
     
         indicatorFileName = WindowExpertName();
         returnBars        = (TimeFrame==-99);
         TimeFrame         = MathMax(TimeFrame,_Period); 
        
   string name = " Wilder\'s "; if (AdxType==adx_bui) name = "";
   IndicatorShortName(timeFrameToString(TimeFrame)+name+" ADX ("+AdxPeriod+")");
return(0);
}

int deinit() { return(0);}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double work[][3];
#define _DIp 0
#define _DIm 1
#define _TR  2

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) { DIp[0] = limit+1; return(0); }
         
   //
   //
   //
   //
   //
   
   if (TimeFrame==Period())
   {
      if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);
      double sf = (AdxPeriod-1.0)/AdxPeriod;
      for (i=limit, r=Bars-i-1;i>=0;i--,r++)
      {
         if (AdxType==adx_bui)
         {
            ADX[i] = iADX(NULL,0,AdxPeriod,(int)PriceForBuiltInADX,MODE_MAIN,i);
            DIp[i] = iADX(NULL,0,AdxPeriod,(int)PriceForBuiltInADX,MODE_PLUSDI,i);
            DIm[i] = iADX(NULL,0,AdxPeriod,(int)PriceForBuiltInADX,MODE_MINUSDI,i);
            continue;
         }
         double currTR  = MathMax(High[i],Close[i+1])-MathMin(Low[i],Close[i+1]);
         double DeltaHi = High[i]  - High[i+1];
	      double DeltaLo = Low[i+1] - Low[i];
         double plusDM  = 0.00;
         double minusDM = 0.00;
         
            if ((DeltaHi > DeltaLo) && (DeltaHi > 0)) plusDM  = DeltaHi;
            if ((DeltaLo > DeltaHi) && (DeltaLo > 0)) minusDM = DeltaLo;      
         
         //
         //
         //
         //
         //
         
            work[r][_DIp] = sf*work[r-1][_DIp] + plusDM;
            work[r][_DIm] = sf*work[r-1][_DIm] + minusDM;
            work[r][_TR]  = sf*work[r-1][_TR]  + currTR;

         //
         //
         //
         //
         //
                  
            DIp[i] = 0.00;                   
            DIm[i] = 0.00;                   
            if (work[r][_TR] > 0)             
            {              
               DIp[i] = 100.00 * work[r][_DIp]/work[r][_TR];
               DIm[i] = 100.00 * work[r][_DIm]/work[r][_TR];
            }            
              double DX;
              if((DIp[i] + DIm[i])>0) 
                   DX  = 100*MathAbs(DIp[i] - DIm[i])/(DIp[i] + DIm[i]); 
              else DX  = 0.00;
              ADX[i]   = sf*ADX[i+1] + DX/AdxPeriod; 
         }
         return(0);
   } 
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/_Period));
   for (i=limit;i>=0; i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         DIp[i] = iCustom(NULL,TimeFrame,indicatorFileName,tf_cu,AdxPeriod,AdxType,PriceForBuiltInADX,0,y);
         DIm[i] = iCustom(NULL,TimeFrame,indicatorFileName,tf_cu,AdxPeriod,AdxType,PriceForBuiltInADX,1,y);
         ADX[i] = iCustom(NULL,TimeFrame,indicatorFileName,tf_cu,AdxPeriod,AdxType,PriceForBuiltInADX,2,y);       
   }
return(0);
} 

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

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("");
}