//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www.forex-station.com"
//------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 clrLimeGreen
#property indicator_color2 clrOrange
#property indicator_color3 clrSilver
#property indicator_color4 clrRed
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 3
#property indicator_level1 0
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame     = PERIOD_CURRENT;  // Time frame
extern bool            BetterFormula = false;           // Use better formula?
extern int             SmoothPeriod  = 6;               // Smoothing period
extern int             SmoothMethod  = MODE_LWMA;       // Smoothing method
extern int             SignalPeriod  = 3;               // Signal period
extern ENUM_MA_METHOD  SignalMethod  = MODE_SMA;        // Signal method
extern bool            Interpolate   = true;            // Interpolate in multi time frame mode?

double haUp[],haDn[],bhaOpn[],bhaClo[],haDelta[],haSignal[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,0,BetterFormula,SmoothPeriod,SmoothMethod,SignalPeriod,SignalMethod,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorDigits(6);
   IndicatorBuffers(7);
   SetIndexBuffer(0, haUp); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1, haDn); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2, haDelta);
   SetIndexBuffer(3, haSignal);
   SetIndexBuffer(4, bhaOpn);
   SetIndexBuffer(5, bhaClo);
   SetIndexBuffer(6, count);

      //
      //
      //
      //
      //
      
         indicatorFileName = WindowExpertName();
         TimeFrame         = MathMax(TimeFrame,_Period);
   IndicatorShortName(timeFrameToString(TimeFrame)+" haDelta ("+(string)SignalPeriod+")");
   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-1); count[0] = limit;
         if (TimeFrame!=_Period)
         {
            limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(6,0)*TimeFrame/Period()));
            for (int i=limit; i>=0; i--)
            {
               int y = iBarShift(NULL,TimeFrame,Time[i]);
                  haDelta[i]  = _mtfCall(2,y);
                  haSignal[i] = _mtfCall(3,y);
                  haUp[i]     = EMPTY_VALUE;
                  haDn[i]     = EMPTY_VALUE;
                     if (haDelta[i]>0) haUp[i] = haDelta[i];
                     if (haDelta[i]<0) haDn[i] = haDelta[i];
                  
                  //
                  //
                  //
                  //
                  //
                  
                  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(haDelta);
                        _interpolate(haSignal);
                           if (haUp[i+k]!=EMPTY_VALUE) haUp[i+k] = haDelta[i+k];
                           if (haDn[i+k]!=EMPTY_VALUE) haDn[i+k] = haDelta[i+k];
                      }                           
            }
            return(0);
         }            
          
   //
   //
   //
   //
   //
   
      for (int i=limit; i >= 0; i--)
      {
         double prOpen  = iMA(NULL,0,SmoothPeriod,0,SmoothMethod,PRICE_OPEN ,i);
         double prClose = iMA(NULL,0,SmoothPeriod,0,SmoothMethod,PRICE_CLOSE,i);
         double prLow   = iMA(NULL,0,SmoothPeriod,0,SmoothMethod,PRICE_LOW  ,i);
         double prHigh  = iMA(NULL,0,SmoothPeriod,0,SmoothMethod,PRICE_HIGH ,i);
         double haClose = 0;
         if (BetterFormula) {
               if (prHigh!=prLow)
                            haClose = (prOpen+prClose)/2.0+(((prClose-prOpen)/(prHigh-prLow))*MathAbs((prClose-prOpen)/2.0));
                     else   haClose = (prOpen+prClose)/2.0; }
          else              haClose = (prOpen+prHigh+prLow+prClose)/4;
                     double haOpen  = (i<Bars-1) ? (bhaOpn[i+1]+bhaClo[i+1])/2.0 : prOpen;

         //
         //
         //
         //
         //
         
         bhaOpn[i]  = haOpen;
         bhaClo[i]  = haClose;
         haDelta[i] = haClose-haOpen;
         haUp[i]    = EMPTY_VALUE;
         haDn[i]    = EMPTY_VALUE;
           if (haDelta[i]>0) haUp[i] = haDelta[i];
           if (haDelta[i]<0) haDn[i] = haDelta[i];
      }
      for (int i=limit; i >= 0; i--) haSignal[i] = iMAOnArray(haDelta,0,SignalPeriod,0,SignalMethod,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("");
}
