//+------------------------------------------------------------------+
//|                                                 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 2
#property indicator_color1   clrDodgerBlue
#property indicator_color2   clrSandyBrown


//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame    = PERIOD_CURRENT;
extern int             DMILength    =    14;
extern int             Level        =    25;
extern int             Smooth       =     5;
extern ENUM_MA_METHOD  SmoothMethod = MODE_EMA;
input int              HistoWidth   = 3;                 // Histogram bars width
input color            UpHistoColor = clrLimeGreen;      // Bullish color
input color            DnHistoColor = clrRed;            // Bearish color

//
//
//
//
//

double DIp[];
double DIm[],upH[],dnH[];
double averageDIp[];
double averageDIm[];
double averageTR[];
double trend[];

//
//
//
//
//

string indicatorFileName;
bool   returnBars;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,upH,INDICATOR_DATA); SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,HistoWidth,UpHistoColor);
   SetIndexBuffer(1,dnH,INDICATOR_DATA); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,HistoWidth,DnHistoColor);   
   SetIndexBuffer(2,DIp);
   SetIndexBuffer(3,DIm);
   SetIndexBuffer(4,averageDIp);
   SetIndexBuffer(5,averageDIm);
   SetIndexBuffer(6,averageTR);
   SetIndexBuffer(7,trend);
      for (int i=4;i<7;i++) SetIndexEmptyValue(i,0.00);

   //
   //
   //
   //
   //
      IndicatorSetDouble(INDICATOR_MINIMUM,0);
      IndicatorSetDouble(INDICATOR_MAXIMUM,1);
      indicatorFileName = WindowExpertName();
      returnBars        = (TimeFrame==-99);
      TimeFrame         = MathMax(TimeFrame,_Period);
      Smooth            = MathMax(Smooth,1);
         SetLevelValue(0,Level);

   //
   //
   //
   //
   //
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" Wilder\'s DMI ("+DMILength+")");
   return(0);
}

int deinit()
{
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int 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)  { upH[0] = limit+1; return(0); }

   //
   //
   //
   //
   //
   
   if (TimeFrame == Period())
   {
      double sf = (DMILength-1.0)/DMILength;
      double arrc[3],arrp[2];
      for (int i=limit; i>=0; i--)
      {
         arrc[0] = iMA(NULL,0,Smooth,0,SmoothMethod,PRICE_HIGH ,i  );
         arrc[1] = iMA(NULL,0,Smooth,0,SmoothMethod,PRICE_LOW  ,i  );
         arrc[2] = iMA(NULL,0,Smooth,0,SmoothMethod,PRICE_CLOSE,i+1);
         arrp[0] = iMA(NULL,0,Smooth,0,SmoothMethod,PRICE_HIGH ,i+1);
         arrp[1] = iMA(NULL,0,Smooth,0,SmoothMethod,PRICE_LOW  ,i+1);
         ArraySort(arrc); ArraySort(arrp); 
         double currTR  = MathMax(arrc[2],arrc[1])-MathMin(arrc[0],arrc[1]);
         double DeltaHi = arrc[2] - arrp[1];
	      double DeltaLo = arrp[0] - arrc[0];
         double plusDM  = 0.00;
         double minusDM = 0.00;
         
            if ((DeltaHi > DeltaLo) && (DeltaHi > 0)) plusDM  = DeltaHi;
            if ((DeltaLo > DeltaHi) && (DeltaLo > 0)) minusDM = DeltaLo;      
         
         //
         //
         //
         //
         //
         
            averageDIp[i] = sf*averageDIp[i+1] + plusDM;
            averageDIm[i] = sf*averageDIm[i+1] + minusDM;
            averageTR[i]  = sf*averageTR[i+1]  + currTR;

         //
         //
         //
         //
         //
                  
            DIp[i] = 0.00;                   
            DIm[i] = 0.00;                   
            if (averageTR[i] > 0)
               {              
                  DIp[i] = 100.00 * averageDIp[i]/averageTR[i];
                  DIm[i] = 100.00 * averageDIm[i]/averageTR[i];
               }            
               trend[i] = 0;
               if (DIp[i]>DIm[i] && DIp[i]>Level) trend[i] =  1;
               if (DIp[i]<DIm[i] && DIm[i]>Level) trend[i] = -1;
               upH[i] = EMPTY_VALUE;
               dnH[i] = EMPTY_VALUE;
               if (trend[i] ==  1) upH[i] = 1;
               if (trend[i] == -1) dnH[i] = 1; 
      }   
      return(0);      
   }
   
   //
   //
   //
   //
   //
   
   limit = MathMax(limit,MathMin(Bars,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   for (i=limit;i>=0;i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         trend[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,DMILength,Level,Smooth,SmoothMethod,HistoWidth,UpHistoColor,DnHistoColor,7,y);
         upH[i] = EMPTY_VALUE;
         dnH[i] = EMPTY_VALUE;
            if (trend[i] ==  1) upH[i] = 1; 
            if (trend[i] == -1) dnH[i] = 1; 
   }
   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("");
}