divergenceviewer_ad

Download script
Author: Scriptong
divergenceviewer_ad

This script is designed to automatically detect and visualize divergences on your trading charts. In simple terms, a divergence occurs when the price of an asset (like a currency pair or stock) moves in one direction, but a technical indicator suggests it is moving in the opposite direction—often signaling a potential trend reversal.

Core Functionality

The tool works by constantly monitoring two different data streams simultaneously:

  1. Market Price: The actual movement of the asset (Highs, Lows, or Closing prices).
  2. Technical Indicators: Data from various tools such as RSI, MACD, Stochastic, Momentum, and more (or even your own custom indicators).

How the Logic Works

Instead of just looking for general trends, the script follows a sophisticated step-by-step logic to identify high-quality signals:

  • Finding Extremums: The script searches for "peaks" (highs) and "valleys" (lows) in both the price chart and the chosen technical indicator.
  • Pairing Data Points: When it finds a peak or valley in one area, it looks nearby to find the corresponding point in the other area. This ensures that it is comparing two relevant moments in time.
  • Divergence Identification: Once it has paired these points, it checks for contradictions:
    • Bullish Divergence: Price makes a lower low, but the indicator makes a higher low (suggesting buyers may be stepping in).
    • Bearish Divergence: Price makes a higher high, but the indicator makes a lower high (suggesting sellers may be taking over).
  • Refining the Results (Classes A, B, C, and Hidden): The script doesn't treat every divergence the same. It categorizes them into different "Classes" based on how significant the price movement is compared to the indicator's movement. This allows you to filter out minor "noise" and focus only on the most significant signals.
  • Verification (The Breakout Check): To prevent "fake" signals, the script uses a mathematical calculation to ensure that the current trend hasn't already broken through the line connecting the two points. If the price has already crossed that boundary, the signal is ignored.

Visuals and Alerts

To make this information easy for a trader to act on, the script provides several visual aids:

  • Trend Lines: It draws actual lines on your chart connecting the divergence points, making it easy to see the "gap" between price action and indicator behavior.
  • Color Coding: Different classes of divergence are assigned unique colors so you can instantly distinguish between strong signals and weaker ones.
  • Notifications: The script can be configured to send live alerts or "Push" notifications to your device the moment a new divergence is detected, so you don't have to stare at the screen constantly.

User Customization

The tool is highly flexible. You can choose:

  • Which Base Indicator to use (e.g., William Blair, RSI, MACD).
  • Which Price Type to monitor (Close, High, or Low).
  • Whether to show/hide specific Classes of Divergence.
  • The Depth of the search area to find previous reference points.
Indicators Used
Relative strength indexMACD HistogramMomentum indicatorRelative Vigor indexStochastic oscillatorStandard Deviation indicatorMoving average indicatorMoving average indicator
Miscellaneous
It issuies visual alerts to the screenImplements a curve of type %1
18 Views
0 Downloads
0 Favorites
divergenceviewer_ad
//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property copyright "Scriptong"
#property link      "http://advancetools.net"
#property description "English: Displaying of the divergence based on the testimony of various indicators.\nRussian: Îòîáðàæåíèå äèâåðãåíöèè íà îñíîâå ïîêàçàíèé ðàçëè÷íûõ èíäèêàòîðîâ."
#property version "1.13"
#property strict

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1  clrTurquoise

