//+------------------------------------------------------------------+
//|                                          dynamic zone stochastic |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrRed
#property indicator_color3  clrLimeGreen
#property indicator_color4  clrRed
#property indicator_color5  clrGold
#property indicator_width1  2
#property indicator_style2  STYLE_DOT
#property indicator_style5  STYLE_DOT
#property indicator_minimum 0
#property indicator_maximum 100

//
//
//
//
//

#import "dynamicZone.dll"
   double dzBuy(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i );
   double dzSell(double& sourceArray[],double probabiltyValue, int lookBack, int bars, int i );
#import

//
//
//
//
//

extern int                StoKPeriod               = 14;
extern int                StoDPeriod               =  3;
extern int                StoSlowingPeriod         =  3;
extern ENUM_MA_METHOD     StoMaMethod              = MODE_SMA;
extern ENUM_APPLIED_PRICE StochasticHighPrice      = PRICE_HIGH;
extern ENUM_APPLIED_PRICE StochasticLowPrice       = PRICE_LOW;
extern ENUM_APPLIED_PRICE StochasticClosePrice     = PRICE_CLOSE;
extern int                DzLookBackBars           = 70;
extern double             DzStartBuyProbability    = 0.10;
extern double             DzStartSellProbability   = 0.10;
extern bool               arrowsVisible            = true;
extern string             arrowsIdentifier         = "dzsto arrows1";
extern double             arrowsUpperGap           = 0.5;
extern double             arrowsLowerGap           = 0.5;
extern bool               arrowsOnObOsCross        = true;
extern color              arrowsOnObOsCrossUpColor = clrLimeGreen;
extern color              arrowsOnObOsCrossDnColor = clrRed;
extern int                arrowsOnObOsCrossUpCode  = 241;
extern int                arrowsOnObOsCrossDnCode  = 242;
extern bool               arrowsOnCross            = true;
extern color              arrowsOnCrossUpColor     = clrLimeGreen;
extern color              arrowsOnCrossDnColor     = clrRed;
extern int                arrowsOnCrossUpCode      = 159;
extern int                arrowsOnCrossDnCode      = 159;
extern bool               alertsOn                 = true;
extern bool               alertsOnCurrent          = false;
extern bool               alertsOnObOsCross        = true;
extern bool               alertsOnCross            = true;
extern bool               alertsMessage            = true;
extern bool               alertsSound              = false;
extern bool               alertsNotify             = false;
extern bool               alertsEmail              = false;
extern string             soundFile                = "alert2.wav";

//
//
//
//
//

double sto[];
double sig[];
double bli[];
double sli[];
double zli[];
double trend[];
double cross[];

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

int init()
{
   IndicatorBuffers(7);
   SetIndexBuffer(0,sto);
   SetIndexBuffer(1,sig);
   SetIndexBuffer(2,bli);
   SetIndexBuffer(3,sli);
   SetIndexBuffer(4,zli);
   SetIndexBuffer(5,trend);
   SetIndexBuffer(6,cross);
   
   //
   //
   //
   //
   //
      
   IndicatorShortName("Dynamic zone stochastic ("+StoKPeriod+","+StoDPeriod+","+StoSlowingPeriod+","+DzLookBackBars+","+DoubleToStr(DzStartBuyProbability,3)+","+DoubleToStr(DzStartSellProbability,3)+")");
return(0);
}
int deinit()
{
   deleteArrows();
return(0);
}

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

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

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = MathMin(Bars-counted_bars,Bars-1);

   //
   //
   //
   //
   //
   
   for(i=limit; i>=0; i--) sto[i] = iStoch(iMA(NULL,0,1,0,MODE_SMA,StochasticClosePrice,i),
                                           iMA(NULL,0,1,0,MODE_SMA,StochasticHighPrice ,i),
                                           iMA(NULL,0,1,0,MODE_SMA,StochasticLowPrice  ,i),StoKPeriod,StoSlowingPeriod,i);
   for(i=limit; i>=0; i--)
   {
      sig[i] = iMAOnArray(sto,0,StoDPeriod,0,StoMaMethod,i);
      bli[i] = dzBuy (sto, DzStartBuyProbability,  DzLookBackBars, Bars, i);
      sli[i] = dzSell(sto, DzStartSellProbability, DzLookBackBars, Bars, i);
      zli[i] = dzSell(sto, 0.5,                    DzLookBackBars, Bars, i);
      trend[i] = 0;
      cross[i] = cross[i+1];
         if (sto[i]>sig[i] && sto[i]<bli[i]) trend[i] = 1;
         if (sto[i]<sig[i] && sto[i]>sli[i]) trend[i] =-1;
         if (sto[i]>sig[i])                  cross[i] = 1;
         if (sto[i]<sig[i])                  cross[i] =-1;
      
         //
         //
         //
         //
         //
            
         if (arrowsVisible)
         {
            ObjectDelete(arrowsIdentifier+":1:"+Time[i]);
            ObjectDelete(arrowsIdentifier+":2:"+Time[i]);
            string lookFor = arrowsIdentifier+":"+Time[i]; ObjectDelete(lookFor);
            if (arrowsOnObOsCross && trend[i] != trend[i+1])
            {
                if (trend[i] == 1) drawArrow("1",0.5,i,arrowsOnObOsCrossUpColor,arrowsOnObOsCrossUpCode,false);
                if (trend[i] ==-1) drawArrow("1",0.5,i,arrowsOnObOsCrossDnColor,arrowsOnObOsCrossDnCode,true);
              }
              if (arrowsOnCross && cross[i] != cross[i+1])
              {
                if (cross[i] == 1) drawArrow("2",1,i,arrowsOnCrossUpColor,arrowsOnCrossUpCode,false);
                if (cross[i] ==-1) drawArrow("2",1,i,arrowsOnCrossDnColor,arrowsOnCrossDnCode,true);
              }
          }  
   }
   
   //
   //
   //
   //
   //
   
   if (alertsOn)
   {
        if (alertsOnCurrent)
             int whichBar = 0;
        else     whichBar = 1;
        static datetime time1 = 0;
        static string   mess1 = "";
        if (alertsOnObOsCross && trend[whichBar] != trend[whichBar+1])
        {
           if (trend[whichBar] ==  1 ) doAlert(time1,mess1,whichBar,"crossing signal and less than lower level");
           if (trend[whichBar] == -1 ) doAlert(time1,mess1,whichBar,"crossing signal and greater than upper level");
        }         
        static datetime time2 = 0;
        static string   mess2 = "";
        if (alertsOnCross && cross[whichBar] != cross[whichBar+1])
        {
           if (cross[whichBar] ==  1 ) doAlert(time2,mess2,whichBar,"crossing signal up");
           if (cross[whichBar] == -1 ) doAlert(time2,mess2,whichBar,"crossing signal down");
        }         
     }           
