i-Divergency

Download script
Author: Copyright � Trofimov, 2008
i-Divergency

This script is a technical analysis tool designed to identify "divergences" in financial markets. In simple terms, it looks for situations where the price of an asset (like a currency or stock) is moving in one direction, while the momentum of that asset—measured by a mathematical indicator called the Stochastic Oscillator—is moving in the opposite direction. These moments are often used by traders to spot potential trend reversals.

Core Logic and Functionality

1. Tracking Market Momentum (Stochastic Oscillator) The script constantly monitors a Stochastic Oscillator, which helps determine if an asset is "overbought" or "oversold." It creates a visual representation of this oscillator in a separate window below the main price chart.

2. Identifying Extremes (Peaks and Troughs) Rather than looking at every single price movement, the script focuses on significant turning points. It looks for "peaks" (high points) and "troughs" (low points) in the oscillator data. To ensure these are significant, it uses a sensitivity setting to confirm that a point is actually a peak or trough by comparing it to the surrounding data points.

3. Measuring Vertical Distance (Delta) The script includes a specific logic check to ensure that the peaks and troughs it identifies are sufficiently far apart vertically. By using a "Delta" value, it filters out minor "noise" in the oscillator, focusing only on major shifts in momentum.

4. Detecting Divergence This is the primary purpose of the script. It compares the actual price history with the oscillator's history at specific peak and trough points:

  • Bearish Divergence: If the price is making new highs but the oscillator's peaks are getting lower, it suggests that the upward momentum is weakening despite the higher price. The script identifies this and marks it on the chart.
  • Bullish Divergence: If the price is making new lows but the oscillator's troughs are getting higher, it suggests that the downward momentum is fading despite the lower price.

5. Visual Alerts When the script detects these conflicting signals (the divergence), it provides visual cues on the chart:

  • Arrows: It places specific markers (arrows) to highlight where a potential reversal might be occurring based on the data analysis.
  • Limit Highlights: It also tracks when the oscillator crosses specific "Overbought" (80) or "Oversold" (20) boundaries, providing an additional layer of context for the user.

Summary for the User

Essentially, this tool acts as a "discrepancy detector." It tells you when the market's price action is becoming disconnected from its underlying momentum. By highlighting these moments with arrows and visual buffers, it helps traders find potential "exhaustion" points where a price trend might be about to flip.

Indicators Used
Stochastic oscillator
Miscellaneous
Implements a curve of type %1
11 Views
0 Downloads
0 Favorites
i-Divergency
//+------------------------------------------------------------------+
//|                                                   Divergency.mq4 |
//|                                       Copyright © Trofimov, 2008 |
//+------------------------------------------------------------------+
#property copyright "Copyright © Trofimov, 2008"
#property link      ""
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 DarkSlateBlue
#property indicator_width1 2
#property indicator_color2 Red
#property indicator_width2 2
#property indicator_color3 FireBrick
#property indicator_width3 1
#property indicator_color4 DarkGreen
#property indicator_width4 1

#property indicator_maximum  100
#property indicator_minimum -100

extern double Delta=10; // - ìèíèìàëüíîå ðàññòîÿíèå ìåæäó ìèíèìóìîì è ìàêñèìóìîì
int    ExtremumPoint=3; // - êîëè÷åñòâî òî÷åê ïî êîòîðûì îïðåäåëÿþòñÿ ýêñòðåìóìû. Ìîæåò áûòü ëþáûì íå÷¸òíûì çíà÷åíèåì áîëüøå åäèíèöû (Íàïðèìåð: 3,5,7,9....)
int    Buffer=500;      // - ðàçìåð áóôåðà ìàññèâà Stochastic[]
int    CurBuffer;       // - òåêóùèé (ïîñëåäíèé çàïîëíåííûé) áóôåðíûé èíäåêñ ìàññèâà Stochastic[]
double Stochastic[];
int    UpStochIdx[2];   // - ìàññèâ, ñîäåðæàùèé áóôåðíûå èíäåêñû òð¸õ ïîñëåäíèõ ìàêñèìóìîâ
int    DnStochIdx[2];   // - ìàññèâ, ñîäåðæàùèé áóôåðíûå èíäåêñû òð¸õ ïîñëåäíèõ ìèíèìóìîâ
int    CurrentCandle;
datetime LastTime;

