//------------------------------------------------------------------
#property copyright "mladen"
#property link      "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  clrGreen
#property indicator_color5  clrRed
#property indicator_color6  clrDeepSkyBlue
#property indicator_color7  clrMagenta
#property indicator_width1  2
#property indicator_width2  2
#property indicator_width3  2
#property indicator_level1  0.3
#property indicator_level2  0.7
#property indicator_minimum -0.1
#property indicator_maximum 1.01
#property strict

//
//
//
//
//

enum enPrices
{
   pr_close,      // Close
   pr_open,       // Open
   pr_high,       // High
   pr_low,        // Low
   pr_median,     // Median
   pr_typical,    // Typical
   pr_weighted,   // Weighted
   pr_average,    // Average (high+low+open+close)/4
   pr_medianb,    // Average median body (open+close)/2
   pr_tbiased,    // Trend biased price
   pr_tbiased2,   // Trend biased (extreme) price
   pr_haclose,    // Heiken ashi close
   pr_haopen ,    // Heiken ashi open
   pr_hahigh,     // Heiken ashi high
   pr_halow,      // Heiken ashi low
   pr_hamedian,   // Heiken ashi median
   pr_hatypical,  // Heiken ashi typical
   pr_haweighted, // Heiken ashi weighted
   pr_haaverage,  // Heiken ashi average
   pr_hamedianb,  // Heiken ashi median body
   pr_hatbiased,  // Heiken ashi trend biased price
   pr_hatbiased2  // Heiken ashi trend biased (extreme) price
};

extern double   PaCycles                     = 1.0;         // Cycles   
extern double   PaFilter                     = 0.0;         // Phase filter
extern enPrices PaPrice                      = pr_median;   // Price
extern double   T3Hot                        = 0.5;         // T3 hot
extern bool     T3Original                   = false;       // Original Tim Tillson T3 calculation?
extern bool     ShowArrows                   = false;       // Show arrows
extern string   arrowsIdentifier             = "demarker Arrows1"; // Arrows unique ID
extern double   arrowsUpperGap               = 0.5;         // Arrows upper gap
extern double   arrowsLowerGap               = 0.5;         // Arrows lower gap
extern color    arrowsUpColor                = clrLimeGreen; // Up arrow color   
extern color    arrowsDnColor                = clrRed;       // Down arrow color
extern int      arrowsUpCode                 = 241;         // Up arrow code
extern int      arrowsDnCode                 = 242;         // Down arrow code
extern bool     divergenceVisible            = false;       // Should the divergence be visible
extern bool     divergenceOnValuesVisible    = true;        // Divergence lines on RSI visible?
extern bool     divergenceOnChartVisible     = true;        // Divergence lines on main chart visible?
extern int      DivergearrowSize             = 2;           // Divergence arrows size
extern double   DivergencearrowsUpperGap     = 1;           // Upper Gap between divergence arrows and indicator line
extern double   DivergencearrowsLowerGap     = 1;           // Lower Gap between divergence arrows and indicator line
extern bool     ShowClassicalDivergence      = true;        // Classical divergence visible
extern bool     ShowHiddenDivergence         = true;        // Hidden divergence visible
extern color    divergenceBullishColor       = clrLimeGreen;   // Bullish divergences color
extern color    divergenceBearishColor       = clrOrangeRed;   // Bearish divergences color
extern int      ClassicDivergenceUpArrowCode = 233;         // classical divergence up arrow code
extern int      ClassicDivergenceDnArrowCode = 234;         // classical divergence dn arrow code
extern int      HiddenDivergenceUpArrowCode  = 159;         // hidden divergence up arrow code
extern int      HiddenDivergenceDnArrowCode  = 159;         // hidden divergence dn arrow code
extern string   divergenceUniqueID           = "pademarker divergence1"; // Unique ID for divergence lines

