Stochastic_Divergence

Download script
Author: Copyright � 2007, FX5
Stochastic_Divergence

This script is designed as a technical analysis tool for the MetaTrader trading platform. Its primary purpose is to identify "divergences"—situations where the price action of an asset moves in one direction, while a specific momentum indicator (in this case, the Stochastic oscillator) moves in the opposite direction. These moments are often used by traders to spot potential trend reversals.

Core Functionality

The script automatically monitors two primary data streams:

  1. Price Action: The actual high and low prices of the market.
  2. Momentum Data: Specifically, it calculates and tracks a Stochastic indicator.

By comparing these two data streams, the tool identifies four specific types of signals:

1. Bullish Divergence (Potential Price Increase)

The script looks for "troughs" (low points) in the momentum data and compares them to the actual lows on the price chart.

  • Classical Bullish Divergence: Triggered when the market price makes a new low, but the momentum indicator shows a higher low. This suggests that despite the falling price, the selling pressure may be weakening.
  • Hidden Bullish Divergence: Triggered when the momentum indicator makes a new low, but the price stays relatively high or moves up. This is often interpreted as a sign of trend continuation.

2. Bearish Divergence (Potential Price Decrease)

The script looks for "peaks" (high points) in the momentum data and compares them to the actual highs on the price chart.

  • Classical Bearish Divergence: Triggered when the market price makes a new high, but the momentum indicator shows a lower peak. This suggests that the buying momentum is exhausting even as prices rise.
  • Hidden Bearish Divergence: Triggered when the momentum indicator makes a new peak, but the price stays relatively low or moves down. This can indicate a continuing downward trend.

Visual and Interactive Features

To make these findings easy for a trader to see at a glance, the script includes several visual enhancements:

  • On-Chart Markers: It places specific arrows on the chart to signal exactly where a divergence has been detected.
  • Trend Lines: The script automatically draws connecting lines between the points of interest. It can draw these lines directly on the price chart (to show price relationship) and also within the indicator window (to show momentum relationship).
  • Customizable Visuals: Users can choose to toggle these trend lines on or off and select whether they appear as solid or dotted lines depending on the type of divergence detected.
  • Real-Time Alerts: The tool features an integrated notification system. When a new divergence is identified, it triggers a pop-up alert on the trading platform to notify the user immediately.

Summary for the User

Essentially, this script acts as an automated "scout." Instead of a trader having to manually compare every peak and valley between two different windows on their screen, this tool does that math instantly. It highlights the specific moments where the price and momentum are "out of sync," providing visual cues and alerts to help traders spot potential turning points in the market.

Indicators Used
Stochastic oscillatorMACD Histogram
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
9 Views
2 Downloads
0 Favorites
Stochastic_Divergence
//+------------------------------------------------------------------+
//|                     edited from     FX5_MACD_Divergence_V1.1.mq4 |
//|                                                              FX5 |
//|Editor: byens (byens@web.de)                        hazem@uk2.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, FX5"
#property link      "hazem@uk2.net"
//----
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_color3 Blue
#property indicator_color4 Red
#property indicator_level1 80
#property indicator_level2 20
#property indicator_maximum	100
#property indicator_minimum	0
//----
#define arrowsDisplacement 0.0001
//---- input parameters
extern string separator1 = "*** Stochastic Settings ***";
/*extern int    fastEMA = 12;
extern int    slowEMA = 26;
extern int    signalSMA = 9;*/
extern int KPeriod=8;
extern int DPeriod=3;
extern int Slowing=3;
extern string separator2 = "*** Indicator Settings ***";
extern bool   drawIndicatorTrendLines = true;
extern bool   drawPriceTrendLines = true;
extern bool   displayAlert = true;
//---- buffers
double bullishDivergence[];
double bearishDivergence[];
double macd[];
double signal[];
//----
static datetime lastAlertTime;
static string   indicatorName;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexStyle(2, DRAW_LINE);
   SetIndexStyle(3, DRAW_LINE);
//----   
   SetIndexBuffer(0, bullishDivergence);
   SetIndexBuffer(1, bearishDivergence);
   SetIndexBuffer(2, macd);
   SetIndexBuffer(3, signal);   
//----   
   SetIndexArrow(0, 233);
   SetIndexArrow(1, 234);
//----
   indicatorName = "Stochastic_Divergence(" + KPeriod + ", " + 
                                 DPeriod + ", " + Slowing + ")";
   SetIndexDrawBegin(3, Slowing);//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, 25) != "Stochastic_DivergenceLine")
           continue;
       ObjectDelete(label);   
     }
//     ObjectsDeleteAll();
/*     int periodecurrent= Period();
     if (Period()!=periodecurrent){
     ObjectsDeleteAll();
     periodecurrent=Period();
     }*/