return(0);
}

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

double workSto[][5];
#define _hi 0
#define _lo 1
#define _re 2
#define _ma 3
#define _mi 4
double iStoch(double priceR, double priceH, double priceL, int period, int slowing, int i, int instanceNo=0)
{
   if (ArrayRange(workSto,0)!=Bars) ArrayResize(workSto,Bars); i = Bars-i-1; instanceNo *= 5;
   
   //
   //
   //
   //
   //
   
   workSto[i][_hi+instanceNo] = priceH;
   workSto[i][_lo+instanceNo] = priceL;
   workSto[i][_re+instanceNo] = priceR;
   workSto[i][_ma+instanceNo] = priceH;
   workSto[i][_mi+instanceNo] = priceL;
      for (int k=1; k<period && (i-k)>=0; k++)
      {
         workSto[i][_mi+instanceNo] = MathMin(workSto[i][_mi+instanceNo],workSto[i-k][_lo+instanceNo]);
         workSto[i][_ma+instanceNo] = MathMax(workSto[i][_ma+instanceNo],workSto[i-k][_hi+instanceNo]);
      }                   
      double sumlow  = 0.0;
      double sumhigh = 0.0;
      for(k=0; k<slowing; k++)
      {
         sumlow  += workSto[i-k][_re+instanceNo]-workSto[i-k][_mi+instanceNo];
         sumhigh += workSto[i-k][_ma+instanceNo]-workSto[i-k][_mi+instanceNo];
      }

   //
   //
   //
   //
   //
   
   if(sumhigh!=0.0) 
         return(100.0*sumlow/sumhigh);
   else  return(0);    
}

//
//
//
//
//

void drawArrow(string nameAdd, double gapMul, int i,color theColor,int theCode,bool up)
{
   string name = arrowsIdentifier+":"+nameAdd+":"+Time[i];
   double gap  = iATR(NULL,0,20,i)*gapMul;   
   
      //
      //
      //
      //
      //
      
      ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);
}

//
//
//
//
//

void deleteArrows()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
}

//
//
//
//
//

void deleteArrow(datetime time)
{
   string lookFor = arrowsIdentifier+":"+time; ObjectDelete(lookFor);
}

//
//
//
//
//

void doAlert(datetime& previousTime, string& previousAlert, int forBar, string doWhat)
{
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

        message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," Dynamic zone stochastic ",doWhat);
          if (alertsMessage) Alert(message);
          if (alertsNotify)  SendNotification(message);
          if (alertsEmail)   SendMail(StringConcatenate(Symbol()," Dynamic zone stochastic "),message);
          if (alertsSound)   PlaySound(soundFile);
   }
}
