//+------------------------------------------------------------------+
//|                                                        DPO_BB.mq4|
//|                                                           Mobidik|
//|                                                              2015|
//+------------------------------------------------------------------+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#property link ""
#property strict
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1  clrGold
#property indicator_color2  clrSteelBlue
#property indicator_color3  clrGray
#property indicator_color4  clrSteelBlue
#property indicator_style3  2
#property strict
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
extern ENUM_TIMEFRAMES    TimeFrame          = PERIOD_CURRENT;   // Time frame
extern int                DPO_Period         = 14;               // Dpo period
extern ENUM_APPLIED_PRICE DPO_Price          = PRICE_CLOSE;      // Dpo price
extern ENUM_MA_METHOD     DPO_Method         = MODE_SMMA;        // Dpo ma method
extern int                BollingerPeriod    = 21;               // Bollinger period
extern double             BollingerDeviation = 1;                // Bollinger deviation
extern int                BollingerShift     = 0;                // Bollinger shift
extern bool               Interpolate        = true;             // Interpolate in mtf mode

double dpo[],BUpper[],BMiddle[],BLower[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,DPO_Period,DPO_Price,DPO_Method,BollingerPeriod,BollingerDeviation,0,_buff,_ind)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
 {
  IndicatorBuffers(5);
  SetIndexBuffer(0, dpo);     SetIndexLabel (0, "DPO");
  SetIndexBuffer(1, BUpper);  SetIndexLabel (1, "BB Up");
  SetIndexBuffer(2, BMiddle); SetIndexLabel (2, "BB Middle");
  SetIndexBuffer(3, BLower);  SetIndexLabel (3, "BB Dn");
  SetIndexBuffer(4, count);
   
  indicatorFileName = WindowExpertName();
  TimeFrame         = fmax(TimeFrame,_Period);
  
  for (int i=0; i<7; i++) SetIndexShift(i,BollingerShift*TimeFrame/Period());
  
  IndicatorShortName(timeFrameToString(TimeFrame)+" DPO-BB");
return(0);
 }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//+------------------------------------------------------------------+
//| DPO-BB                                                           |
//+------------------------------------------------------------------+
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)
   {
     int shift = DPO_Period/2+1;       
     for(i=limit; i>=0; i--) dpo[i] = iMA(NULL,0,1,0,DPO_Method,DPO_Price,i)-iMA(NULL,0,DPO_Period,0,DPO_Method,DPO_Price,i+shift);
     for(i=limit; i>=0; i--)
     {
        BUpper [i] = iBandsOnArray(dpo,0,BollingerPeriod,BollingerDeviation,BollingerShift,MODE_UPPER,i);
        BMiddle[i] = iBandsOnArray(dpo,0,BollingerPeriod,BollingerDeviation,BollingerShift,MODE_MAIN, i);
        BLower [i] = iBandsOnArray(dpo,0,BollingerPeriod,BollingerDeviation,BollingerShift,MODE_LOWER,i);
     } 
   return(0);
   }
   
   //
   //
   //
   //
   //
   
   limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(4,0)*TimeFrame/_Period));
   for (i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,TimeFrame,Time[i]);
         dpo[i]     = _mtfCall(0,y);
         BUpper[i]  = _mtfCall(1,y);
         BMiddle[i] = _mtfCall(2,y);
         BLower[i]  = _mtfCall(3,y);
         
         //
         //
         //
         //
         //
      
         if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
            #define _interpolate(buff) buff[i+j] = buff[i]+(buff[i+n]-buff[i])*j/n
            int n,j; datetime time = iTime(NULL,TimeFrame,y);
               for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
               for(j = 1; j<n && (i+n)<Bars && (i+j)<Bars; j++) 
               {
                  _interpolate(dpo);
                  _interpolate(BUpper);
                  _interpolate(BMiddle);
                  _interpolate(BLower);
               }                           
   }
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("");
}
