This tool is designed to identify "divergences" in financial markets—a phenomenon where the price movement of an asset disagrees with the momentum shown by technical indicators. By spotting these discrepancies, traders can often identify potential trend reversals before they happen.
Core Logic and Functionality
The script functions by comparing two different data streams simultaneously: the actual market price and a momentum indicator of your choice. It systematically scans historical price bars to find specific "peaks" (high points) and "troughs" (low points) to determine if the asset is losing its strength.
1. Customizable Indicators The tool allows you to choose which mathematical model to use for comparison. You can select from four common market oscillators:
- MACD
- RSI
- DMI
- Momentum
2. Peak and Trough Detection Instead of looking at every minor price fluctuation, the logic focuses on significant structural points. It identifies a "peak" or "trough" by analyzing the relationship between three consecutive bars. To ensure these are meaningful, it uses a depth filter; this prevents the tool from reacting to tiny, insignificant ripples and ensures it only triggers on prominent market turns.
3. Identifying Divergence The script constantly compares the behavior of the price peaks/troughs against the indicator's peaks/troughs:
- Bullish Divergence: The logic looks for instances where the price is making "lower lows" (the price is dropping), but the chosen indicator is making "higher lows." This suggests that while the price is falling, the downward momentum is actually weakening, potentially signaling an upcoming upward move.
- Bearish Divergence: Conversely, it looks for instances where the price is making "higher highs," but the indicator is making "lower highs." This suggests that despite the price rising, the upward strength is fading, which may signal a coming downward correction.
4. Visual Feedback Once the logic confirms a divergence, it highlights these areas on your trading chart. It distinguishes between these movements using two separate visual buffers (histograms), allowing you to see exactly where the trend and momentum have decoupled.
Key User Parameters
- Indicator Selection: Choose which momentum tool to track.
- Periods: Adjust how sensitive the indicator is to price changes.
- Price Field: Decide whether the tool should look at the "Close" price or the "High/Low" extremes of the candles.
- Depth: Fine-tune how significant a peak or trough must be before the tool recognizes it as a valid point for divergence analysis.
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------+
//| 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