//+-------------------------------------------------------------------+
//|                               StochDifZones Indicator (C) Ralome  |
//|                               StochDifZones Principle (C) Eurusdd |
//| v1.80                                                             |
//|        This code comes as is and carries NO WARRANTY whatsoever   |
//|                                           Use at your own risk!   |
//+-------------------------------------------------------------------+
#property  indicator_separate_window
#property  indicator_buffers 8

#property  indicator_color4  Green
#property  indicator_width4  3
#property  indicator_color5  Plum
#property  indicator_width5  3
#property  indicator_color6  Blue
#property  indicator_width6  1

extern int stochperiod=300;
extern int bbperiod=24;
extern string note_1 = " -- bars_limit 0 means all bars -- ";
extern int bars_limit=1000;

extern bool show_first_dissimilarity_zone = true;
extern color first_dissimilarity_zone_color=PowderBlue;
extern double zone_lifetime_in_days = 14;
extern string note_2 = " -- What to do with old/cleared zones -- ";
extern string note_3 = " -- 0: nothing, 1: remove, 2: gray out -- ";
extern int old_cleared_zones = 0;
extern color old_cleared_zones_color = Gray;

extern string extras_1 = " ** Change bottom dots into lines ** ";
extern bool lines_instead_of_dots = false;
extern double line_height = 2;

extern string extras_2 = " ** Show counters after zones ** ";
extern bool show_counters = true;
extern string counter_fontname = "Arial";
extern int counter_fontsize = 10;
extern color counter_color = Black;
extern string counter_what_to_show = "0: elapsed, 1: remaining";
extern int counter_what = 0;
extern string counter_distance_in_bars = "position of the counter";
extern int counter_pos = 10;

extern string extras_3 = " ** Alert when a new zone starts ** ";
extern bool alert_popup = false;
extern bool alert_sound = false;

extern string extras_4 = " ** Mark youngest/oldest active zones with different color ** ";
extern bool mark_youngest_oldest_zone = true;
extern color youngest_zone_color = LimeGreen;
extern color oldest_zone_color = Red;

extern string extras_5 = " ** Mark big dissimilarity on chart ** ";
extern bool show_markers = false;
extern double dissim_bigger_than = 1;
extern int marker_code = 159;
extern string where_it_will_be = "0: above H, 1: below L, 2: middle";
extern int marker_placement = 0;
extern string distance_from_candle = "applies if you choose 0/1 above";
extern double marker_distance = 0.0005;
extern color marker_color = Plum;
extern int marker_size = 3;

extern string extras_6 = " ** Zones based on biggest dissimilarity ** ";
extern bool show_biggest_dissimilarity_zone = false;
extern color biggest_dissim_zone_color=LimeGreen;

extern string extras_7 = "pricefield: 0: H/L, 1: C/C (Stochastics indy)";
extern int pricefield=0;

#property indicator_minimum 0
#property indicator_maximum 2.2

   SetLevelValue (0, 1);       // The horizontal line level is set
   SetLevelValue (1, 2);       // The horizontal line level is set
   SetLevelValue (2, 0);       // The horizontal line level is set
   SetLevelStyle(STYLE_SOLID,1,DarkKhaki);

double stochi[],price_ma[],price_std[],stochi_ma,stochi_std,dif[],change_sim[],change_dissim[];
double objects_finished[],objects_finished2[];
double cval;

   double stochi_perc,price_perc;
   double newboxhigh,newboxlow,newboxtime,newbiggestdif,newbiggestdifhigh,newbiggestdiflow,newbiggestdiftime;
   double objlow,objhigh;
   int objstart;
   string name,currentobj,counter_text,prevobj, old_obj, new_obj;
   int ot, obj_time_min, obj_time_max;
   double objstarttime,lifetime;
   int tf;
   

   
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
  IndicatorBuffers(8);
   SetIndexStyle(0,DRAW_NONE);
   SetIndexBuffer(0,stochi);
SetIndexStyle(1,DRAW_NONE);
   SetIndexBuffer(1,price_ma);
SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(2,price_std);

   SetIndexBuffer(3,change_sim);
   SetIndexBuffer(4,change_dissim);
   
   if (lines_instead_of_dots==true)
      {
      SetIndexStyle(3,DRAW_HISTOGRAM);
      SetIndexStyle(4,DRAW_HISTOGRAM);
      cval=line_height;
      }
      else
      {
      SetIndexStyle(3,DRAW_ARROW);
      SetIndexArrow(3,159);
      SetIndexStyle(4,DRAW_ARROW);
      SetIndexArrow(4,159);
      cval=0;
      }
      
SetIndexStyle(5,DRAW_LINE);
   SetIndexBuffer(5,dif);      
SetIndexStyle(6,DRAW_NONE);
   SetIndexBuffer(6,objects_finished);   
SetIndexStyle(7,DRAW_NONE);
   SetIndexBuffer(7,objects_finished2);
   
   newbiggestdif=-1;   
   lifetime=zone_lifetime_in_days*24*60*60;
   tf=Period();
   old_obj="start";
   new_obj="start";
      
   return(0);
  }

int start()
  {

   int limit, handle,i;
   int counted_bars=IndicatorCounted();
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;

   limit=Bars-counted_bars;
   
   if (limit>bars_limit-1 && bars_limit!=0) limit=bars_limit-1;
   if (Bars<stochperiod+bbperiod || (bars_limit>0 && bars_limit<stochperiod+bbperiod))
      {
      Alert("Adjust limit settings or put more bars on your chart!");
      return(0);
      }
   
   for(i=0; i<limit; i++)
      {
      stochi[i]=iStochastic(NULL,0,stochperiod,1,1,MODE_EMA,pricefield,MODE_MAIN,i);
      price_ma[i]=iMA(NULL,0,bbperiod,0,MODE_EMA,PRICE_CLOSE,i);
      price_std[i]=iStdDev(NULL,0,bbperiod,0,MODE_EMA,PRICE_CLOSE,i);
      }
      
   for(i=0; i<limit; i++)
      {
      stochi_ma=iMAOnArray(stochi,0,bbperiod,0,MODE_EMA,i);
      stochi_std=iStdDevOnArray(stochi,0,bbperiod,0,MODE_EMA,i);
      
      if (stochi_std>0) stochi_perc=(stochi[i]-stochi_ma)/(2*stochi_std);
      if (price_std[i]>0) price_perc=(Close[i]-price_ma[i])/(2*price_std[i]);
      dif[i]=MathAbs(stochi_perc-price_perc);

      }      
      
   for(i=0; i<limit; i++)
      {
      if ((dif[i+1]<0.0001) && (dif[i+2]>=0.0001)) change_sim[i+1]=cval;
      if ((dif[i+1]>=0.0001) && (dif[i+2]<0.0001)) change_dissim[i+1]=cval;
      
      if (show_markers==TRUE && dif[i+1]>dissim_bigger_than)
         {
         name=StringConcatenate("bigdifmark_",DoubleToStr(Time[i+1],0));
         if (ObjectFind(name) == -1)
            {
            ObjectCreate(name,OBJ_ARROW,0,Time[i+1],High[i+1]+marker_distance);
            ObjectSet(name,OBJPROP_COLOR,marker_color);
            ObjectSet(name,OBJPROP_ARROWCODE,marker_code);
            ObjectSet(name,OBJPROP_WIDTH,marker_size);
            
            if (marker_placement==1) ObjectSet(name,OBJPROP_PRICE1,Low[i+1]-marker_distance);
            if (marker_placement==2) ObjectSet(name,OBJPROP_PRICE1,(Low[i+1]+High[i+1])/2);
            }
         }    
      
      }  

   for(i=limit; i>=0; i--)
      {
      if (change_dissim[i]==cval)
         {
         newboxhigh=High[i];
         newboxlow=Low[i];
         newboxtime=Time[i];
         newbiggestdif=-1;
         }
      
      if (dif[i+1]>newbiggestdif && newboxtime!=0 && Time[i+1]>newboxtime && show_biggest_dissimilarity_zone==TRUE)
         {
         newbiggestdif=dif[i+1];
         newbiggestdifhigh=High[i+1];
         newbiggestdiflow=Low[i+1];
         newbiggestdiftime=Time[i+1];
         /* name=StringConcatenate("bgdft_",DoubleToStr(newbiggestdiftime,0));
                        
                          if (ObjectFind(name) == -1)
                              {
                              ObjectCreate(name, OBJ_TEXT, 0, Time[i],High[i]+0.001);
                              }
         ObjectSetText(name, DoubleToStr(newbiggestdif,2), 8, counter_fontname, counter_color);*/
         }
      
      if (change_sim[i]==cval && newboxtime!=0 && Time[i]>newboxtime && show_first_dissimilarity_zone==TRUE)
         {
         
         name=StringConcatenate("dsim_",DoubleToStr(newboxtime,0));
         if (ObjectFind(name) == -1)
            {
            if (ObjectFind(new_obj) != -1 && StringFind(new_obj,"dsim_",0))
               {
               ObjectSet(new_obj,OBJPROP_COLOR, first_dissimilarity_zone_color);
               }
            ObjectCreate(name, OBJ_RECTANGLE, 0, Time[i],newboxhigh,Time[i],newboxlow);
            ObjectSet(name,OBJPROP_COLOR, first_dissimilarity_zone_color);
            ObjectSet(name, OBJPROP_BACK, TRUE);
            ObjectSet(name, OBJPROP_WIDTH, 0);
            ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);
            objects_finished[i]=1;
            if (alert_popup == true)
               {
               Alert(StringConcatenate("New dissimilarity zone: ",Symbol(), ", ",DoubleToStr(TimeHour(Time[i]),0),":",
                    DoubleToStr(TimeMinute(Time[i]),0)));
               }
            if (alert_sound == true)
               {
               PlaySound("alert.wav");
               }               
            }
         }
         
      if (change_sim[i]==cval && newbiggestdiftime!=0 && Time[i]>newbiggestdiftime && show_biggest_dissimilarity_zone==TRUE)
         {       
         name=StringConcatenate("bigsim_",DoubleToStr(newboxtime,0));
         if (ObjectFind(name) == -1)
            {
            if (ObjectFind(new_obj) != -1 && StringFind(new_obj,"bigsim_",0))
               {
               ObjectSet(new_obj,OBJPROP_COLOR, first_dissimilarity_zone_color);
               }
            ObjectCreate(name, OBJ_RECTANGLE, 0, Time[i],newbiggestdifhigh,Time[i],newbiggestdiflow);
            ObjectSet(name,OBJPROP_COLOR, biggest_dissim_zone_color);
            ObjectSet(name, OBJPROP_BACK, TRUE);
            ObjectSet(name, OBJPROP_WIDTH, 0);
            ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);
            objects_finished2[i]=1;
            
            if (alert_popup == true)
               {
               Alert(StringConcatenate("New dissimilarity zone: ",Symbol(), ", ",DoubleToStr(TimeHour(Time[i]),0),":",
                    DoubleToStr(TimeMinute(Time[i]),0)));
               }
            if (alert_sound == true)
               {
               PlaySound("alert.wav");
               }   
            }
         }

      ot=ObjectsTotal();
      
      obj_time_max=0;
      obj_time_min=9999999999;
      
      while(ot>=0 && (show_first_dissimilarity_zone==TRUE || show_biggest_dissimilarity_zone==TRUE))
         {
         currentobj=ObjectName(ot);
                         
         if (StringFind(currentobj,"dsim_",0)>-1 && show_first_dissimilarity_zone==TRUE)
            {
            
            objstarttime=ObjectGet(currentobj,OBJPROP_TIME1); 
            objstart=iBarShift(NULL,0,objstarttime);
            
            if (objects_finished[objstart]<15)
               {
               
               if (Time[i]-objstarttime>lifetime)
                  {
                  
                  if (old_cleared_zones==0 && ObjectGet(currentobj,OBJPROP_COLOR) != first_dissimilarity_zone_color)
                     {
                     ObjectSet(currentobj,OBJPROP_COLOR,first_dissimilarity_zone_color);
                     }
                  
                  if (old_cleared_zones==1)
                     {
                     ObjectDelete(StringConcatenate("counter_ds_",DoubleToStr(objstarttime,0)));
                     ObjectDelete(currentobj);
                     objects_finished[objstart]=EMPTY_VALUE;
                     }
                  if (old_cleared_zones==2 && ObjectGet(currentobj,OBJPROP_COLOR) != old_cleared_zones_color)
                     {
                     ObjectSet(currentobj,OBJPROP_COLOR, old_cleared_zones_color);
                     }   
                  }
                  
                  else
                  {
                  
                  if (objstarttime<obj_time_min) 
                     {
                     obj_time_min=objstarttime;
                     old_obj=currentobj;
                     }
                  if (objstarttime>obj_time_max) 
                     {
                     obj_time_max=objstarttime;
                     new_obj=currentobj;
                     }  
                     
                  ObjectSet(currentobj,OBJPROP_COLOR,first_dissimilarity_zone_color);                   
                  objhigh=ObjectGet(currentobj,OBJPROP_PRICE1);
                  objlow=ObjectGet(currentobj,OBJPROP_PRICE2);
            
                  if (MathMod(objects_finished[objstart],5)>0 && objhigh<=High[i] && objhigh>=Low[i] && i<objstart)
                      objects_finished[objstart]=objects_finished[objstart]+4;
                  if (objects_finished[objstart]<10 && objlow<=High[i] && objlow>=Low[i] && i<objstart)
                      objects_finished[objstart]=objects_finished[objstart]+10;
               
                  if (objects_finished[objstart]<15 && Time[i]>ObjectGet(currentobj,OBJPROP_TIME2))
                     {
                     ObjectSet(currentobj, OBJPROP_TIME2, Time[i]);
                     
                     if (show_counters == TRUE)
                        {
                        name=StringConcatenate("counter_ds_",DoubleToStr(objstarttime,0));
                        
                           if (ObjectFind(name) == -1)
                              {
                              ObjectCreate(name, OBJ_TEXT, 0, Time[i]+tf*counter_pos*60,(objhigh+objlow)/2);
                              }
                        
                        if (counter_what==0)
                           {
                           counter_text=StringConcatenate("El.: ",DoubleToStr((Time[i]-objstarttime)/60/60/24,1),"/",zone_lifetime_in_days," days");
                           }
                           else
                           {
                           counter_text=StringConcatenate("Rem.: ",DoubleToStr((lifetime-(Time[i]-objstarttime))/60/60/24,1),"/",zone_lifetime_in_days," days");
                           }
                           
                              
                        ObjectSetText(name, counter_text, counter_fontsize, counter_fontname, counter_color);
                        ObjectSet(name, OBJPROP_TIME1, Time[i]+tf*counter_pos*60);
                        } // counters
                     } // unfinished
                  } // young enough

               } //unfinished2
               
            if (objects_finished[objstart]==15)
               
               {
               if (old_cleared_zones==0 && ObjectGet(currentobj,OBJPROP_COLOR) != first_dissimilarity_zone_color)
                     {
                     ObjectSet(currentobj,OBJPROP_COLOR,first_dissimilarity_zone_color);
                     }
               if (old_cleared_zones==1)
                  {
                  ObjectDelete(StringConcatenate("counter_ds_",DoubleToStr(objstarttime,0)));
                  ObjectDelete(currentobj);
                  objects_finished[objstart]=EMPTY_VALUE;
                  }
               if (old_cleared_zones==2 && ObjectGet(currentobj,OBJPROP_COLOR) != old_cleared_zones_color)
                  {
                  ObjectSet(currentobj,OBJPROP_COLOR, old_cleared_zones_color);
                  }                  
               }

            } // firstdissim

         if (StringFind(currentobj,"bigsim_",0)>-1 && show_biggest_dissimilarity_zone==TRUE)
            {
            
            objstarttime=ObjectGet(currentobj,OBJPROP_TIME1);             
            objstart=iBarShift(NULL,0,objstarttime);
            
            if (objects_finished2[objstart]<15)
               {
               
            if (Time[i]-objstarttime>lifetime)
                  {
                  if (old_cleared_zones==0 && ObjectGet(currentobj,OBJPROP_COLOR) != biggest_dissim_zone_color)
                     {
                     ObjectSet(currentobj,OBJPROP_COLOR,biggest_dissim_zone_color);
                     }
                  if (old_cleared_zones==1)
                     {
                     ObjectDelete(StringConcatenate("counter_bigs_",DoubleToStr(objstarttime,0)));
                     ObjectDelete(currentobj);
                     objects_finished[objstart]=EMPTY_VALUE;
                     }
                  if (old_cleared_zones==2 && ObjectGet(currentobj,OBJPROP_COLOR) != old_cleared_zones_color)
                     {
                     ObjectSet(currentobj,OBJPROP_COLOR, old_cleared_zones_color);
                     }      
                  }
                  else
                  {
                  
                  ObjectSet(currentobj,OBJPROP_COLOR,biggest_dissim_zone_color);                 
                  objhigh=ObjectGet(currentobj,OBJPROP_PRICE1);
                  objlow=ObjectGet(currentobj,OBJPROP_PRICE2);
                  
                  if (objstarttime<obj_time_min) 
                     {
                     obj_time_min=objstarttime;
                     old_obj=currentobj;
                     }
                  if (objstarttime>obj_time_max) 
                     {
                     obj_time_max=objstarttime;
                     new_obj=currentobj;
                     }  
            
                  if (MathMod(objects_finished2[objstart],5)>0 && objhigh<=High[i] && objhigh>=Low[i] && i<objstart)
                     objects_finished2[objstart]=objects_finished2[objstart]+4;
                  if (objects_finished2[objstart]<10 && objlow<=High[i] && objlow>=Low[i] && i<objstart)
                     objects_finished2[objstart]=objects_finished2[objstart]+10;
                     
                  if (objects_finished2[objstart]<15 && Time[i]>ObjectGet(currentobj,OBJPROP_TIME2))
                     {
                     ObjectSet(currentobj, OBJPROP_TIME2, Time[i]);
               
                     if (show_counters == TRUE)
                        {
                        name=StringConcatenate("counter_bigs_",DoubleToStr(objstarttime,0));
                        
                           if (ObjectFind(name) == -1)
                              {
                              ObjectCreate(name, OBJ_TEXT, 0, Time[i]+tf*counter_pos*60,(objhigh+objlow)/2);
                              }
                        
                        if (counter_what==0)
                           {
                           counter_text=StringConcatenate("El.: ",DoubleToStr((Time[i]-objstarttime)/60/60/24,1),"/",zone_lifetime_in_days," days");
                           }
                           else
                           {
                           counter_text=StringConcatenate("Rem.: ",DoubleToStr((lifetime-(Time[i]-objstarttime))/60/60/24,1),"/",zone_lifetime_in_days," days");
                           }
                           
                              
                        ObjectSetText(name, counter_text, counter_fontsize, counter_fontname, counter_color);
                        ObjectSet(name, OBJPROP_TIME1, Time[i]+tf*counter_pos*60);
                        }   //counters            
                     } // unfinished
                  } // young enough
               } // unfinished2
               
            if (objects_finished[objstart]==15)
               
               {
               if (old_cleared_zones==0 && ObjectGet(currentobj,OBJPROP_COLOR) != biggest_dissim_zone_color)
                  {
                  ObjectSet(currentobj,OBJPROP_COLOR,biggest_dissim_zone_color);
                  }
               if (old_cleared_zones==1)
                  {
                  ObjectDelete(StringConcatenate("counter_bigs_",DoubleToStr(objstarttime,0)));
                  ObjectDelete(currentobj);
                  objects_finished[objstart]=EMPTY_VALUE;
                  }
               if (old_cleared_zones==2 && ObjectGet(currentobj,OBJPROP_COLOR) != old_cleared_zones_color)
                  {
                  ObjectSet(currentobj,OBJPROP_COLOR, old_cleared_zones_color);
                  }                  
               }


            } // bigdissim

         ot--;
         }

         if (ObjectGet(old_obj,OBJPROP_COLOR) != oldest_zone_color)
            {
            ObjectSet(old_obj,OBJPROP_COLOR, oldest_zone_color);
            }
         if (ObjectGet(new_obj,OBJPROP_COLOR) != youngest_zone_color)
            {
            ObjectSet(new_obj,OBJPROP_COLOR, youngest_zone_color);
            } 
            
                
      }  
    

   return(0);
  }
//+------------------------------------------------------------------+

int deinit()
{
DelObjects("dsim_");
DelObjects("bigsim_");
DelObjects("bigdifmark_");
DelObjects("counter_ds_");
DelObjects("counter_bigs_");
//DelObjects("bgdft_");
}

void DelObjects(string id)
   {
   int ot=ObjectsTotal();
   while(ot>=0)
      {
      if (StringFind(ObjectName(ot),id,0)>-1)
         {
         ObjectDelete(ObjectName(ot));
         }
      ot--;
      }
   }