double dem[];
double demDa[];
double demDb[];
double cbulld[];
double hbulld[];
double cbeard[];
double hbeard[];
string shortName;
double slope[];
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
   SetIndexBuffer(0, dem);
   SetIndexBuffer(1, demDa);
   SetIndexBuffer(2, demDb);
   SetIndexBuffer(3, cbulld);  SetIndexStyle(3,DRAW_ARROW,0,DivergearrowSize); SetIndexArrow(3,ClassicDivergenceUpArrowCode);
   SetIndexBuffer(4, cbeard);  SetIndexStyle(4,DRAW_ARROW,0,DivergearrowSize); SetIndexArrow(4,ClassicDivergenceDnArrowCode);
   SetIndexBuffer(5, hbulld);  SetIndexStyle(5,DRAW_ARROW,0,DivergearrowSize); SetIndexArrow(5,HiddenDivergenceUpArrowCode);
   SetIndexBuffer(6, hbeard);  SetIndexStyle(6,DRAW_ARROW,0,DivergearrowSize); SetIndexArrow(6,HiddenDivergenceDnArrowCode);
   SetIndexBuffer(7, slope);
   shortName = divergenceUniqueID+": T3 DeMarker - pa adaptive ("+DoubleToStr(PaCycles,2)+")";
   IndicatorShortName(shortName);
return(0);
}

void OnDeinit(const int reason) 
{ 
    int lookForLength = StringLen(divergenceUniqueID);
   
      for (int i=ObjectsTotal()-1; i>=0; i--) 
      {
         string name = ObjectName(i);  if (StringSubstr(name,0,lookForLength) == divergenceUniqueID) ObjectDelete(name);
      }
return;
}

//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
           int limit=fmin(Bars-counted_bars,Bars-1);

   //
   //
   //
   //
   //

   if (slope[limit]==-1) CleanPoint(limit,demDa,demDb);
   for(int i=limit; i>=0; i--)
   {
      double demH = (i<Bars-1) ? (High[i] > High[i+1]) ? High[i] - High[i+1] : 0 : 0;
      double demL = (i<Bars-1) ? (Low[i] < Low[i+1])   ? Low[i+1] - Low[i]   : 0 : 0;
      double DeMarkerPeriod = iHilbertPhase(getPrice(PaPrice,Open,Close,High,Low,i),PaFilter,PaCycles,i);
         double smtH = MathMax(iT3(demH,DeMarkerPeriod,T3Hot,T3Original,i,0),0);
         double smtL = MathMax(iT3(demL,DeMarkerPeriod,T3Hot,T3Original,i,1),0);
          if (smtH+smtL!=0)
                  dem[i] = smtH/(smtH+smtL);
            else  dem[i] = 0;
            slope[i] = (i<Bars-1) ? (dem[i]>dem[i+1]) ? 1 : (dem[i]<dem[i+1]) ? -1 : slope[i+1] : 0;
            demDa[i] = EMPTY_VALUE;
            demDb[i] = EMPTY_VALUE;
               if (slope[i]==-1) PlotPoint(i,demDa,demDb,dem);
               
               //
               //
               //
               //
               //
     
               if (ShowArrows)
               {
                 string lookFor = arrowsIdentifier+":"+(string)Time[i]; ObjectDelete(lookFor);
                 if (i<Bars-1 && slope[i] != slope[i+1])
                 {
                   if (slope[i] == 1)  drawArrow(i,arrowsUpColor,arrowsUpCode,false);
                   if (slope[i] ==-1)  drawArrow(i,arrowsDnColor,arrowsDnCode, true);
                 }
               }
      
               if (divergenceVisible)
               {
                 CatchBullishDivergence(dem,i);
                 CatchBearishDivergence(dem,i);
               } 
   }   
   return(0);
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

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; }
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workT3[][12];
double workT3Coeffs[][6];
#define _tperiod 0
#define _c1      1
#define _c2      2
#define _c3      3
#define _c4      4
#define _alpha   5

//
//
//
//
//

