i-Divergency
Download scriptThis 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.
//+------------------------------------------------------------------+
//| 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