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

#property indicator_separate_window
#property indicator_buffers 6
#property indicator_color1  DarkOrange
#property indicator_color2  LimeGreen
#property indicator_color3  DarkGray
#property indicator_color4  LimeGreen
#property indicator_color5  DarkOrange
#property indicator_color6  DarkOrange
#property indicator_width4  2
#property indicator_width5  2
#property indicator_width6  2
#property indicator_style1  STYLE_DOT
#property indicator_style2  STYLE_DOT
#property indicator_style3  STYLE_DOT

//
//
//
//
//

#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    RsiLength              = 50;
extern int    RsiPrice               = PRICE_CLOSE;
extern int    DzLookBackBars         = 70;
extern double DzStartBuyProbability  = 0.10;
extern double DzStartSellProbability = 0.10;
extern bool   alertsOn               = false;    // Turn alerts on
extern bool   alertsOnCurrent        = true;     // Alerts on currnt (still opened) bar
extern bool   alertsMessage          = true;     // Alerts should show pop-up message
extern bool   alertsSound            = false;    // Alerts should play alert sound
extern bool   alertsPushNotif        = false;    // Alerts should send push notification
extern bool   alertsEmail            = false;    // Alerts should send email

//
//
//
//
//

double rsi[];
double rsida[];
double rsidb[];
double bli[];
double sli[];
double zli[];
double state[];
double crossup[];
double crossdn[];

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

int init()
{
   IndicatorBuffers(9);
   SetIndexBuffer(0,bli);
   SetIndexBuffer(1,sli);
   SetIndexBuffer(2,zli);
   SetIndexBuffer(3,rsi);
   SetIndexBuffer(4,rsida);
   SetIndexBuffer(5,rsidb);
   SetIndexBuffer(6,state);
   SetIndexBuffer(7,crossup);
   SetIndexBuffer(8,crossdn);

   //
   //
   //
   //
   //
   
   string PriceType;
      switch(RsiPrice)
      {
         case PRICE_CLOSE:    PriceType = "Close";    break;  // 0
         case PRICE_OPEN:     PriceType = "Open";     break;  // 1
         case PRICE_HIGH:     PriceType = "High";     break;  // 2
         case PRICE_LOW:      PriceType = "Low";      break;  // 3
         case PRICE_MEDIAN:   PriceType = "Median";   break;  // 4
         case PRICE_TYPICAL:  PriceType = "Typical";  break;  // 5
         case PRICE_WEIGHTED: PriceType = "Weighted"; break;  // 6
      }      

   //
   //
   //
   //
   //

   RsiLength = MathMax(RsiLength ,1);
   IndicatorShortName ("Dynamic zone RSI ("+RsiLength+","+PriceType+","+DzLookBackBars+","+DoubleToStr(DzStartBuyProbability,3)+","+DoubleToStr(DzStartSellProbability,3)+")");
   return(0);
}
int deinit()
{
   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);

   //
   //
   //
   //
   //
   //

   if  (state[limit] == -1) ClearPoint(limit,rsida,rsidb);
   for(i=limit; i >= 0; i--)
   {
      rsi[i]     = iRSI(NULL,0,RsiLength,RsiPrice,i);
      bli[i]     = dzBuy (rsi, DzStartBuyProbability,  DzLookBackBars, Bars, i);
      sli[i]     = dzSell(rsi, DzStartSellProbability, DzLookBackBars, Bars, i);
      zli[i]     = dzSell(rsi, 0.5                   , DzLookBackBars, Bars, i);
      rsida[i]   = EMPTY_VALUE;
      rsidb[i]   = EMPTY_VALUE;
      state[i]   = state[i+1];
      crossdn[i] = crossdn[i+1];
      crossup[i] = crossup[i+1];
         if (rsi[i]>zli[i]) state[i] =  1;
         if (rsi[i]<zli[i]) state[i] = -1;
	      if (state[i] == -1) PlotPoint(i,rsida,rsidb,rsi);
	      if (rsi[i]>MathMax(bli[i],sli[i])) crossup[i] =  1;
	      if (rsi[i]<MathMax(bli[i],sli[i])) crossup[i] = -1;
	      if (rsi[i]>MathMin(bli[i],sli[i])) crossdn[i] =  1;
	      if (rsi[i]<MathMin(bli[i],sli[i])) crossdn[i] = -1;
   }
   manageAlerts();
   return(0);
}

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

void manageAlerts()
{
   if (alertsOn)
   {
      int whichBar = 1; if (alertsOnCurrent) whichBar = 0;
      if (crossup[whichBar] != crossup[whichBar+1])
      {
         static string   mess1 = "";
         static datetime time1 = 0;
         if (crossup[whichBar] ==  1) doAlert(mess1,time1,whichBar," upper dynamic zone level up");
         if (crossup[whichBar] == -1) doAlert(mess1,time1,whichBar," upper dynamic zone level down");
      }
      if (crossdn[whichBar] != crossdn[whichBar+1])
      {
         static string   mess2 = "";
         static datetime time2 = 0;
         if (crossdn[whichBar] ==  1) doAlert(mess2,time2,whichBar," lower dynamic zone level up");
         if (crossdn[whichBar] == -1) doAlert(mess2,time2,whichBar," lower dynamic zone level down");
      }
   }
}

//
//
//
//
//

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

       //
       //
       //
       //
       //

       message = Symbol()+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" DZ rsi crossed"+doWhat;
          if (alertsMessage)   Alert(message);
          if (alertsEmail)     SendMail(Symbol()+" DZ rsi",message);
          if (alertsPushNotif) SendNotification(message);
          if (alertsSound)     PlaySound("alert2.wav");
   }
}

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

void ClearPoint(int i,double& first[],double& second[])
{
   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 (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;
      }
}