//---- Ìàññèâ äàííûõ èíäèêàòîðà
double StochBuffer[];
double EndLimit[];
double StochUp[],StochDn[];
//+------------------------------------------------------------------+
int init() {
   //if(Buffer==0) Buffer=Bars;
   ArrayResize(Stochastic, Buffer);
   IndicatorBuffers(4);
//---- ïàðàìåòðû ðèñîâàíèÿ (óñòàíîâêà íà÷àëüíîãî áàðà)
   SetIndexDrawBegin(0,Buffer);
//---- 2 ðàñïðåäåëåííûõ áóôåðà èíäèêàòîðà
   SetIndexBuffer(0,StochBuffer);
   SetIndexBuffer(1,EndLimit);
   SetIndexBuffer(2,StochUp);
   SetIndexBuffer(3,StochDn);
//---- èìÿ èíäèêàòîðà è ïîäñêàçêè äëÿ ëèíèé
   IndicatorShortName("Divergency("+DoubleToStr(Delta,1)+")");
   SetIndexLabel(0,"Divergency");
   SetIndexLabel(1,"Limit");
   SetIndexLabel(2,"Top");
   SetIndexLabel(3,"Low");
//--- ñòèëü îòðèñîâêè
   SetIndexStyle(0, DRAW_HISTOGRAM);
   SetIndexStyle(1, DRAW_HISTOGRAM);
   SetIndexStyle(2, DRAW_ARROW);
   SetIndexStyle(3, DRAW_ARROW);
   SetIndexArrow(2, 108);
   SetIndexArrow(3, 108);
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   static int OldUpStochIdx,OldDnStochIdx;
   int limit;
   // Ïðîïóùåííûå áàðû
   int counted_bars=IndicatorCounted();
//---- îáõîäèì âîçìîæíûå îøèáêè
   if(counted_bars<0) return(-1);
//---- íîâûå áàðû íå ïîÿâèëèñü è ïîýòîìó íè÷åãî ðèñîâàòü íå íóæíî
   limit=Bars-counted_bars-1;
//---- îñíîâíîé öèêë
   for(int i=limit; i>=0; i--) {
      CurrentCandle=i+1;//-ýòî ïîëíîñòüþ ñôîðìèðîâàâøàÿñÿ ñâå÷à
      if(LastTime!=iTime(NULL,0,CurrentCandle)) {
         AddStochastic();
         LastTime=iTime(NULL,0,CurrentCandle);
         //Èíäèêàòîð ïåðåñå÷åíèÿ ãðàíèö 20/80
         //EndLimit[i]=0;
         if(OldUpStochIdx!=UpStochIdx[0]) {
            if(Stochastic[UpStochIdx[0]]>80) {
               EndLimit[i]=-50;
               OldUpStochIdx=UpStochIdx[0];
            }
         }
         if(OldDnStochIdx!=DnStochIdx[0]) {
            if(Stochastic[DnStochIdx[0]]<20) {
               EndLimit[i]=50;
               OldDnStochIdx=DnStochIdx[0];
            }
         }
         //Èíäèêàòîð äèâåðãåíöèè
         //StochBuffer[i]=0;
         if(VectorStochastic(true)<0 && VectorPrice(true)>0) {
            if(GetIndexNormal(UpStochIdx[0])<GetIndexNormal(DnStochIdx[0])) {//åñëè ïîñëåäíèé ìèíèìóì ñòàðåå ïîñëåäíåãî ìàêñèìóìà
               StochBuffer[i]=-100;
            }
         }
         if(VectorStochastic(false)>0 && VectorPrice(false)<0) {
            if(GetIndexNormal(UpStochIdx[0])>GetIndexNormal(DnStochIdx[0])) {//åñëè ïîñëåäíèé ìàêñèìóì ñòàðåå ïîñëåäíåãî ìèíèìóìà
               StochBuffer[i]=100;
            }
         }
         //Print("===== ",TimeToStr(LastTime)," =====");
      }
   }
   return(0);
  }
