
#property link      "www.forex-tsd.com"      
#property copyright "www.forex-tsd.com"                           

#property indicator_separate_window
#property indicator_buffers    7
#property indicator_color1     clrLimeGreen
#property indicator_color2     clrOrange
#property indicator_color3     clrOrange
#property indicator_color4     clrRed
#property indicator_color5     clrDarkSlateGray
#property indicator_color6     clrDarkSlateGray
#property indicator_color7     clrDarkSlateGray
#property indicator_width1     2
#property indicator_width2     2
#property indicator_width3     2
#property indicator_style4     STYLE_DASHDOT
#property indicator_style5     STYLE_DOT
#property indicator_style6     STYLE_DOT
#property indicator_style7     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

//
//
//
//
//

enum colorOn
{
   clrOnSlope, //Color change on slope change
   clrOnZero,  // Color change on zero cross
   clrOnSign   // Color change on signal cross
};

extern double  Length1                = 35.0;        // Oma length1
extern double  Length2                = 7.0;         // Oma length2
extern double  Length3                = 7.0;         // Oma length3(signal length)
extern double  Speed                  = 1.0;         // Oma speed 
extern bool    Adaptive               = false;       // Should it be adaptive?
extern int     DzLookBackBars         = 70;          // Dynamic zone look back
extern double  DzStartBuyProbability  = 0.95;        // Dynamic zone buy probability
extern double  DzStartSellProbability = 0.95;        // Dynamic zone buy probability
extern colorOn ColorChangeOn          = clrOnSlope;  // Color change on : 

//
//
//
//
//

double eco[];
double ecoDa[];
double ecoDb[];
double sig[];
double sli[];
double bli[];
double zli[];
double trend[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0,eco);
   SetIndexBuffer(1,ecoDa);
   SetIndexBuffer(2,ecoDb);
   SetIndexBuffer(3,sig);
   SetIndexBuffer(4,bli);
   SetIndexBuffer(5,sli);
   SetIndexBuffer(6,zli);
   SetIndexBuffer(7,trend);
 
   Length1 = MathMax(Length1,1);
   Length2 = MathMax(Length2,1);
   Length3 = MathMax(Length3,1);
   Speed   = MathMax(Speed,-1.5);
   IndicatorShortName("Dynamic zone Blau Eco on oma ("+DoubleToStr(Length1,1)+","+DoubleToStr(Length2,1)+","+DoubleToStr(Length3,1)+")");   
return(0);
}

int deinit()
{
   
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);

   //
   //
   //
   //
   //
   
   if (trend[limit]==-1) CleanPoint(limit,ecoDa,ecoDb);
   for (int i = limit; i >= 0; i--)
   { 
      double co = iAverage(iAverage(Close[i]- Open[i],Length1,Speed,Adaptive,i,0),Length2,Speed,Adaptive,i,1);
      double hl = iAverage(iAverage(High[i] - Low[i], Length1,Speed,Adaptive,i,2),Length2,Speed,Adaptive,i,3);
         
            if (hl!=0)
                  eco[i] = 100.0*co/hl;
            else  eco[i] = 0;                 
            
            sig[i] = iAverage(eco[i],Length3,Speed,Adaptive,i,4);
            bli[i] = dzBuyP (eco, DzStartBuyProbability, DzLookBackBars,Bars,i,0.0001);
            sli[i] = dzSellP(eco, DzStartSellProbability,DzLookBackBars,Bars,i,0.0001);
            zli[i] = dzSellP(eco, 0.5,                   DzLookBackBars,Bars,i,0.0001);
            
            if (i>=Bars-1) continue;
            
            //
            //
            //
            //
            //
            
            ecoDa[i] = EMPTY_VALUE;
            ecoDb[i] = EMPTY_VALUE;             
            trend[i] = trend[i+1];
            switch (ColorChangeOn)
            {
               case clrOnSlope: 
                  if (eco[i]>eco[i+1]) trend[i] =  1;
                  if (eco[i]<eco[i+1]) trend[i] = -1;
               break;
               case clrOnZero: 
                  if (eco[i]>zli[i])   trend[i] =  1;
                  if (eco[i]<zli[i])   trend[i] = -1;
               break;
               default : 
                  if (eco[i]>sig[i])   trend[i] =  1;
                  if (eco[i]<sig[i])   trend[i] = -1;
               break;
            }    
            if (trend[i] == -1) PlotPoint(i,ecoDa,ecoDb,eco);  
      }
return(0);
}   

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

#define omaInstances 5
double workOma[][omaInstances*7];
#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 tconst, bool adaptive, int i, int instanceNo=0)
{
   if (averagePeriod <=1) return(price); int r = Bars-i-1; instanceNo *= 7;
   if (ArrayRange(workOma,0)!=Bars) ArrayResize(workOma,Bars);
   
   double e1=workOma[(int)MathMax(r-1,0)][instanceNo+E1];  double e2=workOma[(int)MathMax(r-1,0)][instanceNo+E2];
   double e3=workOma[(int)MathMax(r-1,0)][instanceNo+E3];  double e4=workOma[(int)MathMax(r-1,0)][instanceNo+E4];
   double e5=workOma[(int)MathMax(r-1,0)][instanceNo+E5];  double e6=workOma[(int)MathMax(r-1,0)][instanceNo+E6];

   //
   //
   //
   //
   //

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

            for(int k=1; k<endPeriod && r-k>=0; k++) noise=noise+MathAbs(price-workOma[r-k][instanceNo+res]);

         averagePeriod = ((signal/noise)*(maxPeriod-minPeriod))+minPeriod;
      }
      
      //
      //
      //
      //
      //
      
      double alpha = (2.0+tconst)/(1.0+tconst+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;

   //
   //
   //
   //
   //

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

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

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; }
}