double iT3(double price, double period, double hot, bool original, int i, int instanceNo=0)
{
   if (ArrayRange(workT3,0) != Bars)                ArrayResize(workT3,Bars);
   if (ArrayRange(workT3Coeffs,0) < (instanceNo+1)) ArrayResize(workT3Coeffs,instanceNo+1);

   if (workT3Coeffs[instanceNo][_tperiod] != period)
   {
     workT3Coeffs[instanceNo][_tperiod] = period;
        double a = hot;
            workT3Coeffs[instanceNo][_c1] = -a*a*a;
            workT3Coeffs[instanceNo][_c2] = 3*a*a+3*a*a*a;
            workT3Coeffs[instanceNo][_c3] = -6*a*a-3*a-3*a*a*a;
            workT3Coeffs[instanceNo][_c4] = 1+3*a+a*a*a+3*a*a;
            if (original)
                 workT3Coeffs[instanceNo][_alpha] = 2.0/(1.0 + period);
            else workT3Coeffs[instanceNo][_alpha] = 2.0/(2.0 + (period-1.0)/2.0);
   }
   
   //
   //
   //
   //
   //
   
   int buffer = instanceNo*6;
   int r = Bars-i-1;
   if (r == 0)
      {
         workT3[r][0+buffer] = price;
         workT3[r][1+buffer] = price;
         workT3[r][2+buffer] = price;
         workT3[r][3+buffer] = price;
         workT3[r][4+buffer] = price;
         workT3[r][5+buffer] = price;
      }
   else
      {
         workT3[r][0+buffer] = workT3[r-1][0+buffer]+workT3Coeffs[instanceNo][_alpha]*(price              -workT3[r-1][0+buffer]);
         workT3[r][1+buffer] = workT3[r-1][1+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][0+buffer]-workT3[r-1][1+buffer]);
         workT3[r][2+buffer] = workT3[r-1][2+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][1+buffer]-workT3[r-1][2+buffer]);
         workT3[r][3+buffer] = workT3[r-1][3+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][2+buffer]-workT3[r-1][3+buffer]);
         workT3[r][4+buffer] = workT3[r-1][4+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][3+buffer]-workT3[r-1][4+buffer]);
         workT3[r][5+buffer] = workT3[r-1][5+buffer]+workT3Coeffs[instanceNo][_alpha]*(workT3[r][4+buffer]-workT3[r-1][5+buffer]);
      }

   //
   //
   //
   //
   //
   
   return(workT3Coeffs[instanceNo][_c1]*workT3[r][5+buffer] + 
          workT3Coeffs[instanceNo][_c2]*workT3[r][4+buffer] + 
          workT3Coeffs[instanceNo][_c3]*workT3[r][3+buffer] + 
          workT3Coeffs[instanceNo][_c4]*workT3[r][2+buffer]);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//
//

