//------------------------------------------------------------------
//                                                   ChandesDMI.mq4 
//------------------------------------------------------------------
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers   5
#property indicator_color1    Gray
#property indicator_color2    LimeGreen
#property indicator_color3    LimeGreen
#property indicator_color4    PaleVioletRed
#property indicator_color5    PaleVioletRed
#property indicator_width1    2 
#property indicator_width2    2 
#property indicator_width3    2 
#property indicator_width4    2 
#property indicator_width5    2 
//
extern int       Price           =  0; // Applied Price: 0-Close,1-Open,2-High,3-Low,4-Median,5-Typical,6-Weighted
extern int       StdDevPeriod    =  5; // Period of Standard Deviation
extern int       MAStdDevPeriod  = 10; // Period of smoothing
extern int       MAStdDevMode    =  0; // Mode of smoothing MA
extern int       DMIPeriod       =  5; // Dynamic Momentum Index Period
extern int       DmiLowerLimit   = 10; // Dynamic Periods Lower Bound
extern int       DmiUpperLimit   = 50; // Dynamic Periods Upper Bound
extern double    LevelUp         = 70;
extern double    LevelDown       = 30;
//---- buffers
double DMI[];
double dmiUa[];
double dmiUb[];
double dmiDa[];
double dmiDb[];
double STD[];
double state[];


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
   IndicatorBuffers(7);
   SetIndexBuffer(0,DMI);
   SetIndexBuffer(1,dmiUa);
   SetIndexBuffer(2,dmiUb);
   SetIndexBuffer(3,dmiDa);
   SetIndexBuffer(4,dmiDb);
   SetIndexBuffer(5,STD);
   SetIndexBuffer(6,state);
            SetLevelValue(0,LevelUp);
            SetLevelValue(1,LevelDown);
//---- name for DataWindow and indicator subwindow label
   string short_name="TC Chandes DMI ("+Price+","+StdDevPeriod+","+MAStdDevPeriod+","+MAStdDevMode+","+DMIPeriod+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"DMI");
   
//----
   SetIndexDrawBegin(0,StdDevPeriod+MAStdDevPeriod+DMIPeriod);
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+

double wrkBuffer[][13];
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-1);
         if (ArrayRange(wrkBuffer,0) != Bars) ArrayResize(wrkBuffer,Bars);
  
   //
   //
   //
   //
   //
      
   if (state[limit] == 1) CleanPoint(limit,dmiUa,dmiUb);
   if (state[limit] ==-1) CleanPoint(limit,dmiDa,dmiDb);
   for(i=limit; i>=0; i--) STD[i] = iStdDev(NULL,0,StdDevPeriod,0,MODE_SMA,Price,i);
   for(i=limit, r=Bars-i-1; i>=0; i--, r++)
   {
      double MASTD = iMAOnArray(STD,0,MAStdDevPeriod,0,MAStdDevMode,i); 
      double VI = 0;
      if (MASTD != 0) VI = STD[i]/MASTD;
                  if (VI != 0)
                        int Td = MathRound(DMIPeriod/VI); 
                  else      Td = 0;                        
   
      if (Td > DmiUpperLimit ) Td = DmiUpperLimit;
      if (Td < DmiLowerLimit ) Td = DmiLowerLimit;

         wrkBuffer[r][12] = iMA(NULL,0,1,0,MODE_SMA,Price,i);
            double Kg     = (3.0)/(2.0+Td);
            double Hg     = 1.0-Kg;
            double roc = wrkBuffer[r][12]-wrkBuffer[r-1][12];
            double roa = MathAbs(roc);
            for (int k=0; k<3; k++)
            {
               int kk = k*2;
                  wrkBuffer[r][kk+0] = Kg*roc                + Hg*wrkBuffer[r-1][kk+0];
                  wrkBuffer[r][kk+1] = Kg*wrkBuffer[r][kk+0] + Hg*wrkBuffer[r-1][kk+1]; roc = 1.5*wrkBuffer[r][kk+0] - 0.5 * wrkBuffer[r][kk+1];
                  wrkBuffer[r][kk+6] = Kg*roa                + Hg*wrkBuffer[r-1][kk+6];
                  wrkBuffer[r][kk+7] = Kg*wrkBuffer[r][kk+6] + Hg*wrkBuffer[r-1][kk+7]; roa = 1.5*wrkBuffer[r][kk+6] - 0.5 * wrkBuffer[r][kk+7];
            }
         if (roa != 0)
              DMI[i] = MathMax(MathMin((roc/roa+1.0)*50.0,100.00),0.00); 
         else DMI[i] = 50.0;
         dmiUa[i] = EMPTY_VALUE;
         dmiUb[i] = EMPTY_VALUE;
         dmiDa[i] = EMPTY_VALUE;
         dmiDb[i] = EMPTY_VALUE;
      if (DMI[i]<LevelDown)                        state[i] = -1;
      if (DMI[i]>LevelUp)                          state[i] =  1;
      if (DMI[i]>LevelDown && DMI[i]<LevelUp)  state[i] =  0;
      if (state[i] == 1) PlotPoint(i,dmiUa,dmiUb,DMI);
      if (state[i] ==-1) PlotPoint(i,dmiDa,dmiDb,DMI);
   }
   return(0);
}
  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i]   = 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 (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;
      }
}
  
//+------------------------------------------------------------------+
/*

Source Code For Metastock

========================
Dynamic Mom Index - jose
========================
---8<---------------------------

{ Jose's Dynamic Momentum Index v3.1, 0~100% }
{ ©Copyright 2003-2004 Jose Silva }
{ http://www.metastocktools.com }

pds:=Input("avg DyMoIdx periods",3,252,21);
Stpds:=
 Input("Standard Deviation periods",2,252,5);
x:=Input("use Open=1 High=2 Low=3 Close=4 Volume=5 P=6",1,6,4);
plot:=Input("[1]Dynamic Momentum Idx,  [2]dynamic periods used",1,2,1);

x:=If(x=1,O,If(x=2,H,If(x=3,L,If(x=5,V,
 If(x=6,P,C)))));
Vt:=Stdev(x,Stpds)/Mov(Stdev(x,Stpds),10,S);
pds:=pds/(Vt+.14142);
pds:=If(pds>Cum(IsDefined(x))-13,
 Cum(IsDefined(x))-13,pds);
pds:=If(pds<2,2,pds);

Up:=If(x>Ref(x,-1),x-Ref(x,-1),0);
Dw:=If(x<Ref(x,-1),Ref(x,-1)-x,0);
UpAvg:=Up*2/pds+PREV*(1-2/pds);
DwAvg:=Dw*2/pds+PREV*(1-2/pds);
DyMoIdx:=
 100-(100/(1+UpAvg/If(DwAvg>0,DwAvg,.000001)));

If(plot=1,DyMoIdx,pds)

---8<---------------------------

Source Code From VTS:

Vi:= Stdev(price,stdevPeriods) / Mov(Stdev(price,stdevPeriods),stdevmaper,stdevmat) ;
Td:= Int(DmiPeriods/Vi);
Td:= if(Td>DmiUpperLimit,DmiUpperLimit,if(Td<DmiLowerLi mit,DmiLowerLimit,Td));

rsi_r:= (price - ref(price,-1));
rsi_rs:= Wilders(if(rsi_r>0,rsi_r,0),Td) / Wilders(if(rsi_r<0,Abs(rsi_r),0),Td);
DMIndex:= 100-(100/(1+rsi_rs));

IndicatorPlot:= if(plot=0,DMIndex,Td);
*/