//     ObjectDelete(label);
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int countedBars = IndicatorCounted();
   if(countedBars < 0)
       countedBars = 0;
   CalculateIndicator(countedBars);
//---- 
   return(0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateIndicator(int countedBars)
  {
   for(int i = Bars - countedBars; i >= 0; i--)
     {
       CalculateMACD(i);
       CatchBullishDivergence(i + 2);
       CatchBearishDivergence(i + 2);
     }              
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateMACD(int i)
  {
   macd[i] = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing, MODE_SMA, 0, MODE_MAIN, i);
               /*iMACD(NULL, 0, fastEMA, slowEMA, signalSMA, 
                   PRICE_CLOSE, MODE_MAIN, i);*/
   
   signal[i] = iStochastic(NULL, 0, KPeriod, DPeriod, Slowing, MODE_SMA, 0, MODE_SIGNAL, i);
               /*iMACD(NULL, 0, fastEMA, slowEMA, signalSMA, 
                     PRICE_CLOSE, MODE_SIGNAL, i);         */
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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] = macd[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                             Low[lastTrough], Green, STYLE_SOLID);
       //----
       if(drawIndicatorTrendLines == true)
          DrawIndicatorTrendLine(Time[currentTrough], 
                                 Time[lastTrough], 
                                 macd[currentTrough],
                                 macd[lastTrough], 
                                 Green, STYLE_SOLID);
       //----
       if(displayAlert == true)
          DisplayAlert("Classical bullish divergence on: ", 
                        currentTrough);  
                        
       //----
     }
//----   
   if(macd[currentTrough] <= macd[lastTrough] && 
      Low[currentTrough] >= Low[lastTrough])
     { //bullishDivergence
       bullishDivergence[currentTrough] = macd[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                              Low[lastTrough], Green, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)                            
           DrawIndicatorTrendLine(Time[currentTrough], 
                                  Time[lastTrough], 
                                  macd[currentTrough],
                                  macd[lastTrough], 
                                  Green, STYLE_DOT);
       //----
       if(displayAlert == true)
           DisplayAlert("Hidden 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] = macd[currentPeak] + 
                                        arrowsDisplacement;
      
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], DarkViolet, STYLE_SOLID);
                            
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  macd[currentPeak],
                                  macd[lastPeak], DarkViolet, STYLE_SOLID);

       if(displayAlert == true)
           DisplayAlert("Classical bearish divergence on: ", 
                        currentPeak);  
       
     }
   if(macd[currentPeak] >= macd[lastPeak] && 
      High[currentPeak] <= High[lastPeak])
     {//bearishDivergence
       bearishDivergence[currentPeak] = macd[currentPeak] + 
                                        arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], DarkViolet, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  macd[currentPeak],
                                  macd[lastPeak], DarkViolet, STYLE_DOT);
       //----
       if(displayAlert == true)//bearish??
           DisplayAlert("Hidden 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 IsIndicatorTrough(int shift)
  {
   if(macd[shift] <= macd[shift+1] && macd[shift] < macd[shift+2] && 
      macd[shift] < macd[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 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);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DisplayAlert(string message, int shift)
  {
   if(shift <= 2 && Time[shift] != lastAlertTime)
     {
       lastAlertTime = Time[shift];
       Alert(message, Symbol(), " , ", Period(), " minutes chart");
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawPriceTrendLine(datetime x1, datetime x2, double y1, 
                        double y2, color lineColor, double style)
  {
   string label = "Stochastic_DivergenceLine_v1.0# " + DoubleToStr(x1, 0);
   ObjectDelete(label);
   ObjectCreate(label, OBJ_TREND, 0, x1, y1, x2, y2, 0, 0);
   ObjectSet(label, OBJPROP_RAY, 0);
   ObjectSet(label, OBJPROP_COLOR, lineColor);
   ObjectSet(label, OBJPROP_STYLE, style);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void DrawIndicatorTrendLine(datetime x1, datetime x2, double y1, 
                            double y2, color lineColor, double style)
  {
   int indicatorWindow = WindowFind(indicatorName);
   if(indicatorWindow < 0)
       return;
   string label = "Stochastic_DivergenceLine_v1.0$# " + DoubleToStr(x1, 0);
   ObjectDelete(label);
   ObjectCreate(label, OBJ_TREND, indicatorWindow, x1, y1, x2, y2, 
                0, 0);
   ObjectSet(label, OBJPROP_RAY, 0);
   ObjectSet(label, OBJPROP_COLOR, lineColor);
   ObjectSet(label, OBJPROP_STYLE, style);
  }
//+------------------------------------------------------------------+



Comments