#define priceInstances 1
double workHa[][priceInstances*4];
double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int instanceNo=0)
{
  if (tprice>=pr_haclose)
   {
      if (ArrayRange(workHa,0)!= Bars) ArrayResize(workHa,Bars); instanceNo*=4;
         int r = Bars-i-1;
         
         //
         //
         //
         //
         //
         
         double haOpen;
         if (r>0)
                haOpen  = (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0;
         else   haOpen  = (open[i]+close[i])/2;
         double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0;
         double haHigh  = MathMax(high[i], MathMax(haOpen,haClose));
         double haLow   = MathMin(low[i] , MathMin(haOpen,haClose));

         if(haOpen  <haClose) { workHa[r][instanceNo+0] = haLow;  workHa[r][instanceNo+1] = haHigh; } 
         else                 { workHa[r][instanceNo+0] = haHigh; workHa[r][instanceNo+1] = haLow;  } 
                                workHa[r][instanceNo+2] = haOpen;
                                workHa[r][instanceNo+3] = haClose;
         //
         //
         //
         //
         //
         
         switch (tprice)
         {
            case pr_haclose:     return(haClose);
            case pr_haopen:      return(haOpen);
            case pr_hahigh:      return(haHigh);
            case pr_halow:       return(haLow);
            case pr_hamedian:    return((haHigh+haLow)/2.0);
            case pr_hamedianb:   return((haOpen+haClose)/2.0);
            case pr_hatypical:   return((haHigh+haLow+haClose)/3.0);
            case pr_haweighted:  return((haHigh+haLow+haClose+haClose)/4.0);
            case pr_haaverage:   return((haHigh+haLow+haClose+haOpen)/4.0);
            case pr_hatbiased:
               if (haClose>haOpen)
                     return((haHigh+haClose)/2.0);
               else  return((haLow+haClose)/2.0);        
            case pr_hatbiased2:
               if (haClose>haOpen)  return(haHigh);
               if (haClose<haOpen)  return(haLow);
                                    return(haClose);        
         }
   }
   
   //
   //
   //
   //
   //
   
   switch (tprice)
   {
      case pr_close:     return(close[i]);
      case pr_open:      return(open[i]);
      case pr_high:      return(high[i]);
      case pr_low:       return(low[i]);
      case pr_median:    return((high[i]+low[i])/2.0);
      case pr_medianb:   return((open[i]+close[i])/2.0);
      case pr_typical:   return((high[i]+low[i]+close[i])/3.0);
      case pr_weighted:  return((high[i]+low[i]+close[i]+close[i])/4.0);
      case pr_average:   return((high[i]+low[i]+close[i]+open[i])/4.0);
      case pr_tbiased:   
               if (close[i]>open[i])
                     return((high[i]+close[i])/2.0);
               else  return((low[i]+close[i])/2.0);        
      case pr_tbiased2:   
               if (close[i]>open[i]) return(high[i]);
               if (close[i]<open[i]) return(low[i]);
                                     return(close[i]);        
   }
   return(0);
}   

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

#define _hilInstances    1
#define _hilInstanceSize 9
double  workHil[][_hilInstances*_hilInstanceSize];
#define _price      0
#define _smooth     1
#define _detrender  2
#define _period     3
#define _instPeriod 4
#define _phase      5
#define _deltaPhase 6
#define _Q1         7
#define _I1         8

double iHilbertPhase(double price, double filter, double cyclesToReach, int i, int s=0)
{
   if (ArrayRange(workHil,0)!=Bars) ArrayResize(workHil,Bars);
   int r = Bars-i-1; s = s*_hilInstanceSize;
      
   //
   //
   //
   //
   //

   #define _calcComp(_ind) ((0.0962*workHil[r][s+_ind] + 0.5769*workHil[r-2][s+_ind] - 0.5769*workHil[r-4][s+_ind] - 0.0962*workHil[r-6][s+_ind]) * (0.075*workHil[r-1][s+_period] + 0.54))

      workHil[r][s+_price]      = price; 
      if (r<6) { workHil[r][s+_smooth]=price; return(0); }
      workHil[r][s+_smooth]     = (4.0*workHil[r][s+_price]+3.0*workHil[r-1][s+_price]+2.0*workHil[r-2][s+_price]+workHil[r-3][s+_price])/10.0;
      workHil[r][s+_detrender]  = _calcComp(_smooth);
      workHil[r][s+_Q1]         = 0.15*_calcComp(_detrender)     +0.85*workHil[r-1][s+_Q1];
      workHil[r][s+_I1]         = 0.15*workHil[r-3][s+_detrender]+0.85*workHil[r-1][s+_I1];
      workHil[r][s+_phase]      = workHil[r-1][s+_phase];
      workHil[r][s+_instPeriod] = workHil[r-1][s+_instPeriod];

      //
      //
      //
      //
      //
           
         if (MathAbs(workHil[r][s+_I1])>0)
                     workHil[r][s+_phase] = 180.0/M_PI*MathArctan(MathAbs(workHil[r][s+_Q1]/workHil[r][s+_I1]));
           
         if (workHil[r][s+_I1]<0 && workHil[r][s+_Q1]>0) workHil[r][s+_phase] = 180.0-workHil[r][s+_phase];
         if (workHil[r][s+_I1]<0 && workHil[r][s+_Q1]<0) workHil[r][s+_phase] = 180.0+workHil[r][s+_phase];
         if (workHil[r][s+_I1]>0 && workHil[r][s+_Q1]<0) workHil[r][s+_phase] = 360.0-workHil[r][s+_phase];

      //
      //
      //
      //
      //
                        
      workHil[r][s+_deltaPhase] = workHil[r-1][s+_phase]-workHil[r][s+_phase];

         if (workHil[r-1][s+_phase]<90.0 && workHil[r][s+_phase]>270.0)
             workHil[r][s+_deltaPhase] = 360.0+workHil[r-1][s+_phase]-workHil[r][s+_phase];
             workHil[r][s+_deltaPhase] = MathMax(MathMin(workHil[r][s+_deltaPhase],60),7);
      
            //
            //
            //
            //
            //
                  
            double alpha    = 2.0/(1.0+MathMax(filter,1));
            double phaseSum = 0; int k=0; for (; phaseSum<cyclesToReach*360.0 && (r-k)>0; k++) phaseSum += workHil[r-k][s+_deltaPhase];
               if (k>0) workHil[r][s+_instPeriod]= k;
                  workHil[r][s+_period] = (i>0) ? workHil[r-1][s+_period]+alpha*(workHil[r][s+_instPeriod]-workHil[r-1][s+_period]) : k;
   return (workHil[r][s+_period]);
}

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)
{
   string name = arrowsIdentifier+":"+(string)Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //
      
      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 CatchBullishDivergence(double& values[], int i)
{
   i++;
            cbulld[(int)MathMin(i,Bars-1)] = EMPTY_VALUE;
            hbulld[(int)MathMin(i,Bars-1)] = EMPTY_VALUE;
            ObjectDelete(divergenceUniqueID+"l"+ DoubleToStr(Time[(int)MathMin(i,Bars-1)],0));
            ObjectDelete(divergenceUniqueID+"l"+"os" + DoubleToStr(Time[(int)MathMin(i,Bars-1)],0));            
   if (!IsIndicatorLow(values,(int)MathMin(i,Bars-1))) return;  

   //
   //
   //
   //
   //

   int currentLow = i;
   int lastLow    = GetIndicatorLastLow(values,i+1);
      if (currentLow>=0 && currentLow<Bars && lastLow>=0) 
      if (values[currentLow] > values[lastLow] && Low[currentLow] < Low[lastLow])
      {
        if (ShowClassicalDivergence)
        {
          cbulld[currentLow] = values[currentLow] - DivergencearrowsLowerGap*iATR(NULL,0,10,i);
          if(divergenceOnChartVisible)  DrawPriceTrendLine("l",Time[currentLow],Time[lastLow],Low[currentLow],Low[lastLow],          divergenceBullishColor,STYLE_SOLID);
          if(divergenceOnValuesVisible) DrawIndicatorTrendLine("l",Time[currentLow],Time[lastLow],values[currentLow],values[lastLow],divergenceBullishColor,STYLE_SOLID);
        }
      }
      
      if (currentLow>=0 && currentLow<Bars && lastLow>=0) 
      if (values[currentLow] < values[lastLow] && Low[currentLow] > Low[lastLow])
      {
        if (ShowHiddenDivergence)
        {
          hbulld[currentLow] = values[currentLow] - DivergencearrowsLowerGap*iATR(NULL,0,10,i);
          if(divergenceOnChartVisible)  DrawPriceTrendLine("l",Time[currentLow],Time[lastLow],Low[currentLow],Low[lastLow],           divergenceBullishColor, STYLE_DOT);
          if(divergenceOnValuesVisible) DrawIndicatorTrendLine("l",Time[currentLow],Time[lastLow],values[currentLow],values[lastLow], divergenceBullishColor, STYLE_DOT);
        }
      }
}

//
//
//
//
//

void CatchBearishDivergence(double& values[], int i)
{
   i++; 
            cbeard[(int)MathMin(i,Bars-1)] = EMPTY_VALUE;
            hbeard[(int)MathMin(i,Bars-1)] = EMPTY_VALUE;
            ObjectDelete(divergenceUniqueID+"h"+DoubleToStr(Time[(int)MathMin(i,Bars-1)],0));
            ObjectDelete(divergenceUniqueID+"h"+"os" + DoubleToStr(Time[(int)MathMin(i,Bars-1)],0));            
   if (IsIndicatorPeak(values,(int)MathMin(i,Bars-1)) == false) return;

   //
   //
   //
   //
   //
      
   int currentPeak = i;
   int lastPeak = GetIndicatorLastPeak(values,i+1);
      if (currentPeak>=0 && currentPeak<Bars && lastPeak>=0) 
      if (values[currentPeak] < values[lastPeak] && High[currentPeak]>High[lastPeak])
      {
        if (ShowClassicalDivergence)
        {
          cbeard[currentPeak] = values[currentPeak] + DivergencearrowsUpperGap*iATR(NULL,0,10,i);
          if (divergenceOnChartVisible)  DrawPriceTrendLine("h",Time[currentPeak],Time[lastPeak],High[currentPeak],High[lastPeak],        divergenceBearishColor,STYLE_SOLID);
          if (divergenceOnValuesVisible) DrawIndicatorTrendLine("h",Time[currentPeak],Time[lastPeak],values[currentPeak],values[lastPeak],divergenceBearishColor,STYLE_SOLID);
        }
      }
      if (currentPeak>=0 && currentPeak<Bars && lastPeak>=0) 
      if (values[currentPeak] > values[lastPeak] && High[currentPeak] < High[lastPeak])
      {
        if (ShowHiddenDivergence)
        {
          hbeard[currentPeak] = values[currentPeak] + DivergencearrowsUpperGap*iATR(NULL,0,10,i);
          if (divergenceOnChartVisible)  DrawPriceTrendLine("h",Time[currentPeak],Time[lastPeak],High[currentPeak],High[lastPeak],         divergenceBearishColor, STYLE_DOT);
          if (divergenceOnValuesVisible) DrawIndicatorTrendLine("h",Time[currentPeak],Time[lastPeak],values[currentPeak],values[lastPeak], divergenceBearishColor, STYLE_DOT);
        }
      }
}

//
//
//
//
//

bool IsIndicatorPeak(double& values[], int i) { return(values[i] >= values[(int)MathMin(i+1,Bars-1)] && values[i] > values[(int)MathMin(i+2,Bars-1)] && values[i] > values[(int)MathMax(i-1,0)]); }
bool IsIndicatorLow( double& values[], int i) { return(values[i] <= values[(int)MathMin(i+1,Bars-1)] && values[i] < values[(int)MathMin(i+2,Bars-1)] && values[i] < values[(int)MathMax(i-1,0)]); }

int GetIndicatorLastPeak(double& values[], int shift)
{
   for(int i = shift+5; i<Bars && (i+2)<(Bars-1) && (i-2)>=0; i++)
         if (values[i] >= values[i+1] && values[i] > values[i+2] && values[i] >= values[i-1] && values[i] > values[i-2]) return(i);
   return(-1);
}
int GetIndicatorLastLow(double& values[], int shift)
{
   for(int i = shift+5; i<Bars && (i+2)<(Bars-1) && (i-2)>=0; i++)
         if (values[i] <= values[i+1] && values[i] < values[i+2] && values[i] <= values[i-1] && values[i] < values[i-2]) return(i);
   return(-1);
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

void DrawPriceTrendLine(string first,datetime t1, datetime t2, double p1, double p2, color lineColor, double style)
{
   string   label = divergenceUniqueID+first+"os"+DoubleToStr(t1,0);
   ObjectDelete(label);
      ObjectCreate(label, OBJ_TREND, 0, t1+Period()*60-1, p1, t2, p2, 0, 0);
         ObjectSet(label, OBJPROP_RAY, false);
         ObjectSet(label, OBJPROP_COLOR, lineColor);
         ObjectSet(label, OBJPROP_STYLE, style);
}
void DrawIndicatorTrendLine(string first,datetime t1, datetime t2, double p1, double p2, color lineColor, double style)
{
   int indicatorWindow = WindowFind(shortName);
   if (indicatorWindow < 0) return;
   string label = divergenceUniqueID+first+DoubleToStr(t1,0);
   ObjectDelete(label);
      ObjectCreate(label, OBJ_TREND, indicatorWindow, t1+Period()*60-1, p1, t2, p2, 0, 0);
         ObjectSet(label, OBJPROP_RAY, false);
         ObjectSet(label, OBJPROP_COLOR, lineColor);
         ObjectSet(label, OBJPROP_STYLE, style);
}