//+------------------------------------------------------------------+
int AddStochastic() {
   //Äîáàâëÿåò íîâîå çíà÷åíèå ñòîõàñòèêà â ìàññèâ
   if(CurBuffer==0) 
      CurBuffer=Buffer-1;
   else
      CurBuffer--;
   Stochastic[CurBuffer]=iStochastic(NULL,0,5,3,3,MODE_EMA,0,MODE_MAIN,CurrentCandle);

   //Ïðîâåðêà íà âîçíèêíîâåíèå ýêñòðåìóìà
   int countUp, countDn;
   int idxTop=(ExtremumPoint-1)/2; // - íîðìàëüíûé èíäåêñ âåðøèíû
   for (int i = idxTop-1; i >= 0 ; i--) { //Öûêë íîðìàëüíîãî èíäåêñà
      if(Stochastic[GetIndexBuffer(i)]<Stochastic[GetIndexBuffer(i+1)] &&
      Stochastic[GetIndexBuffer(idxTop+(idxTop-i))]<Stochastic[GetIndexBuffer(idxTop+(idxTop-i)-1)]) {
         countUp++;
      }
      if(Stochastic[GetIndexBuffer(i)]>Stochastic[GetIndexBuffer(i+1)] &&
      Stochastic[GetIndexBuffer(idxTop+(idxTop-i))]>Stochastic[GetIndexBuffer(idxTop+(idxTop-i)-1)]) {
         countDn++;
      }
   } //Next i
   if(countUp==idxTop) { //âåðøèíà îêàçàëàñü ìàêñèìóìîì
      if(GetIndexNormal(DnStochIdx[0])<GetIndexNormal(UpStochIdx[0])) { //Åñëè ïðåäûäóùèì ñòîèò ìèíèìóì
         if(Stochastic[GetIndexBuffer(idxTop)]-Stochastic[DnStochIdx[0]]>Delta){ 
         //Åñëè ìåæäó ïðåäûäóùèì ìèíèìóìîì è ïðåäïîëîæèòåëüíûì ìàêñèìóìîì ðàñòîÿíèå ïî âåðòèêàëè áîëüøå Delta
            UpStochIdx[2]=UpStochIdx[1];
            UpStochIdx[1]=UpStochIdx[0];
            UpStochIdx[0]=GetIndexBuffer(idxTop);
            StochUp[CurrentCandle-1]=Stochastic[UpStochIdx[0]];
         }
      } else { //Åñëè ïðåäûäóùèì ñòîèò ìàêñèìóì
         if(Stochastic[UpStochIdx[0]]<Stochastic[GetIndexBuffer(idxTop)]) { //åñëè ïðåäûäóùèé ìàêñèìóì áûë ìåíüøå íàñòîÿùåãî
            StochUp[CurrentCandle-2+GetIndexNormal(UpStochIdx[0])]=EMPTY_VALUE;
            //StochUp[CurrentCandle-1+idxTop]=Stochastic[GetIndexBuffer(idxTop)];
            StochUp[CurrentCandle-1]=Stochastic[GetIndexBuffer(idxTop)];
            UpStochIdx[0]=GetIndexBuffer(idxTop);
         }
      }
   } else if(countDn==idxTop) { //âåðøèíà îêàçàëàñü ìèíèìóìîì
      if(GetIndexNormal(UpStochIdx[0])<GetIndexNormal(DnStochIdx[0])) { //Åñëè ïðåäûäóùèì ñòîèò ìàêñèìóì
         if(Stochastic[UpStochIdx[0]]-Stochastic[GetIndexBuffer(idxTop)]>Delta){ 
         //Åñëè ìåæäó ïðåäûäóùèì ìàêñèñóìîì è ïðåäïîëîæèòåëüíûì ìèíèìóìîì ðàñòîÿíèå ïî âåðòèêàëè áîëüøå Delta
            DnStochIdx[2]=DnStochIdx[1];
            DnStochIdx[1]=DnStochIdx[0];
            DnStochIdx[0]=GetIndexBuffer(idxTop);
            StochDn[CurrentCandle-1]=Stochastic[DnStochIdx[0]];
         }
      } else { //Åñëè ïðåäûäóùèì ñòîèò ìèíèìóì
         if(Stochastic[DnStochIdx[0]]>Stochastic[GetIndexBuffer(idxTop)]) { //åñëè ïðåäûäóùèé ìèíèìóì áûë áîëüøå íàñòîÿùåãî
            StochDn[CurrentCandle-2+GetIndexNormal(DnStochIdx[0])]=EMPTY_VALUE;
            //StochDn[CurrentCandle-1+idxTop]=Stochastic[GetIndexBuffer(idxTop)];
            StochDn[CurrentCandle-1]=Stochastic[GetIndexBuffer(idxTop)];
            DnStochIdx[0]=GetIndexBuffer(idxTop);
         }
      }
   }
   return(0);
}
//+------------------------------------------------------------------+
int GetIndexBuffer(int Idx) {
   //âîçâðàùàåò áóôåðíûé èíäåêñ ìàññèâà, ãäå Idx - íîðìàëüíûé èíäåêñ
   if(Idx>Buffer-1) {
      Print("Íåäîïóñòèìîå çíà÷åíèå èíäåêñà äëÿ ìàññèâà");
      return(-1);
   }
   int retIndex=CurBuffer+Idx;
   if(retIndex>Buffer-1) retIndex=retIndex-Buffer;
   return(retIndex);
}
//+------------------------------------------------------------------+
int GetIndexNormal(int IdxBuf) {
   //âîçâðàùàåò íîðìàëüíûé èíäåêñ, ãäå IdxBuf - áóôåðíûé èíäåêñ ìàññèâà
   if(IdxBuf>Buffer-1) {
      Print("Íåäîïóñòèìîå çíà÷åíèå èíäåêñà äëÿ ìàññèâà");
      return(-1);
   }
   int retIndex=IdxBuf-CurBuffer;
   if(retIndex<0) retIndex=retIndex+Buffer;
   return(retIndex);
}
//+------------------------------------------------------------------+
int VectorStochastic(bool MaxMin) {
   //âîçâðàùàåò íàïðàâëåíèå òðåíäîâîé ëèíèè, ïðîâåä¸ííîé ÷åðåç âåðøèíû ñòîõàñòèêà:
   //1 - ââåðõ, -1 - âíèç, 0 - ãîðèçîíòàëüíî
   //MaxMin - òèïû àíàëèçèðóåìûõ âåðøèí: true - ìàêñèìóìû, false - ìèíèìóìû 
   if(MaxMin) {
      //Print("Stochastic[UpStochIdx[0]]="+Stochastic[UpStochIdx[0]],", Stochastic[UpStochIdx[1]]="+Stochastic[UpStochIdx[1]]);
      if(Stochastic[UpStochIdx[0]]>Stochastic[UpStochIdx[1]]) {
         //Print("Stochastic[0]="+Stochastic[UpStochIdx[0]],", Stochastic[1]="+Stochastic[UpStochIdx[1]],", return 1");
         return(1);
      } else if(Stochastic[UpStochIdx[0]]<Stochastic[UpStochIdx[1]]) {
         //Print("Stochastic[0]="+Stochastic[UpStochIdx[0]],", Stochastic[1]="+Stochastic[UpStochIdx[1]],", return -1");
         return(-1);
      }
   } else {
      //Print("Stochastic[DnStochIdx[0]]="+Stochastic[DnStochIdx[0]],", Stochastic[DnStochIdx[1]]="+Stochastic[DnStochIdx[1]]);
      if(Stochastic[DnStochIdx[0]]>Stochastic[DnStochIdx[1]]) {
         //Print("Stochastic[0]="+Stochastic[DnStochIdx[0]],", Stochastic[1]="+Stochastic[DnStochIdx[1]],", return 1");
         return(1);
      } else if(Stochastic[DnStochIdx[0]]<Stochastic[DnStochIdx[1]]) {
         //Print("Stochastic[0]="+Stochastic[DnStochIdx[0]],", Stochastic[1]="+Stochastic[DnStochIdx[1]],", return -1");
         return(-1);
      }
   }
   return(0);
}
//+------------------------------------------------------------------+
int VectorPrice(bool MaxMin) {
   //âîçâðàùàåò íàïðàâëåíèå òðåíäîâîé ëèíèè, ïðîâåä¸ííîé ÷åðåç ïèêè ñâå÷åé òåêóùåãî ãðàôèêà:
   //1 - ââåðõ, -1 - âíèç, 0 - ãîðèçîíòàëüíî
   //MaxMin - òèïû àíàëèçèðóåìûõ ïèêîâ: true - High, false - Low 
   int Extremum0,Extremum1;
   if(MaxMin) {
      Extremum0=iHighest(NULL,0,MODE_HIGH,GetIndexNormal(DnStochIdx[0]),CurrentCandle);
      Extremum1=iHighest(NULL,0,MODE_HIGH,GetIndexNormal(DnStochIdx[1])-GetIndexNormal(DnStochIdx[0]),GetIndexNormal(DnStochIdx[0])+CurrentCandle);
      //Print("High[Extremum0]=",High[Extremum0],", High[Extremum1]=",High[Extremum1]);
      if(High[Extremum0]>High[Extremum1]) {
         //Print("High[0]=",High[Extremum0],", High[1]=",High[Extremum1],", return 1");
         return(1);
      } else {
         //Print("High[0]=",High[Extremum0],", High[1]=",High[Extremum1],", return -1");
         return(-1);
      }
   } else {
      Extremum0=iLowest(NULL,0,MODE_LOW,GetIndexNormal(UpStochIdx[0]),CurrentCandle);
      Extremum1=iLowest(NULL,0,MODE_LOW,GetIndexNormal(UpStochIdx[1])-GetIndexNormal(UpStochIdx[0]),GetIndexNormal(UpStochIdx[0])+CurrentCandle);
      //Print("Low[Extremum0]=",Low[Extremum0],", Low[Extremum1]=",Low[Extremum1]);
      if(Low[Extremum0]>Low[Extremum1]) {
         //Print("Low[0]=",Low[Extremum0],", Low[1]=",Low[Extremum1],", return 1");
         return(1);
      } else {
         //Print("Low[0]=",Low[Extremum0],", Low[1]=",Low[Extremum1],", return -1");
         return(-1);
      }
   }
   return(0);
}
//+------------------------------------------------------------------+

Comments