//+------------------------------------------------------------------+
//|                                                          dmx.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mrtools"
#property link      "mrtools@aol.com"

#property indicator_separate_window
#property indicator_buffers    6
#property indicator_color1     clrRed
#property indicator_color2     clrRed
#property indicator_color3     clrLime
#property indicator_color4     clrLime
#property indicator_color5     clrDodgerBlue
#property indicator_color6     clrCoral 
#property indicator_width1     3
#property indicator_width2     1
#property indicator_width3     3
#property indicator_width4     1
#property indicator_width5     2
#property indicator_width6     2
#property indicator_levelcolor clrGold
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame       = PERIOD_CURRENT; // Time frame
extern int             DmxLength       = 32;             // Dmx jurik length
extern int             DmxPhase        = 0;              // Dmx jurik phase
extern bool            DmxDouble       = false;          // Dmx jurik smooth double     
extern int             Smooth          = 5;              // Dmx jurik smoothing length          
extern int             SmoothPhase     = 0;              // Dmx jurik smoothing phase
extern bool            SmoothDouble    = false;          // Dmx jurik smoothing double
extern int             SignalLength    = 5;              // Dmx signal length
extern int             SignalPhase     = 0;              // Dmx signal phase 
extern bool            SignalDouble    = false;          // Dmx signal double
extern double          levelOb         = 60.0;           // Overbought level
extern double          levelOs         = -60.0;          // Oversold level
extern bool            Interpolate     = true;           // Interpolate in multi time frame mode?


double Upa[],Upb[],Dna[],Dnb[],dmx[],sig[],slope[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_y) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,DmxLength,DmxPhase,DmxDouble,Smooth,SmoothPhase,SmoothDouble,SignalLength,SignalPhase,SignalDouble,levelOb,levelOs,_buff,_y)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(9);
   SetIndexBuffer(0,Dna);  SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,Dnb);  SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,Upa);  SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexBuffer(3,Upb);  SetIndexStyle(3,DRAW_HISTOGRAM);
   SetIndexBuffer(4,dmx);  SetIndexLabel(4,"Dmx");
   SetIndexBuffer(5,sig);
   SetIndexBuffer(6,slope);
   SetIndexBuffer(7,trend);
   SetIndexBuffer(8,count);
   SetLevelValue(0,levelOb);
   SetLevelValue(1,0);
   SetLevelValue(2,levelOs);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period);  
      
   IndicatorShortName(timeFrameToString(TimeFrame)+" dmx ("+(string)DmxLength+","+(string)SignalLength+")");
return(0);
}
int deinit(){ return(0); }

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start()
{
   int i,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = fmin(Bars-counted_bars,Bars-1); count[0]=limit;
            if (TimeFrame!=_Period)
            {
               limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(8,0)*TimeFrame/_Period));
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     dmx[i]   = _mtfCall(4,y);
                     sig[i]   = _mtfCall(5,y);
                     slope[i] = _mtfCall(6,y);
                     trend[i] = _mtfCall(7,y);
                 
                     //
                     //
                     //
                     //
                     //
                     
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                        #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                        int n,k; datetime time = iTime(NULL,TimeFrame,y);
                           for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                           for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                           {
                              _interpolate(dmx);
                              _interpolate(sig);
                           }                           
              }   
              for (i=limit; i >= 0; i--)
              {
                 Upa[i] = (trend[i] == 1 && slope[i] == 1) ? dmx[i] : EMPTY_VALUE;
                 Upb[i] = (trend[i] == 1 && slope[i] ==-1) ? dmx[i] : EMPTY_VALUE;
                 Dna[i] = (trend[i] ==-1 && slope[i] ==-1) ? dmx[i] : EMPTY_VALUE;
                 Dnb[i] = (trend[i] ==-1 && slope[i] == 1) ? dmx[i] : EMPTY_VALUE;      
	           }      
    return(0);
    }
   
    //
    //
    //
    //
    //
   
    for (i = limit; i >= 0; i--)
    {
       if (i<Bars-1)
       {
         double currTR  = iDSmooth(fmax(High[i],Close[i+1])-fmin(Low[i],Close[i+1]),DmxLength,DmxPhase,DmxDouble,i,0);
         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*iDSmooth(plusDM ,DmxLength,DmxPhase,DmxDouble,i,20)/currTR;
                  DIm = 100.0*iDSmooth(minusDM,DmxLength,DmxPhase,DmxDouble,i,40)/currTR;
               }
               if ((DIp+DIm) != 0)
                     dmx[i] = 100.00*iDSmooth((DIp-DIm)/(DIp+DIm),Smooth,SmoothPhase,SmoothDouble,i,60);
               else  dmx[i] = 100.00*iDSmooth(0                  ,Smooth,SmoothPhase,SmoothDouble,i,60);
               sig[i] = iDSmooth(dmx[i],SignalLength,SignalPhase,SignalDouble,i,80);
               
               slope[i] = (i<Bars-1) ? (dmx[i]>dmx[i+1]) ? 1 : (dmx[i]<dmx[i+1]) ? -1 : slope[i+1] : 0;  
               trend[i] = (i<Bars-1) ? (dmx[i]>0)        ? 1 : (dmx[i]<0)        ? -1 : trend[i+1] : 0;
               Upa[i] = (trend[i] == 1 && slope[i] == 1) ? dmx[i] : EMPTY_VALUE;
               Upb[i] = (trend[i] == 1 && slope[i] ==-1) ? dmx[i] : EMPTY_VALUE;
               Dna[i] = (trend[i] ==-1 && slope[i] ==-1) ? dmx[i] : EMPTY_VALUE;
               Dnb[i] = (trend[i] ==-1 && slope[i] == 1) ? dmx[i] : EMPTY_VALUE; 
          }               
      }
