FX5_Divergence_V2.0

Download script
Author: Copyright � 2007, FX5
FX5_Divergence_V2.0

This script is a specialized trading tool designed to identify "divergences"—a situation where the price action of an asset moves in one direction while a technical indicator moves in the opposite direction. In trading, these discrepancies often signal that the current trend is losing steam and a reversal might be coming.

Core Logic Overview

The script operates by analyzing two main components: the actual price movements (Highs and Lows) and a momentum indicator called the OSMA (On Balance Volume Average).

1. The Momentum Foundation (OSMA)

The tool first calculates the OSMA, which helps determine the strength of price movement over time. It separates this data into "Up" (positive) and "Down" (negative) values. By looking at these values, the script can see whether the momentum is pushing upward or downward independently of the price itself.

2. Identifying Key Turning Points

To find meaningful divergences, the script doesn't just look at every random candle; it specifically searches for "Peaks" and "Troughs":

  • Peaks: High points in the indicator where the momentum has reached a summit before dropping.
  • Troughs: Low points in the indicator where the momentum has hit a bottom before rising.

3. Detecting Divergence Types

The script automatically compares the current peak/trough with the previous one to find two types of signals:

  • Bullish Divergence (Potential Buy Signal):

    • Classical: The price makes a "Lower Low" (price is dropping), but the indicator makes a "Higher Low." This suggests that even though the price is falling, the selling pressure is weakening.
    • Reverse: The price makes a "Higher Low," but the indicator makes a "Lower Low." This suggests the upward movement lacks strength.
  • Bearish Divergence (Potential Sell Signal):

    • Classical: The price makes a "Higher High" (price is rising), but the indicator makes a "Lower High." This suggests that despite the higher price, the buying momentum is fading.
    • Reverse: The price makes a "Lower High," but the indicator makes a "Higher High." This suggests the downward move lacks conviction.

4. Visual and Audible Feedback

When the script detects these specific mathematical discrepancies, it provides immediate feedback to the user:

  • Visual Markers: It places arrows on the chart to highlight exactly where the divergence occurred.
  • Trend Lines: It automatically draws lines connecting the price points and the indicator points, allowing you to see the "gap" between price and momentum visually.
  • Alerts: If enabled, the script will trigger a pop-up notification on your screen to warn you of a new divergence in real-time.

Summary for the User

Essentially, this tool acts as an early warning system. While the price might look like it is continuing in one direction, this script looks "under the hood" at the momentum. When it finds a mismatch between what the price is doing and what the momentum is doing, it highlights those areas to help you spot potential market reversals before they happen.

Indicators Used
Moving Average of Oscillator
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
21 Views
1 Downloads
0 Favorites
FX5_Divergence_V2.0
//+------------------------------------------------------------------+
//|                                          FX5_Divergence_V2.0.mq4 |
//|                                                              FX5 |
//|                                                    hazem@uk2.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, FX5"
#property link      "hazem@uk2.net"
//----
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 LimeGreen
#property indicator_color2 FireBrick
#property indicator_color3 Green
#property indicator_color4 Red
//---- input parameters
extern string separator1 = "*** OSMA Settings ***";
extern int    fastEMA = 12;
extern int    slowEMA = 26;
extern int    signal = 9;
extern string separator2 = "*** Indicator Settings ***";
extern double positiveSensitivity = 0.0001;
extern double negativeSensitivity = -0.0001;
extern double historyBarsCount = 0;
extern bool   drawDivergenceLines = true;
extern bool   displayAlert = true;
//---- buffers
double upOsMA[];
double downOsMA[];
double bullishDivergence[];
double bearishDivergence[];
double OsMA[];
//----
static datetime lastAlertTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 2);
   SetIndexStyle(1, DRAW_HISTOGRAM, STYLE_SOLID, 2);
   SetIndexStyle(2, DRAW_ARROW);
   SetIndexStyle(3, DRAW_ARROW);
   SetIndexStyle(4, DRAW_NONE);
//----   
   SetIndexBuffer(0, upOsMA);
   SetIndexBuffer(1, downOsMA);
   SetIndexBuffer(2, bullishDivergence);
   SetIndexBuffer(3, bearishDivergence);
   SetIndexBuffer(4, OsMA);
//----   
   SetIndexArrow(2, 233);
   SetIndexArrow(3, 234);