#property indicator_level1 0.0
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_YESNO
  {
   NO,                                                                                             // No / Íåò
   YES                                                                                             // Yes / Äà
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_INDICATOR_TYPE
  {
   RSI,                                                                                            // RSI
   MACD,                                                                                           // MACD   
   MOMENTUM,                                                                                       // Momentum
   RVI,                                                                                            // RVI
   STOCHASTIC,                                                                                     // Stochastic
   StdDev,                                                                                         // Standart deviation
   DERIVATIVE,                                                                                     // Derivative / ïðîèçâîäíàÿ
   WILLIAM_BLAU,                                                                                   // William Blau
   CUSTOM                                                                                          // Custom / Ïîëüçîâàòåëüñêèé
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_EXTREMUM_TYPE
  {
   EXTREMUM_TYPE_NONE,
   EXTREMUM_TYPE_MIN,
   EXTREMUM_TYPE_MAX
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_MARKET_APPLIED_PRICE
  {
   MARKET_APPLIED_PRICE_CLOSE,                                                                     // Close/Close   
   MARKET_APPLIED_PRICE_HIGHLOW                                                                    // High/Low   
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_PRICE_TYPE
  {
   PRICE_TYPE_INDICATOR,
   PRICE_TYPE_MARKET
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_CUSTOM_PARAM_CNT
  {
   PARAM_CNT_0,                                                                                    // 0   
   PARAM_CNT_1,                                                                                    // 1   
   PARAM_CNT_2,                                                                                    // 2   
   PARAM_CNT_3,                                                                                    // 3   
   PARAM_CNT_4,                                                                                    // 4   
   PARAM_CNT_5,                                                                                    // 5   
   PARAM_CNT_6,                                                                                    // 6   
   PARAM_CNT_7,                                                                                    // 7   
   PARAM_CNT_8,                                                                                    // 8   
   PARAM_CNT_9,                                                                                    // 9   
   PARAM_CNT_10,                                                                                   // 10   
   PARAM_CNT_11,                                                                                   // 11   
   PARAM_CNT_12,                                                                                   // 12   
   PARAM_CNT_13,                                                                                   // 13   
   PARAM_CNT_14,                                                                                   // 14   
   PARAM_CNT_15,                                                                                   // 15   
   PARAM_CNT_16,                                                                                   // 16   
   PARAM_CNT_17,                                                                                   // 17   
   PARAM_CNT_18,                                                                                   // 18   
   PARAM_CNT_19,                                                                                   // 19   
   PARAM_CNT_20                                                                                    // 20   
  };

//--- Input parameters of indicator
input ENUM_INDICATOR_TYPE      i_indicatorType       = WILLIAM_BLAU;                               // Base indicator / Áàçîâûé èíäèêàòîð
input int                      i_divergenceDepth     = 20;                                         // Depth of 2nd ref. point search / Ãëóáèíà ïîèñêà 2îé îï. òî÷êè

input string                   i_string1="The base indicator parameters / Ïàðàìåòðû áàçîâîãî èíäèêàòîðà";            // ============================
input int                      i_barsPeriod1         = 8000;                                       // First calculate period / Ïåðâûé ïåðèîä ðàñ÷åòà
input int                      i_barsPeriod2         = 2;                                          // Second calculate period / Âòîðîé ïåðèîä ðàñ÷åòà
input int                      i_barsPeriod3         = 1;                                          // Third calculate period / Òðåòèé ïåðèîä ðàñ÷åòà
input ENUM_APPLIED_PRICE       i_indAppliedPrice     = PRICE_CLOSE;                                // Applied price of indicator / Öåíà ðàñ÷åòà èíäèêàòîðà
input ENUM_MA_METHOD           i_indMAMethod         = MODE_EMA;                                   // MA calculate method / Ìåòîä ðàñ÷åòà ñðåäíåãî

input string                   i_string2="Price extremum parameters / Ïàðàìåòðû öåíîâîãî ýêñòðåìóìà";            // ============================
input int                      i_findExtInterval     = 10;                                         // Price ext. to indicator ext. / Îò ýêñò. öåíû äî ýêñò. èíä.
input ENUM_MARKET_APPLIED_PRICE i_marketAppliedPrice = MARKET_APPLIED_PRICE_CLOSE;                 // Applied price of market / Èñïîëüçóåìàÿ ðûíî÷íàÿ öåíà

input string                   i_string3="Custom indicator / Ïîëüçîâàòåëüñêèé èíäèêàòîð";            // ============================
input string                   i_customName          = "Sentiment_Line";                           // The name of indicator / Èìÿ èíäèêàòîðà
input int                      i_customBuffer        = 0;                                          // Index of data buffer / Èíäåêñ áóôåðà äëÿ ñúåìà äàííûõ
input ENUM_CUSTOM_PARAM_CNT    i_customParamCnt      = PARAM_CNT_3;                                // Amount of ind. parameters / Êîë-âî ïàðàìåòðîâ èíäèêàòîðà
input double                   i_customParam1         = 13.0;                                      // Value of the 1st parameter / Çíà÷åíèå 1-îãî ïàðàìåòðà
input double                   i_customParam2         = 1.0;                                       // Value of the 2nd parameter / Çíà÷åíèå 2-îãî ïàðàìåòðà
input double                   i_customParam3         = 0.0;                                       // Value of the 3rd parameter / Çíà÷åíèå 3-îãî ïàðàìåòðà
input double                   i_customParam4         = 0.0;                                       // Value of the 4th parameter / Çíà÷åíèå 4-îãî ïàðàìåòðà
input double                   i_customParam5         = 0.0;                                       // Value of the 5th parameter / Çíà÷åíèå 5-îãî ïàðàìåòðà
input double                   i_customParam6         = 0.0;                                       // Value of the 6th parameter / Çíà÷åíèå 6-îãî ïàðàìåòðà
input double                   i_customParam7         = 0.0;                                       // Value of the 7th parameter / Çíà÷åíèå 7-îãî ïàðàìåòðà
input double                   i_customParam8         = 0.0;                                       // Value of the 8th parameter / Çíà÷åíèå 8-îãî ïàðàìåòðà
input double                   i_customParam9         = 0.0;                                       // Value of the 9th parameter / Çíà÷åíèå 9-îãî ïàðàìåòðà
input double                   i_customParam10        = 0.0;                                       // Value of the 10th parameter / Çíà÷åíèå 10-îãî ïàðàìåòðà
input double                   i_customParam11        = 0.0;                                       // Value of the 11th parameter / Çíà÷åíèå 11-îãî ïàðàìåòðà
input double                   i_customParam12        = 0.0;                                       // Value of the 12th parameter / Çíà÷åíèå 12-îãî ïàðàìåòðà
input double                   i_customParam13        = 0.0;                                       // Value of the 13th parameter / Çíà÷åíèå 13-îãî ïàðàìåòðà
input double                   i_customParam14        = 0.0;                                       // Value of the 14th parameter / Çíà÷åíèå 14-îãî ïàðàìåòðà
input double                   i_customParam15        = 0.0;                                       // Value of the 15th parameter / Çíà÷åíèå 15-îãî ïàðàìåòðà
input double                   i_customParam16        = 0.0;                                       // Value of the 16th parameter / Çíà÷åíèå 16-îãî ïàðàìåòðà
input double                   i_customParam17        = 0.0;                                       // Value of the 17th parameter / Çíà÷åíèå 17-îãî ïàðàìåòðà
input double                   i_customParam18        = 0.0;                                       // Value of the 18th parameter / Çíà÷åíèå 18-îãî ïàðàìåòðà
input double                   i_customParam19        = 0.0;                                       // Value of the 19th parameter / Çíà÷åíèå 19-îãî ïàðàìåòðà
input double                   i_customParam20        = 0.0;                                       // Value of the 20th parameter / Çíà÷åíèå 20-îãî ïàðàìåòðà

input string                   i_string4="Parameters of displaying / Ïàðàìåòðû îòîáðàæåíèÿ";                    // ============================
input ENUM_YESNO               i_isAlert             = YES;                                        // Alert on divergence? / Ñèãíàë ïðè äèâåðãåíöèè?
input ENUM_YESNO               i_isPush              = YES;                                        // Notification on divergence? / Óâåäîìëÿòü ïðè äèâåðãåíöèè?
input string                   i_string4_1           = "Divergence class A / Äèâåðãåíöèè êëàññà À";// ============================
input ENUM_YESNO               i_showClassA          = YES;                                        // Show / Îòîáðàæàòü
input color                    i_bullsDivAColor      = clrBlue;                                    // Color of bulls divergence line / Öâåò ëèíèé áû÷üåé äèâåðãåíöèè
input color                    i_bearsDivAColor      = clrRed;                                     // Color of bears divergence line / Öâåò ëèíèé ìåäâ. äèâåðãåíöèè
input string                   i_string4_2           = "Divergence class B / Äèâåðãåíöèè êëàññà B";// ============================
input ENUM_YESNO               i_showClassB          = NO;                                         // Show / Îòîáðàæàòü
input color                    i_bullsDivBColor      = clrDodgerBlue;                              // Color of bulls divergence line / Öâåò ëèíèé áû÷üåé äèâåðãåíöèè
input color                    i_bearsDivBColor      = clrMaroon;                                  // Color of bears divergence line / Öâåò ëèíèé ìåäâ. äèâåðãåíöèè
input string                   i_string4_3           = "Divergence class C / Äèâåðãåíöèè êëàññà C";// ============================
input ENUM_YESNO               i_showClassC          = NO;                                         // Show / Îòîáðàæàòü
input color                    i_bullsDivCColor      = clrDeepSkyBlue;                             // Color of bulls divergence line / Öâåò ëèíèé áû÷üåé äèâåðãåíöèè
input color                    i_bearsDivCColor      = clrPurple;                                  // Color of bears divergence line / Öâåò ëèíèé ìåäâ. äèâåðãåíöèè
input string                   i_string4_4           = "Hidden divergence / Ñêðûòàÿ äèâåðãåíöèÿ";  // ============================
input ENUM_YESNO               i_showHidden          = NO;                                         // Show / Îòîáðàæàòü
input color                    i_bullsDivHColor      = clrYellowGreen;                             // Color of bulls divergence line / Öâåò ëèíèé áû÷üåé äèâåðãåíöèè
input color                    i_bearsDivHColor      = clrIndigo;                                  // Color of bears divergence line / Öâåò ëèíèé ìåäâ. äèâåðãåíöèè
input int                      i_indBarsCount        = 10000;                                      // The number of bars to display / Êîëè÷åñòâî áàðîâ îòîáðàæåíèÿ
//--- The indicator's buffers
double            g_indValues[];
double            g_tempBuffer[];
//--- Other global variables of indicator
bool              g_activate;                                                                      // Sign of successful initialization of indicator
int               g_indSubWindow;                                                                  // Subwindow index of indicator
string            g_indName,// The unique name of the indicator for easy location indicator subwindow
                  g_tfName;                                                                        // Name of current TF

#define PREFIX                                  "DIVVIEW_"                                         // Prefix the name of the graphic objects which displayed by indicator
#define TITLE_CLASS_A                           "Class A"
#define TITLE_CLASS_B                           "Class B"
#define TITLE_CLASS_C                           "Class C"
#define TITLE_CLASS_H                           "Hidden divergence"
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
  {
   g_activate=false;

   if(!IsTuningParametersCorrect())
      return INIT_FAILED;

   if(!BuffersBind())
      return (INIT_FAILED);

   g_tfName=GetCurrentTFName();
   g_indSubWindow=-1;
   g_activate=true;
   return INIT_SUCCEEDED;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the correctness of input parameters                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTuningParametersCorrect()
  {
   string name=WindowExpertName();

   bool isRussianLang=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian");

   if(i_divergenceDepth<1)
     {
      Alert(name,(isRussianLang)? ": ãëóáèíà ïîèñêà âòîðîé îïîðíîé òî÷êè äîëæíà áûòü 1 è áîëåå áàðîâ. Èíäèêàòîð îòêëþ÷åí." :
            ": depth search for the second reference point should be 1 or more bars. The indicator is turned off.");
      return false;
     }

   if(i_barsPeriod1<1)
     {
      Alert(name,(isRussianLang)? ": ïåðâîå êîëè÷åñòâî áàðîâ äëÿ ðàñ÷åòà ïîêàçàíèé èíäèêàòîðà ìåíåå 1. Èíäèêàòîð îòêëþ÷åí." :
            ": the first amount of bars for calculate the indicator values is less then 1. The indicator is turned off.");
      return false;
     }

   if(i_barsPeriod2<1)
     {
      Alert(name,(isRussianLang)? ": âòîðîå êîëè÷åñòâî áàðîâ äëÿ ðàñ÷åòà ïîêàçàíèé èíäèêàòîðà ìåíåå 1. Èíäèêàòîð îòêëþ÷åí." :
            ": the second amount of bars for calculate the indicator values is less then 1. The indicator is turned off.");
      return false;
     }

   if(i_barsPeriod3<1)
     {
      Alert(name,(isRussianLang)? ": òðåòüå êîëè÷åñòâî áàðîâ äëÿ ðàñ÷åòà ïîêàçàíèé èíäèêàòîðà ìåíåå 1. Èíäèêàòîð îòêëþ÷åí." :
            ": the third amount of bars for calculate the indicator values is less then 1. The indicator is turned off.");
      return false;
     }

   if(i_findExtInterval<1)
     {
      Alert(name,(isRussianLang)? ": èíòåðâàë ïîèñêà ýêñòðåìóìà öåíû äîëæåí áûòü áîëåå íóëÿ áàðîâ. Èíäèêàòîð îòêëþ÷åí." :
            ": the interval of search of price extremum must be greater than zero bars. The indicator is turned off.");
      return false;
     }

   return (true);
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Defining the current TF name                                                                                                                                                                      |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetCurrentTFName()
  {
   switch(_Period)
     {
      case PERIOD_M1: return "M1";
      case PERIOD_M5: return "M5";
      case PERIOD_M15: return "M15";
      case PERIOD_M30: return "M30";
      case PERIOD_H1: return "H1";
      case PERIOD_H4: return "H4";
      case PERIOD_D1: return "D1";
      case PERIOD_W1: return "W1";
      case PERIOD_MN1: return "MN1";
     }

   return "U/D";
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Binding the indicator buffers with arrays                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool BuffersBind()
  {
   if(i_indicatorType==WILLIAM_BLAU)
      IndicatorBuffers(2);
   string name=WindowExpertName();
   bool isRussianLang=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian");

   if(!SetIndexBuffer(0,g_indValues))
     {
      Alert(name,(isRussianLang)? ": îøèáêà ñâÿçûâàíèÿ ìàññèâîâ ñ áóôåðàìè èíäèêàòîðà. Îøèáêà ¹"+IntegerToString(GetLastError()) :
            ": error of binding of the arrays and the indicator buffers. Error N"+IntegerToString(GetLastError()));
      return false;
     }

   if(i_indicatorType==WILLIAM_BLAU)
      if(!SetIndexBuffer(1,g_tempBuffer))
        {
         Alert(name,(isRussianLang)? ": îøèáêà ñâÿçûâàíèÿ ìàññèâîâ ñ áóôåðàìè èíäèêàòîðà. Îøèáêà ¹"+IntegerToString(GetLastError()) :
               ": error of binding of the arrays and the indicator buffers. Error N"+IntegerToString(GetLastError()));
         return false;
        }

   SetIndexStyle(0,DRAW_LINE);
   if(i_indicatorType==WILLIAM_BLAU)
      SetIndexStyle(1,DRAW_NONE);

   g_indName="DivViewer at "+GetBaseIndicatorName()+IntegerToString(GetTickCount());
   IndicatorShortName(g_indName);

   return true;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Defining the name of the base indicator                                                                                                                                                           |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string GetBaseIndicatorName()
  {
   if(i_indicatorType==CUSTOM)
      return i_customName + " (" + DoubleToString(i_customParam1, 1) + ", " + DoubleToString(i_customParam2, 1) + ", " + DoubleToString(i_customParam3, 1) + ") ";

   return EnumToString(i_indicatorType) + " (" + IntegerToString(i_barsPeriod1) + ", " + IntegerToString(i_barsPeriod2) + ", " + IntegerToString(i_barsPeriod3) + ") ";
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator deinitialization function                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   DeleteAllObjects();
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Deleting of all graphical objects                                                                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void DeleteAllObjects()
  {
   string prefix=PREFIX+IntegerToString(g_indSubWindow);
   int strLen= StringLen(prefix);
   for(int i = ObjectsTotal()-1; i>= 0; i--)
      if(StringSubstr(ObjectName(i),0,strLen)==prefix)
         ObjectDelete(ObjectName(i));
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying the trend line                                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ShowTrendLine(int subWindow,datetime time1,double price1,datetime time2,double price2,string toolTip,color clr)
  {
   string name=PREFIX+IntegerToString(g_indSubWindow)+IntegerToString(subWindow)+IntegerToString(time1)+IntegerToString(time2);

   if(ObjectFind(0,name)<0)
     {
      ObjectCreate(0,name,OBJ_TREND,subWindow,time1,price1,time2,price2);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_BACK,false);
      ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
      ObjectSetInteger(0,name,OBJPROP_RAY,false);
      ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
      ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
      ObjectSetString(0,name,OBJPROP_TOOLTIP,toolTip);
      return;
     }

   ObjectMove(0,name,0,time1,price1);
   ObjectMove(0,name,1,time2,price2);
   ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
   ObjectSetString(0,name,OBJPROP_TOOLTIP,toolTip);
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of bar index which needed to recalculate                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex(int &total,const int ratesTotal,const int prevCalculated)
  {
   total=ratesTotal-1;

   if(i_indBarsCount>0 && i_indBarsCount<total)
      total=MathMin(i_indBarsCount,total);

   if(prevCalculated<ratesTotal-1)
     {
      InitializeBuffers();
      return (total);
     }

   return (MathMin(ratesTotal - prevCalculated, total));
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Initialize of all indicator buffers                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void InitializeBuffers()
  {
   ArrayInitialize(g_indValues,EMPTY_VALUE);
   ArrayInitialize(g_tempBuffer,EMPTY_VALUE);
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculate the price value at the specified bar                                                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
double GetPrice(int barIndex)
  {
   barIndex=(int) MathMin(Bars-1,barIndex);

   switch(i_indAppliedPrice)
     {
      case PRICE_CLOSE:    return(Close[barIndex]);
      case PRICE_OPEN:     return(Open[barIndex]);
      case PRICE_HIGH:     return(High[barIndex]);
      case PRICE_LOW:      return(Low[barIndex]);
      case PRICE_MEDIAN:   return((High[barIndex] + Low[barIndex]) / 2);
      case PRICE_TYPICAL:  return((High[barIndex] + Low[barIndex] + Close[barIndex]) / 3);
      case PRICE_WEIGHTED: return((High[barIndex] + Low[barIndex] + 2 * Close[barIndex]) / 4);
     }

   return 0.0;
  }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculate the value of the custom indicator at the specified bar                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
double GetCustomIndicatorValue(int barIndex)
  {
   switch(i_customParamCnt)
     {
      case PARAM_CNT_0:    return iCustom(NULL, 0, i_customName, i_customBuffer, barIndex);
      case PARAM_CNT_1:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customBuffer, barIndex);
      case PARAM_CNT_2:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customBuffer, barIndex);
      case PARAM_CNT_3:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customBuffer, barIndex);
      case PARAM_CNT_4:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customBuffer, barIndex);
      case PARAM_CNT_5:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customBuffer, barIndex);
      case PARAM_CNT_6:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customBuffer, barIndex);
      case PARAM_CNT_7:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7,
                                          i_customBuffer,barIndex);
         case PARAM_CNT_8:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                             i_customBuffer,barIndex);
            case PARAM_CNT_9:    return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                i_customParam9,i_customBuffer,barIndex);
               case PARAM_CNT_10:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                   i_customParam9,i_customParam10,i_customBuffer,barIndex);
                  case PARAM_CNT_11:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                      i_customParam9,i_customParam10,i_customParam11,i_customBuffer,barIndex);
                     case PARAM_CNT_12:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                         i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customBuffer,barIndex);
                        case PARAM_CNT_13:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                            i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customBuffer,barIndex);
                           case PARAM_CNT_14:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                               i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customBuffer,barIndex);
                              case PARAM_CNT_15:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                  i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customBuffer,barIndex);
                                 case PARAM_CNT_16:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                     i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customParam16,
                                                                     i_customBuffer,barIndex);
                                    case PARAM_CNT_17:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                        i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customParam16,i_customParam17,
                                                                        i_customBuffer,barIndex);
                                       case PARAM_CNT_18:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                           i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customParam16,i_customParam17,
                                                                           i_customParam18,i_customBuffer,barIndex);
                                          case PARAM_CNT_19:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                              i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customParam16,i_customParam17,
                                                                              i_customParam18,i_customParam19,i_customBuffer,barIndex);
                                             case PARAM_CNT_20:   return iCustom(NULL, 0, i_customName, i_customParam1, i_customParam2, i_customParam3, i_customParam4, i_customParam5, i_customParam6, i_customParam7, i_customParam8,
                                                                                 i_customParam9,i_customParam10,i_customParam11,i_customParam12,i_customParam13,i_customParam14,i_customParam15,i_customParam16,i_customParam17,
                                                                                 i_customParam18,i_customParam19,i_customParam20,i_customBuffer,barIndex);
                                                }

                                                return 0.0;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculate the value of base indicator at the specified bar                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   double GetBaseIndicatorValue(int barIndex)
     {
      switch(i_indicatorType)
        {
         case RSI:         return iRSI(NULL, 0, i_barsPeriod1, i_indAppliedPrice, barIndex);
         case MACD:        return iMACD(NULL, 0, i_barsPeriod1, i_barsPeriod2, 1, i_indAppliedPrice, MODE_MAIN, barIndex);
         case MOMENTUM:    return iMomentum(NULL, 0, i_barsPeriod1, i_indAppliedPrice, barIndex);
         case RVI:         return iRVI(NULL, 0, i_barsPeriod1, MODE_MAIN, barIndex);
         case STOCHASTIC:  return iStochastic(NULL, 0, i_barsPeriod1, i_barsPeriod2, i_barsPeriod3, i_indMAMethod, 1, MODE_MAIN, barIndex);
         case StdDev:      return iStdDev(NULL, 0, i_barsPeriod1, 0, i_indMAMethod, i_indAppliedPrice, barIndex);
         case DERIVATIVE:  return 100.0 * (GetPrice(barIndex) - GetPrice(barIndex + i_barsPeriod1)) / i_barsPeriod1;
         case CUSTOM:      return GetCustomIndicatorValue(barIndex);
        }

      return 0.0;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Receive the price of specified bar index                                                                                                                                                          |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   double GetMarketPrice(int barIndex,ENUM_EXTREMUM_TYPE extremumType)
     {
      if(barIndex<0 || barIndex>=Bars)
         return 0.0;

      if(i_marketAppliedPrice==MARKET_APPLIED_PRICE_CLOSE)
         return Close[barIndex];

      if(extremumType==EXTREMUM_TYPE_MAX)
         return High[barIndex];

      return Low[barIndex];
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determining of the extremum type at the spesified element of speciefied array                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   ENUM_EXTREMUM_TYPE GetBufferExtremum(int barIndex,int total,const double &buffer[])
     {
      if(barIndex+2>=total || barIndex<0)
        {
         Print("Possible error! ",__FUNCTION__,", barIndex = ",barIndex,", total bars = ",total);
         return EXTREMUM_TYPE_NONE;
        }

      double valueRight=buffer[barIndex];
      double valueCenter=buffer[barIndex+1];
      double valueLeft=buffer[barIndex+2];

      if(valueCenter<valueRight && valueCenter<valueLeft)
         return EXTREMUM_TYPE_MIN;

      if(valueCenter>valueRight && valueCenter>valueLeft)
         return EXTREMUM_TYPE_MAX;

      return EXTREMUM_TYPE_NONE;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determining whether an extremum of price at a specified bar                                                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   ENUM_EXTREMUM_TYPE GetMarketExtremum(int barIndex,int total,ENUM_EXTREMUM_TYPE desiredExtremum)
     {
      if(i_marketAppliedPrice==MARKET_APPLIED_PRICE_HIGHLOW)
        {
         if(desiredExtremum!=EXTREMUM_TYPE_MIN && GetBufferExtremum(barIndex,total,High)==EXTREMUM_TYPE_MAX)
            return EXTREMUM_TYPE_MAX;

         if(desiredExtremum!=EXTREMUM_TYPE_MAX && GetBufferExtremum(barIndex,total,Low)==EXTREMUM_TYPE_MIN)
            return EXTREMUM_TYPE_MIN;

         return EXTREMUM_TYPE_NONE;
        }

      return GetBufferExtremum(barIndex, total, Close);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculating the coefficients K and B of the equation straight line through specified points                                                                                                       |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   double GetBAndKKoefs(int x1,double y1,int x2,double y2,double &kKoef)
     {
      if(x2==x1)
         return EMPTY_VALUE;

      kKoef=(y2-y1)/(x2-x1);
      return y1 - kKoef * x1;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Calculating the price by values of base indicator or by market price                                                                                                                              |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   double GetIndOrMarketPrice(ENUM_EXTREMUM_TYPE extremumType,ENUM_PRICE_TYPE priceType,int barIndex)
     {
      if(priceType==PRICE_TYPE_INDICATOR)
         return g_indValues[barIndex];

      return GetMarketPrice(barIndex, extremumType);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Is break the divergence line?                                                                                                                                                                     |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   bool IsDivLineBreak(ENUM_EXTREMUM_TYPE extremumType,ENUM_PRICE_TYPE priceType,int leftBarIndex,int rightBarIndex)
     {
      double kKoef;
      double bKoef=GetBAndKKoefs(rightBarIndex,GetIndOrMarketPrice(extremumType,priceType,rightBarIndex),leftBarIndex,GetIndOrMarketPrice(extremumType,priceType,leftBarIndex),kKoef);
      if(bKoef==EMPTY_VALUE)
         return true;

      for(int i=leftBarIndex-1; i>rightBarIndex; i--)
        {
         double lineValue = kKoef * i + bKoef;
         double basePrice = GetIndOrMarketPrice(extremumType, priceType, i);

         if(extremumType==EXTREMUM_TYPE_MAX && lineValue<basePrice)
            return true;

         if(extremumType==EXTREMUM_TYPE_MIN && lineValue>basePrice)
            return true;
        }

      return false;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| The class definition of divergence                                                                                                                                                                |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   string GetDivergenceType(double indRightValue,double indLeftValue,double priceRightValue,double priceLeftValue,ENUM_EXTREMUM_TYPE extType)
     {
      if(extType==EXTREMUM_TYPE_MIN)
        {
         if(indRightValue>indLeftValue && priceRightValue<priceLeftValue)
            return TITLE_CLASS_A;
         if(indRightValue>indLeftValue && MathAbs(priceRightValue-priceLeftValue)<_Point/10)
            return TITLE_CLASS_B;
         if(MathAbs(indRightValue-indLeftValue)<_Point/100 && priceRightValue<priceLeftValue)
            return TITLE_CLASS_C;

         return TITLE_CLASS_H;
        }

      if(indRightValue<indLeftValue && priceRightValue>priceLeftValue)
         return TITLE_CLASS_A;
      if(indRightValue<indLeftValue && MathAbs(priceRightValue-priceLeftValue)<_Point/10)
         return TITLE_CLASS_B;
      if(MathAbs(indRightValue-indLeftValue)<_Point/100 && priceRightValue>priceLeftValue)
         return TITLE_CLASS_C;

      return TITLE_CLASS_H;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| The class definition of divergence, the need for its display and color of display                                                                                                                 |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   bool IsShowDivergence(double indRightValue,double indLeftValue,double priceRightValue,double priceLeftValue,ENUM_EXTREMUM_TYPE extType,string &divClass,color &clr)
     {
      divClass=GetDivergenceType(indRightValue,indLeftValue,priceRightValue,priceLeftValue,extType);
      if((i_showClassA==NO && divClass==TITLE_CLASS_A) || 
         (i_showClassB == NO && divClass == TITLE_CLASS_B) ||
         (i_showClassC == NO && divClass == TITLE_CLASS_C) ||
         (i_showHidden == NO && divClass == TITLE_CLASS_H))
         return false;

      if(divClass==TITLE_CLASS_A)
         clr=(extType==EXTREMUM_TYPE_MIN) ? i_bullsDivAColor : i_bearsDivAColor;

      if(divClass==TITLE_CLASS_B)
         clr=(extType==EXTREMUM_TYPE_MIN) ? i_bullsDivBColor : i_bearsDivBColor;

      if(divClass==TITLE_CLASS_C)
         clr=(extType==EXTREMUM_TYPE_MIN) ? i_bullsDivCColor : i_bearsDivCColor;

      if(divClass==TITLE_CLASS_H)
         clr=(extType==EXTREMUM_TYPE_MIN) ? i_bullsDivHColor : i_bearsDivHColor;

      return true;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Sound and Push-notifications of divergence                                                                                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void SignalOnDivergence(string text)
     {
      static datetime lastSignal=0;
      if(lastSignal>=Time[0])
         return;

      lastSignal=Time[0];

      if(i_isAlert)
         Alert(_Symbol,", ",g_tfName,": ",text);

      if(i_isPush)
         SendNotification(_Symbol+", "+g_tfName+": "+text);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determining the divergence existence and its showing                                                                                                                                              |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void DefineAndShowDivergence(ENUM_EXTREMUM_TYPE extremumType,int rightBarIndex,int leftBarIndex,int priceRightBarIndex,int priceLeftBarIndex)
     {
      double indRightValue= g_indValues[rightBarIndex];
      double indLeftValue = g_indValues[leftBarIndex];
      double priceRightValue= GetMarketPrice(priceRightBarIndex,extremumType);
      double priceLeftValue = GetMarketPrice(priceLeftBarIndex,extremumType);

      // Checking the divergence existence
      if((indRightValue>indLeftValue && priceRightValue>priceLeftValue) || 
         (indRightValue<indLeftValue && priceRightValue<priceLeftValue))
         return;

      // Checking for exit of one of the indicator values beyond the line of divergence
      if(IsDivLineBreak(extremumType,PRICE_TYPE_INDICATOR,leftBarIndex,rightBarIndex))
         return;

      // Checking for exit of one of the market prices beyond the line of divergence
      if(IsDivLineBreak(extremumType,PRICE_TYPE_MARKET,priceLeftBarIndex,priceRightBarIndex))
         return;

      // The class definition of divergence, the need for its display and color of display
      string divClass="";
      color clr=clrNONE;
      if(!IsShowDivergence(indRightValue,indLeftValue,priceRightValue,priceLeftValue,extremumType,divClass,clr))
         return;

      // The divergence is detected - display it
      string divType=(extremumType==EXTREMUM_TYPE_MIN) ? "Bullish " : "Bearish ";
      if(rightBarIndex==2 || priceRightBarIndex==2)
         SignalOnDivergence(divType+divClass);

      ShowTrendLine(g_indSubWindow,Time[rightBarIndex],indRightValue,Time[leftBarIndex],indLeftValue,divType+divClass,clr);
      ShowTrendLine(0,Time[priceRightBarIndex],priceRightValue,Time[priceLeftBarIndex],priceLeftValue,divType+divClass,clr);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Finding the indicator extremum at the specified interval from said bar                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   int GetIndicatorExtremumAtInterval(int barIndex,int total,ENUM_EXTREMUM_TYPE extType)
     {
      int limit = (int)MathMin(barIndex + i_findExtInterval, total);
      for(int i = barIndex; i < limit; i++)
         if(GetBufferExtremum(i,total,g_indValues)==extType)
            return i;

      return -1;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Finding the market extremum at the specified interval from said bar                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   int GetMarketExtremumAtInterval(int barIndex,int total,ENUM_EXTREMUM_TYPE extType)
     {
      int limit = (int)MathMin(barIndex + i_findExtInterval, total);
      for(int i = barIndex; i < limit; i++)
        {
         if(i_marketAppliedPrice==MARKET_APPLIED_PRICE_HIGHLOW)
           {
            if(extType==EXTREMUM_TYPE_MAX)
               if(GetBufferExtremum(i,total,High)==extType)
                  return i;

            if(extType==EXTREMUM_TYPE_MIN)
               if(GetBufferExtremum(i,total,Low)==extType)
                  return i;
           }
         else
         if(GetBufferExtremum(i,total,Close)==extType)
            return i;
        }

      return -1;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Finding the pair of corresponding extremums of base indicator and market price                                                                                                                    |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   bool IsPairExtremums(int barIndex,int total,ENUM_EXTREMUM_TYPE neededExtType,int &indExtBarIndex,int &priceExtBarIndex)
     {
      // Is the indicator extremum exists?
      indExtBarIndex=barIndex;
      priceExtBarIndex=barIndex;
      ENUM_EXTREMUM_TYPE divExtType=GetBufferExtremum(barIndex,total,g_indValues);
      if(divExtType==EXTREMUM_TYPE_NONE || (neededExtType!=EXTREMUM_TYPE_NONE && divExtType!=neededExtType))
        {
         // Is the market extremum?
         divExtType=GetMarketExtremum(barIndex,total,neededExtType);
         if(divExtType==EXTREMUM_TYPE_NONE)
            return false;

         // Market price extremum was found. Finding the extremum of indicator
         indExtBarIndex=GetIndicatorExtremumAtInterval(barIndex,total,divExtType);
         if(indExtBarIndex<0)
            return false;
        }
      // Indicator extremum was found. Finding the extremum of market price
      else
        {
         priceExtBarIndex=GetMarketExtremumAtInterval(barIndex,total,divExtType);
         if(priceExtBarIndex<0)
            return false;
        }

      return true;
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Search the left extremums of price and indicator                                                                                                                                                  |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void SearchLeftReferencePoint(int total,int rightIndExtBarIndex,int rightPriceExtBarIndex,ENUM_EXTREMUM_TYPE divExtType)
     {
      int startBarIndex=(int)MathMax(rightIndExtBarIndex,rightPriceExtBarIndex)+1;
      int lastBar=(int)MathMin(startBarIndex+i_divergenceDepth,total);
      int leftPriceExtBarIndex=-1,leftIndExtBarIndex=-1;

      for(int i=startBarIndex; i<lastBar; i++)
        {

         if(!IsPairExtremums(i,total,divExtType,leftIndExtBarIndex,leftPriceExtBarIndex))
            continue;

         DefineAndShowDivergence(divExtType,rightIndExtBarIndex+1,leftIndExtBarIndex+1,rightPriceExtBarIndex+1,leftPriceExtBarIndex+1);
        }
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| First searched indicator extremum, and behind it (if extremum of indicator was found) - the price extremum                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void ProcessByIndicatorExtremum(int barIndex,int total)
     {
      // Is the indicator extremum exists?
      ENUM_EXTREMUM_TYPE divExtType=GetBufferExtremum(barIndex,total,g_indValues);
      if(divExtType==EXTREMUM_TYPE_NONE)
         return;

      // Indicator extremum was found. Finding the extremum of market price
      int priceExtBarIndex=GetMarketExtremumAtInterval(barIndex,total,divExtType);
      if(priceExtBarIndex<0)
         return;

      SearchLeftReferencePoint(total,barIndex,priceExtBarIndex,divExtType);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| First searched the price extremum, and behind it (if extremum of price was found) - the indicator extremum                                                                                        |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void ProcessByMarketExtremum(int barIndex,int total,ENUM_EXTREMUM_TYPE desiredExtremum)
     {
      // Is the market extremum?
      ENUM_EXTREMUM_TYPE divExtType=GetMarketExtremum(barIndex,total,desiredExtremum);
      if(divExtType==EXTREMUM_TYPE_NONE)
         return;

      // Market price extremum was found. Finding the extremum of indicator
      int indExtBarIndex=GetIndicatorExtremumAtInterval(barIndex,total,divExtType);
      if(indExtBarIndex<0)
         return;

      SearchLeftReferencePoint(total,indExtBarIndex,barIndex,divExtType);
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Process the specified bar                                                                                                                                                                         |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void ProcessBar(int barIndex,int total)
     {
      ProcessByIndicatorExtremum(barIndex,total);
      if(i_marketAppliedPrice==MARKET_APPLIED_PRICE_CLOSE)
         ProcessByMarketExtremum(barIndex,total,EXTREMUM_TYPE_NONE);
      else
        {
         ProcessByMarketExtremum(barIndex,total,EXTREMUM_TYPE_MAX);
         ProcessByMarketExtremum(barIndex,total,EXTREMUM_TYPE_MIN);
        }
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Recalculate the values of William Blau                                                                                                                                                            |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void CalculateDataByWilliamBlau(int limit,int total)
     {
      for(int i=limit; i>0; i--)
         g_tempBuffer[i]=iMA(NULL,0,i_barsPeriod2,0,MODE_EMA,i_indAppliedPrice,i)-iMA(NULL,0,i_barsPeriod1,0,MODE_EMA,i_indAppliedPrice,i);

      for(int i=limit; i>0; i--)
        {
         g_indValues[i]=iMAOnArray(g_tempBuffer,0,i_barsPeriod3,0,MODE_EMA,i);
         if(i+i_divergenceDepth+i_findExtInterval+2>=total)
            continue;

         ProcessBar(i,total);
        }

     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying of indicators values                                                                                                                                                                   |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   void ShowIndicatorData(int limit,int total)
     {
      if(i_indicatorType==WILLIAM_BLAU)
        {
         CalculateDataByWilliamBlau(limit,total);
         return;
        }

      for(int i=limit; i>0; i--)
        {
         g_indValues[i]=GetBaseIndicatorValue(i);
         if(i+i_divergenceDepth+i_findExtInterval+2>=total)
            continue;

         ProcessBar(i,total);
        }
     }
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator iteration function                                                                                                                                                               |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   int OnCalculate(const int rates_total,
                   const int prev_calculated,
                   const datetime &time[],
                   const double &open[],
                   const double &high[],
                   const double &low[],
                   const double &close[],
                   const long &tick_volume[],
                   const long &volume[],
                   const int &spread[])
     {
      if(!g_activate)
         return rates_total;

      if(g_indSubWindow<0)
        {
         g_indSubWindow=WindowFind(g_indName);
         if(g_indSubWindow<0)
            return 0;
        }

      int total;
      int limit=GetRecalcIndex(total,rates_total,prev_calculated);

      ShowIndicatorData(limit,total);
      WindowRedraw();

      return rates_total;
     }
//+------------------------------------------------------------------+

Comments