//+------------------------------------------------------------------+
//|                                             One more average.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers    7
#property indicator_color1     DeepSkyBlue
#property indicator_color2     Red
#property indicator_color3     LimeGreen
#property indicator_color4     LimeGreen
#property indicator_color5     Red
#property indicator_color6     Red
#property indicator_color7     DimGray
#property indicator_style4     STYLE_DOT
#property indicator_style5     STYLE_DOT
#property indicator_style7     STYLE_DOT
#property indicator_width1     2


//
//
//
//
//

#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 int    FastLength              = 12;
extern int    FastPrice               = PRICE_CLOSE;
extern double FastSpeed               = 1.0;
extern int    SlowLength              = 26;
extern int    SlowPrice               = PRICE_CLOSE;
extern double SlowSpeed               = 1.0;
extern int    SignalLength            = 0;
extern double SignalSpeed             = 1.0;
extern bool   Adaptive                = true;
extern bool   ShowZeroLine            = true;
extern int    DzLookBackBars          = 35;
extern double DzStartBuyProbability1  = 0.10;
extern double DzStartBuyProbability2  = 0.00;
extern double DzStartSellProbability1 = 0.10;
extern double DzStartSellProbability2 = 0.00;

//
//
//
//
//

double macd[];
double signal[];
double bl1Buffer[];
double bl2Buffer[];
double sl1Buffer[];
double sl2Buffer[];
double zliBuffer[];
double stored[][21];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   SetIndexBuffer(0,macd);
   SetIndexBuffer(1,signal);
   SetIndexBuffer(2,bl1Buffer);
   SetIndexBuffer(3,bl2Buffer);
   SetIndexBuffer(4,sl2Buffer);
   SetIndexBuffer(5,sl1Buffer);
   SetIndexBuffer(6,zliBuffer);
         FastLength   = MathMax(FastLength,1);
         SlowLength   = MathMax(SlowLength,1);
         SignalLength = MathMax(SignalLength,1);
         FastSpeed    = MathMax(FastSpeed,-1.5);
         SlowSpeed    = MathMax(SlowSpeed,-1.5);
         SignalSpeed  = MathMax(SignalSpeed,-1.5);
   IndicatorShortName("One more average ("+FastLength+","+SlowLength+")");
   return(0);
}
int deinit() { return(0); }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,r,limit;

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = Bars-counted_bars;
         if (ArrayRange(stored,0) != Bars) ArrayResize(stored,Bars);
         if (Digits>3)
            double precision = 0.001;
         else      precision = 0.1;            
         

   //
   //
   //
   //
   //

   for(i=limit, r=Bars-limit-1; i>=0; i--,r++)
   {
      double fastOma = iAverage(iMA(NULL,0,1,0,MODE_SMA,FastPrice,i),FastLength,FastSpeed,Adaptive,r,0);
      double slowOma = iAverage(iMA(NULL,0,1,0,MODE_SMA,SlowPrice,i),SlowLength,SlowSpeed,Adaptive,r,7);
      
         macd[i]   = fastOma - slowOma;
      if (SignalLength>1)            signal[i] = iAverage(macd[i],SignalLength,SignalSpeed,Adaptive,r,14);
      if (DzStartBuyProbability1 >0) bl1Buffer[i] = dzBuyP (macd, DzStartBuyProbability1,  DzLookBackBars, Bars, i, precision);
      if (DzStartBuyProbability2 >0) bl2Buffer[i] = dzBuyP (macd, DzStartBuyProbability2,  DzLookBackBars, Bars, i, precision);
      if (DzStartSellProbability1>0) sl1Buffer[i] = dzSellP(macd, DzStartSellProbability1, DzLookBackBars, Bars, i, precision);
      if (DzStartSellProbability2>0) sl2Buffer[i] = dzSellP(macd, DzStartSellProbability2, DzLookBackBars, Bars, i, precision);
      if (ShowZeroLine)              zliBuffer[i] = dzSellP(macd, 0.5                    , DzLookBackBars, Bars, i, precision);
   }      
   return(0);
}



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define E1  0
#define E2  1
#define E3  2
#define E4  3
#define E5  4
#define E6  5
#define res 6

//
//
//
//
//

double iAverage(double price, double averagePeriod, double const1, bool adaptive, int r, int ashift=0)
{
   double e1=stored[r-1][E1+ashift];  double e2=stored[r-1][E2+ashift];
   double e3=stored[r-1][E3+ashift];  double e4=stored[r-1][E4+ashift];
   double e5=stored[r-1][E5+ashift];  double e6=stored[r-1][E6+ashift];

   //
   //
   //
   //
   //

      if (adaptive && (averagePeriod > 1))
      {
         double minPeriod = averagePeriod/2.0;
         double maxPeriod = minPeriod*5.0;
         int    endPeriod = MathCeil(maxPeriod);
         double signal    = MathAbs((price-stored[r-endPeriod][res]));
         double noise     = 0.00000000001;

            for(int k=1; k<endPeriod; k++) noise=noise+MathAbs(price-stored[r-k][res]);

         averagePeriod = ((signal/noise)*(maxPeriod-minPeriod))+minPeriod;
      }
      
      //
      //
      //
      //
      //
      
      double alpha = (2.0+const1)/(1.0+const1+averagePeriod);

      e1 = e1 + alpha*(price-e1); e2 = e2 + alpha*(e1-e2); double v1 = 1.5 * e1 - 0.5 * e2;
      e3 = e3 + alpha*(v1   -e3); e4 = e4 + alpha*(e3-e4); double v2 = 1.5 * e3 - 0.5 * e4;
      e5 = e5 + alpha*(v2   -e5); e6 = e6 + alpha*(e5-e6); double v3 = 1.5 * e5 - 0.5 * e6;

   //
   //
   //
   //
   //

   stored[r][E1+ashift]  = e1;  stored[r][E2+ashift] = e2;
   stored[r][E3+ashift]  = e3;  stored[r][E4+ashift] = e4;
   stored[r][E5+ashift]  = e5;  stored[r][E6+ashift] = e6;
   stored[r][res+ashift] = price;
   return(v3);
}