MACD&STOCH ON CHART DIVERGENCE
Download scriptThis script is a technical analysis tool designed to identify "divergences" on a trading chart. In simple terms, it looks for situations where the price of an asset is moving in one direction, but the momentum indicators (the underlying "strength" behind the move) are moving in the opposite direction. Traders often use these moments to predict potential trend reversals.
The logic functions by simultaneously monitoring two popular technical indicators: the MACD (Moving Average Convergence Divergence) and the Stochastic Oscillator.
Core Logic Workflow
1. Data Collection and Monitoring The script constantly calculates the values for both the MACD and the Stochastic indicators in the background. It processes these values to identify specific structural points on the chart, such as:
- Peaks: The highest points reached by an indicator during a move upward.
- Troughs: The lowest points reached by an indicator during a move downward.
2. Identifying Divergence The tool compares the current price action against the historical data of the indicators to find two specific types of signals:
-
Bullish Divergence (Potential Buy Signal): The script looks for instances where the price reaches a "lower low" (the price is dropping), but the indicator reaches a "higher low" (the momentum is actually becoming stronger). This suggests that despite the falling price, the selling pressure may be exhausting. It also recognizes "Reverse Bullish Divergence," which identifies subtle shifts in these patterns.
-
Bearish Divergence (Potential Sell Signal): The script looks for instances where the price reaches a "higher high" (the price is rising), but the indicator reaches a "lower high" (the momentum is weakening). This suggests that despite the rising price, the buying pressure may be fading. It also recognizes "Reverse Bearish Divergence."
3. Automated Detection and Visualization To make this information easy for a user to see, the script performs the following actions:
- Visual Markers: When it detects a confirmed divergence, it automatically places an arrow on the chart. Blue/Lime arrows typically signify bullish signals, while Red/Orange arrows signify bearish signals.
- Alert System: If enabled by the user, the script can trigger a pop-up alert on the trading platform the moment a new divergence is identified, allowing for real-time monitoring without needing to watch the screen constantly.
Summary of Behavior
Instead of just telling you what the price is doing, this tool analyzes the "health" of the price movement. It highlights moments where the market's price action and its internal momentum are out of sync, providing a visual cue that a trend might be about to change direction.
//+------------------------------------------------------------------+
//| MACD&STOCH ON CHART DIVERGENCE.mq4 |
//| Copyright © 2008, FOREXflash. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FOREXflash"
#property link "http://www.metaquotes.net"
//----
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Black
#property indicator_color4 Black
#property indicator_color5 Lime
#property indicator_color6 Orange
#property indicator_color7 Black
#property indicator_color8 Black
//----
#define arrowsDisplacement 0.0001
//---- input parameters
extern string separator1 = "*** MAConv/Div Settings ***";
extern int fastEMA=12,slowEMA=26,signalSMA=9;
extern string separator1b = "*** Stochastic Settings ***";
extern int Kperiod=5,Dperiod=3,slowing=3;
extern string separator2 = "*** Indicator Settings ***";
extern bool displayAlert = false;
//---- buffers
double bullishDivergence[];
double bearishDivergence[];
double macd[];
double signal[];
double StobullishDivergence[];
double StobearishDivergence[];
double Stochastic[];
double Stosignal[];
//----
static datetime lastAlertTime;
static string indicatorName;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0, DRAW_ARROW,0,2);
SetIndexStyle(1, DRAW_ARROW,0,2);
SetIndexStyle(4, DRAW_ARROW,0,2);
SetIndexStyle(5, DRAW_ARROW,0,2);
SetIndexStyle(6, 12);
//----
SetIndexBuffer(0, bullishDivergence);
SetIndexBuffer(1, bearishDivergence);
SetIndexBuffer(2, macd);
SetIndexBuffer(3, signal);
SetIndexBuffer(4, StobullishDivergence);
SetIndexBuffer(5, StobearishDivergence);
SetIndexBuffer(6, Stochastic);
//----
SetIndexArrow(0, 221);
SetIndexArrow(1, 222);
SetIndexArrow(4, 221);
SetIndexArrow(5, 222);
//----
indicatorName = "ULTRA(" + fastEMA + ", " +
slowEMA + ", " + signalSMA + ")";
SetIndexDrawBegin(3, signalSMA);
IndicatorDigits(Digits + 2);
IndicatorShortName(indicatorName);
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
for(int i = ObjectsTotal() - 1; i >= 0; i--)
{
string label = ObjectName(i);
if(StringSubstr(label, 0, 19) != "ULTRA")
continue;
ObjectDelete(label);
ObjectsDeleteAll(0);
}
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int countedBars = IndicatorCounted();
if(countedBars < 0)
countedBars = 0;
CalculateIndicator(countedBars);
CalculateIndicator2(countedBars);
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateIndicator(int countedBars)
{
for(int i = Bars - countedBars; i >= 0; i--)
{
CalculateMACD(i);
CatchBullishDivergence(i + 1);
CatchBearishDivergence(i + 1);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateIndicator2(int countedBars)
{
for(int i = Bars - countedBars; i >= 0; i--)
{
CalculateStochastic2(i);
CatchBullishDivergence2(i + 1);
CatchBearishDivergence2(i + 1);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateMACD(int i)
{
macd[i] = iMACD(NULL, 0, fastEMA, slowEMA, signalSMA,
PRICE_CLOSE, MODE_MAIN, i);
signal[i] = iMACD(NULL, 0, fastEMA, slowEMA, signalSMA,
PRICE_CLOSE, MODE_SIGNAL, i);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CalculateStochastic2(int i)
{
Stochastic[i] = iStochastic(NULL,0,Kperiod,Dperiod,slowing,MODE_SMA,0,MODE_MAIN,i)-50;
Stosignal[i] = iStochastic(NULL,0,Kperiod,Dperiod,slowing,MODE_SMA,0,MODE_SIGNAL,i)-50;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CatchBullishDivergence(int shift)
{
if(IsIndicatorTrough(shift) == false)
return;
int currentTrough = shift;
int lastTrough = GetIndicatorLastTrough(shift);
//----
if(macd[currentTrough] > macd[lastTrough] &&
Low[currentTrough] < Low[lastTrough])
{
bullishDivergence[currentTrough] = Low[currentTrough] -
arrowsDisplacement;
//----
if(displayAlert == true)
DisplayAlert("Classical bullish divergence on: ",
currentTrough);
}
//----
if(macd[currentTrough] < macd[lastTrough] &&
Low[currentTrough] > Low[lastTrough])
{
bullishDivergence[currentTrough] = Low[currentTrough] -
arrowsDisplacement;
//----
if(displayAlert == true)
DisplayAlert("Reverse bullish divergence on: ",
currentTrough);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CatchBullishDivergence2(int shift)
{
if(IsIndicatorTrough2(shift) == false)
return;
int currentTrough = shift;
int lastTrough = GetIndicatorLastTrough2(shift);
//----
if(Stochastic[currentTrough] > Stochastic[lastTrough] &&
Low[currentTrough] < Low[lastTrough])
{
StobullishDivergence[currentTrough] = Low[currentTrough];
//----
if(displayAlert == true)
DisplayAlert2("Classical bullish divergence on: ",
currentTrough);
}
//----
if(Stochastic[currentTrough] < Stochastic[lastTrough] &&
Low[currentTrough] > Low[lastTrough])
{
StobullishDivergence[currentTrough] = Low[currentTrough];
//----
if(displayAlert == true)
DisplayAlert2("Reverse bullish divergence on: ",
currentTrough);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CatchBearishDivergence(int shift)
{
if(IsIndicatorPeak(shift) == false)
return;
int currentPeak = shift;
int lastPeak = GetIndicatorLastPeak(shift);
//----
if(macd[currentPeak] < macd[lastPeak] &&
High[currentPeak] > High[lastPeak])
{
bearishDivergence[currentPeak] = High[currentPeak] +
arrowsDisplacement;
if(displayAlert == true)
DisplayAlert("Classical bearish divergence on: ",
currentPeak);
}
if(macd[currentPeak] > macd[lastPeak] &&
High[currentPeak] < High[lastPeak])
{
bearishDivergence[currentPeak] = High[currentPeak] +
arrowsDisplacement;
//----
if(displayAlert == true)
DisplayAlert("Reverse bearish divergence on: ",
currentPeak);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CatchBearishDivergence2(int shift)
{
if(IsIndicatorPeak2(shift) == false)
return;
int currentPeak = shift;
int lastPeak = GetIndicatorLastPeak2(shift);
//----
if(Stochastic[currentPeak] < Stochastic[lastPeak] &&
High[currentPeak] > High[lastPeak])
{
StobearishDivergence[currentPeak] = High[currentPeak];
if(displayAlert == true)
DisplayAlert2("Classical bearish divergence on: ",
currentPeak);
}
if(Stochastic[currentPeak] > Stochastic[lastPeak] &&
High[currentPeak] < High[lastPeak])
{
StobearishDivergence[currentPeak] = High[currentPeak];
//----
if(displayAlert == true)
DisplayAlert2("Reverse bearish divergence on: ",
currentPeak);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsIndicatorPeak(int shift)
{
if(macd[shift] >= macd[shift+1] && macd[shift] > macd[shift+2] &&
macd[shift] > macd[shift-1])
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsIndicatorPeak2(int shift)
{
if(Stochastic[shift] >= Stochastic[shift+1] && Stochastic[shift] > Stochastic[shift+2] &&
Stochastic[shift] > Stochastic[shift-1])
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsIndicatorTrough(int shift)
{
if(macd[shift] <= macd[shift+1] && macd[shift] < macd[shift+2] &&
macd[shift] < macd[shift-1])
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool IsIndicatorTrough2(int shift)
{
if(Stochastic[shift] <= Stochastic[shift+1] && Stochastic[shift] < Stochastic[shift+2] &&
Stochastic[shift] < Stochastic[shift-1])
return(true);
else
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
{
for(int i = shift + 5; i < Bars; i++)
{
if(signal[i] >= signal[i+1] && signal[i] >= signal[i+2] &&
signal[i] >= signal[i-1] && signal[i] >= signal[i-2])
{
for(int j = i; j < Bars; j++)
{
if(macd[j] >= macd[j+1] && macd[j] > macd[j+2] &&
macd[j] >= macd[j-1] && macd[j] > macd[j-2])
return(j);
}
}
}
return(-1);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak2(int shift)
{
for(int i = shift + 5; i < Bars; i++)
{
if(Stosignal[i] >= Stosignal[i+1] && Stosignal[i] >= Stosignal[i+2] &&
Stosignal[i] >= Stosignal[i-1] && Stosignal[i] >= Stosignal[i-2])
{
for(int j = i; j < Bars; j++)
{
if(Stochastic[j] >= Stochastic[j+1] && Stochastic[j] > Stochastic[j+2] &&
Stochastic[j] >= Stochastic[j-1] && Stochastic[j] > Stochastic[j-2])
return(j);
}
}
}
return(-1);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
{
for(int i = shift + 5; i < Bars; i++)
{
if(signal[i] <= signal[i+1] && signal[i] <= signal[i+2] &&
signal[i] <= signal[i-1] && signal[i] <= signal[i-2])
{
for (int j = i; j < Bars; j++)
{
if(macd[j] <= macd[j+1] && macd[j] < macd[j+2] &&
macd[j] <= macd[j-1] && macd[j] < macd[j-2])
return(j);
}
}
}
return(-1);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough2(int shift)
{
for(int i = shift + 5; i < Bars; i++)
{
if(Stosignal[i] <= Stosignal[i+1] && Stosignal[i] <= Stosignal[i+2] &&
Stosignal[i] <= Stosignal[i-1] && Stosignal[i] <= Stosignal[i-2])
{
for (int j = i; j < Bars; j++)
{
if(Stochastic[j] <= Stochastic[j+1] && Stochastic[j] < Stochastic[j+2] &&
Stochastic[j] <= Stochastic[j-1] && Stochastic[j] < Stochastic[j-2])
return(j);
}
}
}
return(-1);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void DisplayAlert(string message, int shift)
{
if(shift <= 2 && Time[shift] != lastAlertTime)
{
lastAlertTime = Time[shift];
Alert(message, Symbol(), " , ", Period(), " minutes chart");
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void DisplayAlert2(string message, int shift)
{
if(shift <= 2 && Time[shift] != lastAlertTime)
{
lastAlertTime = Time[shift];
Alert(message, Symbol(), " , ", Period(), " minutes chart");
}
}
//+------------------------------------------------------------------+
Comments