Divergence_v3
Download scriptThis technical tool is designed to identify "divergences" in financial markets, which occur when the price action of an asset moves in one direction while a secondary momentum indicator moves in the opposite direction. Identifying these discrepancies can help traders spot potential trend reversals before they happen.
Core Functionality
The script analyzes the relationship between actual market prices (such as the High, Low, or Closing prices) and various technical oscillators. By comparing these two data sets simultaneously, it seeks to find moments where the "strength" of the move no longer matches the price movement.
How the Logic Works
To provide a comprehensive view of the market, the script operates through the following steps:
- Indicator Selection: The tool allows you to choose between several popular momentum oscillators—specifically MACD, RSI, DMI, or Momentum—to serve as the baseline for comparison against price.
- Peak and Trough Detection: The script automatically scans historical data to find "peaks" (high points) and "troughs" (low points) in both the price chart and the chosen momentum indicator. It uses a specific depth setting to ensure that only significant turning points are captured, filtering out minor market noise.
- Divergence Identification:
- Bullish Divergence: The script looks for instances where the price makes a lower low, but the momentum indicator makes a higher low. This suggests that selling pressure is weakening despite the falling price.
- Bearish Divergence: Conversely, it looks for instances where the price makes a higher high, but the momentum indicator makes a lower high. This suggests that buying pressure is exhausting even though the price is rising.
- Visual Signaling: Once a divergence is confirmed based on these mathematical conditions, the tool plots specific visual markers (histograms) on your chart. These signals are designed to highlight areas where the market may be losing steam, potentially indicating an upcoming change in direction.
User Customization
The logic can be adjusted to suit different trading styles through several parameters:
- Price Field: You can choose whether the script monitors the Highs, Lows, or Closing prices.
- Period Settings: You can adjust the sensitivity of the underlying momentum indicators.
- Depth Minimum: This allows you to control how "sharp" a peak or trough must be for the tool to recognize it as a valid turning point.
- Signal Shift: This provides an option to offset the visual signals to align with specific historical data points.
//+------------------------------------------------------------------+
//| Divergence.mq4 |
//| Copyright © 2005, Pavel Kulko |
//| polk@alba.dp.ua |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, Pavel Kulko"
#property link "polk@alba.dp.ua"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_minimum -1
#property indicator_maximum 1
#property indicator_color1 Aqua
#property indicator_color2 Red
//----
extern int ind=1; //MACD=1, RSI=2, DMI=3, Mom=4
extern int pds=10; //indicator periods
extern int f=1; //price field: Close=1, High/Low=2
extern double Ch=0; //peak/trough depth minimum (0-1)
extern int shift=0; //shift signals back to match divergences
extern int MaxBars=1000;
//----
double DivUpBuffer[],DivDnBuffer[];
double R1[],R2[],y[],xd[],xu[];
double fCh;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init() {
IndicatorBuffers(7);
SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID,2);
SetIndexBuffer(0,DivUpBuffer);
SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,2);
SetIndexBuffer(1,DivDnBuffer);
SetIndexBuffer(2,R1);
SetIndexBuffer(3,R2);
SetIndexBuffer(4,y);
SetIndexBuffer(5,xd);
SetIndexBuffer(6,xu);
return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int CNmb1,CNmb2,CNmb3,CNmb4;
double Pkx1,Pkx2,Trx1,Trx2,Pky1,Pky2,Try1,Try2;
bool Trx,Pkx,Try,Pky;
fCh=Ch/100.0;
int counted_bars=IndicatorCounted();
int limit=Bars-counted_bars-1;
if(limit>MaxBars) limit=MaxBars;
for(int i=limit; i>=0; i--)
{
DivUpBuffer[i]=Low[i];
DivDnBuffer[i]=Low[i];
switch(ind)
{
case 1: y[i]=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,i); break;
case 2: y[i]=iRSI(NULL,0,pds,PRICE_CLOSE,i); break;
case 3: y[i]=iADX(NULL,0,pds,PRICE_CLOSE,MODE_MAIN,i); break;
default : y[i]=iMomentum(NULL,0,pds,PRICE_CLOSE,i); break;
}
if(f==1) xu[i]=Close[i];
else xu[i]=High[i];
if(f==1) xd[i]=Close[i];
else xd[i]=Low[i];
}
for(i=limit; i>=0; i--)
{
CNmb1=0; CNmb2=0; CNmb3=0; CNmb4=0;
for(int j=i; j<MaxBars; j++)
{
Pkx=(xu[j] < xu[j-1]) && (xu[j-1] > xu[j-2]) && (xu[j-1]>=(xu[j]+xu[j-2])/2.0*(1.0+fCh));
if(Pkx) CNmb1++;
if(Pkx && CNmb1==1) Pkx1=xu[j-1];
if(Pkx && CNmb1==2) Pkx2=xu[j-1];
Trx=(xd[j] > xd[j-1]) && (xd[j-1] < xd[j-2]) && (xd[j-1]<=(xd[j]+xd[j-2])/2.0*(1.0-fCh));
if(Trx) CNmb2++;
if(Trx && CNmb2==1) Trx1=xd[j-1];
if(Trx && CNmb2==2) Trx2=xd[j-1];
Pky=(y[j] < y[j-1]) && (y[j-1] > y[j-2]) && (y[j-1]>=(y[j]+y[j-2])/2.0*(1.0+fCh));
if(Pky) CNmb3++;
if(Pky && CNmb3==1) Pky1=y[j-1];
if(Pky && CNmb3==2) Pky2=y[j-1];
Try=(y[j] > y[j-1]) && (y[j-1] < y[j-2]) && (y[j-1]<=(y[j]+y[j-2])/2.0*(1.0-fCh));
if(Try) CNmb4++;
if(Try && CNmb4==1) Try1=y[j-1];
if(Try && CNmb4==2) Try2=y[j-1];
if(CNmb1>=2 && CNmb2>=2 && CNmb3>=2 && CNmb4>=2) break;
}
Pkx=(xu[i] < xu[i-1]) && (xu[i-1] > xu[i-2]) && (xu[i-1]>=(xu[i]+xu[i-2])/2.0*(1.0+fCh));
Trx=(xd[i] > xd[i-1]) && (xd[i-1] < xd[i-2]) && (xd[i-1]<=(xd[i]+xd[i-2])/2.0*(1.0-fCh));
Pky=(y[i] < y[i-1]) && (y[i-1] > y[i-2]) && (y[i-1]>=(y[i]+y[i-2])/2.0*(1.0+fCh));
Try=(y[i] > y[i-1]) && (y[i-1] < y[i-2]) && (y[i-1]<=(y[i]+y[i-2])/2.0*(1.0-fCh));
R1[i]=0;
if(Trx && Try && Trx1<Trx2 && Try1>Try2) R1[i]=1;
R2[i]=0;
if(Pkx && Pky && Pkx1>Pkx2 && Pky1<Pky2) R2[i]=1;
if(R1[i+shift] - R2[i+shift] > 0)
{
DivUpBuffer[i+shift]=High[i];
DivDnBuffer[i+shift]=Low[i];
}
if(R1[i+shift] - R2[i+shift] < 0)
{
DivDnBuffer[i]=High[i];
DivUpBuffer[i]=Low[i];
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments