//+------------------------------------------------------------------+
//|                                                 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_chart_window
#property  indicator_buffers 4
#property indicator_color1   clrDodgerBlue
#property indicator_color2   clrSandyBrown
#property indicator_color3   clrSilver
#property indicator_color4   clrSilver

//
//
//
//
//

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;

//
//
//
//
//

double DIp[];
double DIm[];
double histo01[];
double histo02[];
double histo21[];
double histo22[];
double averageDIp[];
double averageDIm[];
double averageTR[];
double trend[];

//
//
//
//
//

string indicatorFileName;
bool   returnBars;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

int init()
{
   IndicatorBuffers(10);
   SetIndexBuffer(0,histo01);  SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,histo02);  SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,histo21);  SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(3,histo22);  SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(4,DIp);
   SetIndexBuffer(5,DIm);
   SetIndexBuffer(6,averageDIp);
   SetIndexBuffer(7,averageDIm);
   SetIndexBuffer(8,averageTR);
   SetIndexBuffer(9,trend);
      for (int i=4;i<7;i++) SetIndexEmptyValue(i,0.00);

   //
   //
   //
   //
   //

      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)  { histo01[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;
               histo01[i] = EMPTY_VALUE;
               histo02[i] = EMPTY_VALUE;
               histo21[i] = EMPTY_VALUE;
               histo22[i] = EMPTY_VALUE;
               if (trend[i] ==  1) { histo01[i] = High[i]; histo02[i] = Low[i]; }
               if (trend[i] == -1) { histo02[i] = High[i]; histo01[i] = Low[i]; }
               if (trend[i] ==  0) { histo21[i] = High[i]; histo22[i] = Low[i]; }
      }   
      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,9,y);
         histo01[i] = EMPTY_VALUE;
         histo02[i] = EMPTY_VALUE;
         histo21[i] = EMPTY_VALUE;
         histo22[i] = EMPTY_VALUE;
            if (trend[i] ==  1) { histo01[i] = High[i]; histo02[i] = Low[i]; }
            if (trend[i] == -1) { histo02[i] = High[i]; histo01[i] = Low[i]; }
            if (trend[i] ==  0) { histo21[i] = High[i]; histo22[i] = Low[i]; }
   }
   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("");
}