//+------------------------------------------------------------------+
//|                                                dmx - ocn nma.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers    5
#property indicator_color1     clrDarkSlateGray
#property indicator_color2     clrDarkSlateGray
#property indicator_color3     clrDeepSkyBlue
#property indicator_color4     clrRed
#property indicator_color5     clrDimGray
#property indicator_style1     STYLE_DOT
#property indicator_style2     STYLE_DOT
#property indicator_width3     2
#property indicator_width4     2
#property indicator_width5     2
#property indicator_levelcolor clrDarkSlateGray
#property indicator_level1     0

//
//
//
//
//

extern int    aperiod         = 40;          // NMA average period
extern int    tperiod         = 10;          // TEMA period
extern int    Smoothaperiod   = 20;
extern int    Smoothtperiod   = 5;
extern bool   ShowHistogram   = true;
extern bool   ShowUpDownLimit = true;

//
//
//
//
//

double dmx[];
double dmxU[];
double dmxD[];
double limU[];
double limD[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,limU); SetIndexLabel(0,NULL);
   SetIndexBuffer(1,limD); SetIndexLabel(1,NULL);
   SetIndexBuffer(4,dmx);  SetIndexLabel(4,"Dmx");
      if (ShowHistogram)
      {
         SetIndexBuffer(2,dmxU); SetIndexStyle(2,DRAW_HISTOGRAM); SetIndexLabel(2,"Dmx");
         SetIndexBuffer(3,dmxD); SetIndexStyle(3,DRAW_HISTOGRAM); SetIndexLabel(3,"DmX");
      }
      else
      {
         SetIndexStyle(2,DRAW_NONE); SetIndexLabel(2,NULL);
         SetIndexStyle(3,DRAW_NONE); SetIndexLabel(3,NULL);
      }
   Smoothaperiod =MathMax(Smoothaperiod,1);

   //
   //
   //
   //
   //
   
   IndicatorShortName("Dmx ocn nma("+aperiod+","+tperiod+","+Smoothaperiod+","+Smoothtperiod+")");
   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);
           
   //
   //
   //
   //
   //
   
   for(int i=limit; i>=0; i--)
   {
      double currTR  = iNma(MathMax(High[i],Close[i+1])-MathMin(Low[i],Close[i+1]),aperiod,tperiod,i);
      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;      
         
      //
      //
      //
      //
      //

         double DIp = 0.00;
         double DIm = 0.00;

            if (currTR > 0.00)
            {
               DIp = 100.0*iNma(plusDM ,aperiod,tperiod,i,1)/currTR;
               DIm = 100.0*iNma(minusDM,aperiod,tperiod,i,2)/currTR;
            }
            if ((DIp+DIm) != 0)
                  dmx[i] = 100.00*iNma((DIp-DIm)/(DIp+DIm),Smoothaperiod,Smoothtperiod,i,3);
            else  dmx[i] = 100.00*iNma(0                  ,Smoothaperiod,Smoothtperiod,i,3);
         
      //
      //
      //
      //
      //
               
      if (ShowHistogram)
      {
         dmxD[i] = dmxD[i+1];
         dmxU[i] = dmxU[i+1];
            if (dmx[i] > dmx[i+1]) { dmxU[i] = dmx[i];  dmxD[i] = EMPTY_VALUE; }
            if (dmx[i] < dmx[i+1]) { dmxD[i] = dmx[i];  dmxU[i] = EMPTY_VALUE; }
      }
      if (ShowUpDownLimit)
      {
         limD[i] = -30;
         limU[i] =  30;
      }         
   }   

   //
   //
   //
   //
   //
   
   return(0);      
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

#define _nmaInstances 4
#define _nmaPrice     3
#define _nmaMom       4
#define _nmaValue     5
double workNma[][_nmaInstances*6];

double iNma(double nprice, int nperiod, int temaperiod, int i, int instanceNo=0)
{
   if (nperiod<=1) return(nprice);
   if (ArrayRange(workNma,0)!=Bars) ArrayResize(workNma,Bars); i = Bars-i-1; instanceNo*=6;

   //
   //
   //
   //
   //

   double alpha = 2.0 /(1.0 + temaperiod);
   if (i < 1)
   {
      workNma[i][instanceNo+_nmaPrice] = nprice;
      workNma[i][instanceNo+_nmaValue] = nprice;
      workNma[i][instanceNo+_nmaMom]   = 0;
      workNma[i][instanceNo+0]         = nprice;
      workNma[i][instanceNo+1]         = nprice;
      workNma[i][instanceNo+2]         = nprice;
   }
   else
   {
      workNma[i][instanceNo+0]         = workNma[i-1][instanceNo+0]+alpha*(nprice                  -workNma[i-1][instanceNo+0]);
      workNma[i][instanceNo+1]         = workNma[i-1][instanceNo+1]+alpha*(workNma[i][instanceNo+0]-workNma[i-1][instanceNo+1]);
      workNma[i][instanceNo+2]         = workNma[i-1][instanceNo+2]+alpha*(workNma[i][instanceNo+1]-workNma[i-1][instanceNo+2]);
      workNma[i][instanceNo+_nmaPrice] = 3*workNma[i][instanceNo+0] - 3*workNma[i][instanceNo+1] + workNma[i][instanceNo+2];
      workNma[i][instanceNo+_nmaMom]   = workNma[i][instanceNo+_nmaPrice]-workNma[i-1][instanceNo+_nmaPrice];
         
      //
      //
      //
      //
      //
   
      double momRatio = 0.00;
      double sumMomen = 0.00;
      double ratio    = 0.00;
      
      for (int k = 0; k<nperiod && (i-k)>=0; k++)
      {
         sumMomen += MathAbs(workNma[i-k][instanceNo+_nmaMom]);
         momRatio +=         workNma[i-k][instanceNo+_nmaMom]*(MathSqrt(k+1)-MathSqrt(k));
      }
      if (sumMomen != 0) ratio = MathAbs(momRatio)/sumMomen;
      workNma[i][instanceNo+_nmaValue] =  workNma[i-1][instanceNo+_nmaValue]+ratio*(nprice-workNma[i-1][instanceNo+_nmaValue]);
   }         
   return(workNma[i][instanceNo+_nmaValue]);
}