return(0);
} 
      
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//

double wrk[][100];

#define bsmax  5
#define bsmin  6
#define volty  7
#define vsum   8
#define avolty 9

double iDSmooth(double price, double length, double phase, bool isDouble, int i, int s=0) 
{
   if (isDouble)
         return (iSmooth(iSmooth(price,MathSqrt(length),phase,i,s),MathSqrt(length),phase,i,s+10));
   else  return (iSmooth(price,length,phase,i,s));
}

//
//
//
//
//

double iSmooth(double price, double length, double phase, int i, int s=0)
{
   if (length <=1) return(price);
   if (ArrayRange(wrk,0) != Bars) ArrayResize(wrk,Bars);
   
   int r = Bars-i-1; 
      if (r==0) { int k; for(k=0; k<7; k++) wrk[r][k+s]=price; for(; k<10; k++) wrk[r][k+s]=0; return(price); }

   //
   //
   //
   //
   //
   
      double len1   = MathMax(MathLog(MathSqrt(0.5*(length-1)))/MathLog(2.0)+2.0,0);
      double pow1   = MathMax(len1-2.0,0.5);
      double del1   = price - wrk[r-1][bsmax+s];
      double del2   = price - wrk[r-1][bsmin+s];
      double div    = 1.0/(10.0+10.0*(MathMin(MathMax(length-10,0),100))/100);
      int    forBar = MathMin(r,10);
	
         wrk[r][volty+s] = 0;
               if(MathAbs(del1) > MathAbs(del2)) wrk[r][volty+s] = MathAbs(del1); 
               if(MathAbs(del1) < MathAbs(del2)) wrk[r][volty+s] = MathAbs(del2); 
         wrk[r][vsum+s] =	wrk[r-1][vsum+s] + (wrk[r][volty+s]-wrk[r-forBar][volty+s])*div;
         
         //
         //
         //
         //
         //
   
         wrk[r][avolty+s] = wrk[r-1][avolty+s]+(2.0/(MathMax(4.0*length,30)+1.0))*(wrk[r][vsum+s]-wrk[r-1][avolty+s]);
            double dVolty = 0;
            if (wrk[r][avolty+s] > 0)
                  dVolty = wrk[r][volty+s]/wrk[r][avolty+s];   
	               if (dVolty > MathPow(len1,1.0/pow1)) dVolty = MathPow(len1,1.0/pow1);
                  if (dVolty < 1)                      dVolty = 1.0;

      //
      //
      //
      //
      //
	        
   	double pow2 = MathPow(dVolty, pow1);
      double len2 = MathSqrt(0.5*(length-1))*len1;
      double Kv   = MathPow(len2/(len2+1), MathSqrt(pow2));

         if (del1 > 0) wrk[r][bsmax+s] = price; else wrk[r][bsmax+s] = price - Kv*del1;
         if (del2 < 0) wrk[r][bsmin+s] = price; else wrk[r][bsmin+s] = price - Kv*del2;
	
   //
   //
   //
   //
   //
      
      double R     = MathMax(MathMin(phase,100),-100)/100.0 + 1.5;
      double beta  = 0.45*(length-1)/(0.45*(length-1)+2);
      double alpha = MathPow(beta,pow2);

         wrk[r][0+s] = price + alpha*(wrk[r-1][0+s]-price);
         wrk[r][1+s] = (price - wrk[r][0+s])*(1-beta) + beta*wrk[r-1][1+s];
         wrk[r][2+s] = (wrk[r][0+s] + R*wrk[r][1+s]);
         wrk[r][3+s] = (wrk[r][2+s] - wrk[r-1][4+s])*MathPow((1-alpha),2) + MathPow(alpha,2)*wrk[r-1][3+s];
         wrk[r][4+s] = (wrk[r-1][4+s] + wrk[r][3+s]); 

   //
   //
   //
   //
   //

return(wrk[r][4+s]);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

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("");
}


