//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www,forex-station.com"
#property link      "www,forex-station.com"

#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1  clrLimeGreen
#property indicator_color2  clrOrange
#property indicator_color3  clrOrange
#property indicator_color4  clrDeepSkyBlue
#property indicator_color5  clrPaleVioletRed
#property indicator_style4  STYLE_DOT
#property indicator_style5  STYLE_DOT
#property strict

//
//
//
//
//

#import "dynamicZone.dll"
   double dzBuyP(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i, double precision);
   double dzSellP(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i, double precision);
#import

//
//
//
//
//

extern ENUM_TIMEFRAMES    TimeFrame         = PERIOD_CURRENT;  // Time frame
extern double             Length            = 20;              // Bband Ma Length
extern ENUM_MA_METHOD     MaMethod          = 0;               // Bband Ma Method
extern ENUM_APPLIED_PRICE Price             = 0;               // Bband Price
extern double             Deviation         = 0.5;             // Bband standard deviation
extern int                DzLookBackBars    = 35;              // Dynamic zone lookback
extern double             DzBuyProbability  = 0.1;             // Dynamic zone buy probability
extern double             DzSellProbability = 0.1;             // Dynamic zone sell probability
extern int                LinesWidth        = 3;               // Bband line width 
extern bool               Interpolate       = true;            // Interpolate in multi time frame mode?

//
//
//
//
//

double bbLine[],buffer2[],buffer3[],up[],dn[],smax[],smin[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_y) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Length,MaMethod,Price,Deviation,DzLookBackBars,DzBuyProbability,DzSellProbability,LinesWidth,_buff,_y)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   if (!IsDllsAllowed())
   {
      Alert("and then attach it to the chart again");
      Alert("Please enable DLL imports in the indicator properties");
      Alert("This indicator needs the dynamicZone.dll to work");
      return(INIT_FAILED);
   }
   IndicatorBuffers(9);
      SetIndexBuffer(0,bbLine);  SetIndexStyle(0,DRAW_LINE,EMPTY,LinesWidth);
      SetIndexBuffer(1,buffer2); SetIndexStyle(1,DRAW_LINE,EMPTY,LinesWidth);
      SetIndexBuffer(2,buffer3); SetIndexStyle(2,DRAW_LINE,EMPTY,LinesWidth); 
      SetIndexBuffer(3,up);
      SetIndexBuffer(4,dn);
      SetIndexBuffer(5,smax);
      SetIndexBuffer(6,smin);
      SetIndexBuffer(7,trend);
      SetIndexBuffer(8,count);
      
      indicatorFileName = WindowExpertName();
      TimeFrame         = fmax(TimeFrame,_Period);  
      
   IndicatorShortName(timeFrameToString(TimeFrame)+" Bollinger band stops line("+(string)Length+","+(string)Deviation+")");
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));
               if (trend[limit]==-1) CleanPoint(limit,buffer2,buffer3);
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     bbLine[i]  = _mtfCall(0,y);
                     buffer2[i] = EMPTY_VALUE;
                     buffer3[i] = EMPTY_VALUE;
                     up[i]      = _mtfCall(3,y);
                     dn[i]      = _mtfCall(4,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(bbLine);
                               _interpolate(up);
                               _interpolate(dn);
                            }
              }
              for (i=limit; i >= 0; i--) if (trend[i]==-1) PlotPoint(i,buffer2,buffer3,bbLine);
            return(0);
           }

   //
   //
   //
   //
   //
   
   if (trend[limit]==-1) CleanPoint(limit,buffer2,buffer3);
   for(i=limit; i>=0; i--)
   { 
      bbLine[i]  = ibbLine(Length,MaMethod,Price,Deviation,i);
      up[i]      = dzSellP(bbLine,DzSellProbability,DzLookBackBars,Bars,i,0.00001);
      dn[i]      = dzBuyP (bbLine,DzBuyProbability ,DzLookBackBars,Bars,i,0.00001);
      buffer2[i] = EMPTY_VALUE;
      buffer3[i] = EMPTY_VALUE;
      if (i<Bars-1) { if (trend[i]==-1) PlotPoint(i,buffer2,buffer3,bbLine);  }         
   }
return(0);
}

//
//
//
//
//

double workBb[][3];
#define smin    0
#define smax    1
#define _trend  2

double ibbLine(double _Length, double _MaMethod, double _Price, double _Deviation, int i)
{
      if (ArrayRange(workBb,0)!=Bars) ArrayResize(workBb,Bars);
      int r = Bars-i-1; 
      
      double StdDev = iStdDev(NULL,0,(int)Length,0,MODE_SMA,Price,i);
      double ma     = iMA(NULL,0,(int)Length,0,MaMethod,Price,i);
      double result = 0; 
      
      //
      //
      //
      //
      //
      
      if (r==0)
      {
         workBb[r][smax]   = ma + (StdDev*Deviation);
         workBb[r][smin]   = ma - (StdDev*Deviation);
         workBb[r][_trend] = 0;
         return(Close[i]);
      }
      
      //
      //
      //
      //
      //
      
      workBb[r][smax]   = ma + (StdDev*Deviation);
      workBb[r][smin]   = ma - (StdDev*Deviation);
      workBb[r][_trend] = workBb[r-1][_trend];
      if (Close[i]>workBb[r-1][smax]) workBb[r][_trend] = 1; 
	   if (Close[i]<workBb[r-1][smin]) workBb[r][_trend] =-1; 
	   if (workBb[r][_trend] ==  1) 
	   { 
	     if (workBb[r][smin] < workBb[r-1][smin]) workBb[r][smin]=workBb[r-1][smin]; result = workBb[r][smin]; 
	   }
      if (workBb[r][_trend] == -1) 
      { 
        if (workBb[r][smax] > workBb[r-1][smax]) workBb[r][smax]=workBb[r-1][smax]; result = workBb[r][smax]; 
      }
      trend[Bars-r-1] = workBb[r][_trend];
      
return(result);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = 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 (i>=Bars-2) return;
   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; }
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

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("");
}



   