//+------------------------------------------------------------------+
//|                                                          EMI.mq4 |
//|                                 Copyright © 2009, Roman Robidet. |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Roman Robidet."

#property indicator_separate_window
#property indicator_buffers 6
#property indicator_color1  clrDodgerBlue
#property indicator_color2  clrLimeGreen
#property indicator_color3  clrLimeGreen
#property indicator_color4  clrRed
#property indicator_color5  clrRed
#property indicator_color6  clrPeru
#property indicator_width1  2
#property indicator_style3  STYLE_DOT
#property indicator_style4  STYLE_DOT
#property indicator_style6  STYLE_DASH

//
//
//
//
//

#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             EMIPeriod               = 13;
extern int             SmoothPeriod            = 0;
extern bool            ShowMiddleLine          = true;
extern int             DzLookBackBars          = 49;
extern double          DzStartBuyProbability1  = 0.10;
extern double          DzStartBuyProbability2  = 0.25;
extern double          DzStartSellProbability1 = 0.10;
extern double          DzStartSellProbability2 = 0.25;

double EMIBuffer[];
double PosBuffer[];
double NegBuffer[];
double bl1[];
double bl2[];
double sl1[];
double sl2[];
double zli[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(6);
   SetIndexBuffer(0,EMIBuffer);
   SetIndexBuffer(1,bl1);
   SetIndexBuffer(2,bl2);
   SetIndexBuffer(3,sl2);
   SetIndexBuffer(4,sl1);
   SetIndexBuffer(5,zli);
   IndicatorShortName("EMI("+EMIPeriod+")");
return(0);
  }

int start()
{
   int  k;
   double _H,sumaEMI,EMV;
   double _B;
   double _HP;
   double _BP;
   double _V;
   int limit;
   int counted_bars=IndicatorCounted();

   if(counted_bars<0) return(-1);

   if(counted_bars>0) counted_bars--;
   limit=MathMin(Bars-counted_bars,Bars-1);
   for(int i=limit; i>=0; i--)
   {
           sumaEMI=0;
            for(k=0;k<EMIPeriod && (i+k+1)<Bars;k++)
            {
   
            _H=High[i+k];
            _B=Low[i+k];
            _HP=High[i+1+k];
            _BP=Low[i+1+k];
            _V=Volume[i+k];
            if ((_H-_B )!=0)
                  EMV=(((_H + _B ) / 2 ) - (( _HP + _BP )/2)) / ( _V / ( _H - _B )) * 10000000000 ;
            else  EMV=0;         
           sumaEMI=sumaEMI + EMV; 
         
            }
            EMIBuffer[i]=iSsm(sumaEMI/ EMIPeriod,SmoothPeriod,i);
            if (DzStartBuyProbability1 >0) bl1[i] = dzBuyP (EMIBuffer, DzStartBuyProbability1,  DzLookBackBars, Bars, i, 0.0001);
            if (DzStartBuyProbability2 >0) bl2[i] = dzBuyP (EMIBuffer, DzStartBuyProbability2,  DzLookBackBars, Bars, i, 0.0001);
            if (DzStartSellProbability1>0) sl1[i] = dzSellP(EMIBuffer, DzStartSellProbability1, DzLookBackBars, Bars, i, 0.0001);
            if (DzStartSellProbability2>0) sl2[i] = dzSellP(EMIBuffer, DzStartSellProbability2, DzLookBackBars, Bars, i, 0.0001);
            if (ShowMiddleLine)            zli[i] = dzSellP(EMIBuffer, 0.5                    , DzLookBackBars, Bars, i, 0.0001);
   }
   return(0);
}

//+------------------------------------------------------------------+

#define Pi 3.14159265358979323846264338327950288
double workSsm[][2];
#define _tprice  0
#define _ssm     1

double workSsmCoeffs[][4];
#define _speriod 0
#define _sc1    1
#define _sc2    2
#define _sc3    3

double iSsm(double price, double period, int i, int instanceNo=0)
{
   if (period<=1) return(price); i = Bars-i-1;
   if (ArrayRange(workSsm,0) !=Bars)                 ArrayResize(workSsm,Bars);
   if (ArrayRange(workSsmCoeffs,0) < (instanceNo+1)) ArrayResize(workSsmCoeffs,instanceNo+1);
   if (workSsmCoeffs[instanceNo][_speriod] != period)
   {
      workSsmCoeffs[instanceNo][_speriod] = period;
      double a1 = MathExp(-1.414*Pi/period);
      double b1 = 2.0*a1*MathCos(1.414*Pi/period);
         workSsmCoeffs[instanceNo][_sc2] = b1;
         workSsmCoeffs[instanceNo][_sc3] = -a1*a1;
         workSsmCoeffs[instanceNo][_sc1] = 1.0 - workSsmCoeffs[instanceNo][_sc2] - workSsmCoeffs[instanceNo][_sc3];
   }

   //
   //
   //
   //
   //

      int s = instanceNo*2; 
      workSsm[i][s+_ssm]    = price;
      workSsm[i][s+_tprice] = price;
      if (i>1)
      {  
          workSsm[i][s+_ssm] = workSsmCoeffs[instanceNo][_sc1]*(workSsm[i][s+_tprice]+workSsm[i-1][s+_tprice])/2.0 + 
                               workSsmCoeffs[instanceNo][_sc2]*workSsm[i-1][s+_ssm]                                + 
                               workSsmCoeffs[instanceNo][_sc3]*workSsm[i-2][s+_ssm]; }
   return(workSsm[i][s+_ssm]);
}