//----
   IndicatorDigits(Digits + 2);
   IndicatorShortName("FX5_Divergence_v2.0(" + fastEMA + "," + 
                      slowEMA + "," + signal + ")");
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   for(int i = ObjectsTotal() - 1; i >= 0; i--)
     {
       string label = ObjectName(i);
       if(StringSubstr(label, 0, 14) != "DivergenceLine")
           continue;
       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--)
     {
      CalculateOsMA(i);
      CatchBullishDivergence(i + 2);
      CatchBearishDivergence(i + 2);
     }              
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CalculateOsMA(int i)
  {
   OsMA[i] = iOsMA(NULL, 0, fastEMA, slowEMA, signal, PRICE_CLOSE, i);
   if(OsMA[i] > 0)
     {
      upOsMA[i] = OsMA[i];
      downOsMA[i] = 0;
     }
   else 
       if(OsMA[i] < 0)
         {
           downOsMA[i] = OsMA[i];
           upOsMA[i] = 0;   
         }
   else
     {
       upOsMA[i] = 0;
       downOsMA[i] = 0;   
     }         
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CatchBullishDivergence(int shift)
  {
   if(IsIndicatorTrough(shift) == false)
       return; 
   int currentTrough = shift;
   int lastTrough = GetIndicatorLastTrough(shift);
//----
   if(OsMA[currentTrough] > OsMA[lastTrough] && 
      Low[currentTrough] < Low[lastTrough])
     {
       bullishDivergence[currentTrough] = OsMA[currentTrough];
      
       if(drawDivergenceLines == true)
         {
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                              Low[lastTrough], Green, STYLE_SOLID);
           DrawIndicatorTrendLine(Time[currentTrough], Time[lastTrough], 
                                  OsMA[currentTrough],
                                  OsMA[lastTrough], Green, STYLE_SOLID);
         }
       if(displayAlert == true)
           DisplayAlert("Classical bullish divergence on: ", currentTrough);  
     }
//----
   if(OsMA[currentTrough] < OsMA[lastTrough] && 
      Low[currentTrough] > Low[lastTrough])
     {
       bullishDivergence[currentTrough] = OsMA[currentTrough];
       //----
       if(drawDivergenceLines == true)
         {
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                              Low[lastTrough], Green, STYLE_DOT);
           DrawIndicatorTrendLine(Time[currentTrough], Time[lastTrough], 
                                  OsMA[currentTrough],
                                  OsMA[lastTrough], Green, STYLE_DOT);
         }
       if(displayAlert == true)
           DisplayAlert("Reverse bullish divergence on: ", currentTrough);   
     }      
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CatchBearishDivergence(int shift)
  {
   if(IsIndicatorPeak(shift) == false)
       return;
   int currentPeak = shift;
   int lastPeak = GetIndicatorLastPeak(shift);   
//----
   if(OsMA[currentPeak] < OsMA[lastPeak] && 
      High[currentPeak] > High[lastPeak])
     {
       bearishDivergence[currentPeak] = OsMA[currentPeak];
       //----
       if(drawDivergenceLines == true)
         {
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], Red, STYLE_SOLID);
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  OsMA[currentPeak],
                                  OsMA[lastPeak], Red, STYLE_SOLID);
         }
       if(displayAlert == true)
           DisplayAlert("Classical bearish divergence on: ", 
                        currentPeak);  
     }
//----
   if(OsMA[currentPeak] > OsMA[lastPeak] && 
       High[currentPeak] < High[lastPeak])
     {
       bearishDivergence[currentPeak] = OsMA[currentPeak];
      
       if(drawDivergenceLines == true)
         {
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], Red, STYLE_DOT);
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  OsMA[currentPeak],
                                  OsMA[lastPeak], Red, STYLE_DOT);
         }
       if(displayAlert == true)
           DisplayAlert("Reverse bearish divergence on: ", currentPeak);   
     }   
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorPeak(int shift)
  {
   if(OsMA[shift] > 0 + positiveSensitivity && 
      OsMA[shift] > OsMA[shift+1] && OsMA[shift] > OsMA[shift-1])
     {
       for(int i = shift + 1; i < Bars; i++)
         {
           if(OsMA[i] < 0)
               return(true);
           if(OsMA[i] > OsMA[shift])
               break;            
         }
     }   
   return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorTrough(int shift)
  {
   if(OsMA[shift] < 0 + negativeSensitivity && 
      OsMA[shift] < OsMA[shift+1] && OsMA[shift] < OsMA[shift-1])
     {
       for(int i = shift + 1; i < Bars; i++)
         {
           if(OsMA[i] > 0)
               return(true);
           if(OsMA[i] < OsMA[shift])
               break;            
         }
     }   
   return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
  {
   bool redZone = false;
   
   for(int i = shift; i < Bars; i++)
     {
       if(OsMA[i] > 0 && redZone == false)
          continue;
       if(OsMA[i] < 0)
         {
           redZone = true;
           continue;
         }
       if(OsMA[i] < positiveSensitivity)
           continue;
       if(OsMA[i] > OsMA[i+1] && OsMA[i] > OsMA[i-1])
           return(i);
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
{
   bool greenZone = false;
   
   for (int i = shift; i < Bars; i++)
   {
      if (OsMA[i] < 0 && greenZone == false)
         continue;
      if (OsMA[i] > 0)
      {
         greenZone = true;
         continue;
      }
      if (OsMA[i] > negativeSensitivity)
         continue;      
      if (OsMA[i] < OsMA[i+1] && OsMA[i] < OsMA[i-1])
         return(i);
   }
   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 = "DivergenceLine2.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("FX5_Divergence_v2.0(" + 
                                    fastEMA + "," + slowEMA + "," + 
                                    signal + ")");
//----
   if(indicatorWindow < 0)
       return;   
   string label = "DivergenceLine2.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