MACD_Histogram_v1

Author: Copyright � 2008, MetaQuotes Software Corp.
MACD_Histogram_v1

This script is a sophisticated technical analysis tool designed for the MetaTrader platform. It focuses on identifying specific price behaviors known as "divergences" by combining traditional trend indicators with visual trend lines and automated alerts.

Core Functionality

The tool operates by calculating the Moving Average Convergence Divergence (MACD), a standard momentum indicator that shows the relationship between two moving averages of a security's price. It breaks this down into three visual components:

  • The MACD Line: Shows the immediate momentum.
  • The Signal Line: A smoothed version of the MACD line used to identify trend directions.
  • The Histogram: The visual difference between the MACD and Signal lines.

Divergence Detection Logic

The primary purpose of this script is to identify "Divergences"—situations where the price action and the momentum indicator disagree with one another. These are often considered early warning signs of a trend reversal.

1. Bullish Divergence (Potential Buy Signals) The script looks for instances where:

  • The market price reaches a new low, but the MACD indicator does not drop as low as it did previously.
  • It specifically identifies "Classical" and "Reverse" variations to distinguish between different types of momentum shifts.
  • When identified, the script places Lime colored arrows and trend lines on the chart.

2. Bearish Divergence (Potential Sell Signals) Conversely, the script monitors for:

  • The market price reaches a new high, while the MACD indicator fails to reach the same height as previous peaks.
  • Similar to the bullish logic, it detects both "Classical" and "Reverse" bearish movements.
  • When these occur, the script marks the area with Red colored arrows and trend lines.

Visual and Notification Features

To make this data actionable for a trader, the script includes several automated visual features:

  • Trend Lines: The script automatically draws physical trend lines on both the price chart (the main window) and the indicator window. This allows you to see the exact connection between the price peaks/troughs and the corresponding indicator movements.
  • Customizable Styles: Depending on the type of divergence found, the script can change the line style (solid vs. dotted) to help differentiate between standard and "reverse" signals.
  • Real-Time Alerts: The script is equipped with a notification system. When a significant divergence is detected, it triggers an automated alert pop-up on your screen, providing the specific type of divergence and its location in time.

Summary for the User

Essentially, this tool acts as a "scout." Instead of you having to manually compare price peaks to indicator lows across many candles, the script does this math automatically. It highlights areas where the market's strength is weakening despite price movement, drawing lines and sending alerts to help you spot potential trend reversals more quickly.

Indicators Used
Moving average indicator
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screen
16 Views
0 Downloads
0 Favorites
MACD_Histogram_v1
//+------------------------------------------------------------------+
//|                                               MACD_Histogram.mq4 |
//|                      Copyright © 2008, MetaQuotes Software Corp. |
//|                         http://www.frankie-prasetio.blogspot.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.frankie-prasetio.blogspot.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 DodgerBlue
#property indicator_color2 Red
#property indicator_color3 Silver
#property indicator_color4 Lime
#property indicator_color5 Red
#property indicator_level1 0
//----
#define arrowsDisplacement 0.0001
//---- input parameters
extern string separator1 = "*** MACD Settings ***";
extern int FastMAPeriod = 12;
extern int SlowMAPeriod = 26;
extern int SignalMAPeriod = 9;
extern string separator2 = "*** Indicator Settings ***";
extern bool   drawIndicatorTrendLines = true;
extern bool   drawPriceTrendLines = true;
extern bool   displayAlert = true;
//---- buffers
double MACDLineBuffer[];
double SignalLineBuffer[];
double HistogramBuffer[];
double bullishDivergence[];
double bearishDivergence[];
//---- variables
double alpha = 0;
double alpha_1 = 0;
//----
static datetime lastAlertTime;
static string   indicatorName;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IndicatorDigits(Digits + 1);
   //---- indicators
   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, MACDLineBuffer);
   SetIndexDrawBegin(0, SlowMAPeriod);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, SignalLineBuffer);
   SetIndexDrawBegin(1, SlowMAPeriod + SignalMAPeriod);
   SetIndexStyle(2, DRAW_HISTOGRAM, STYLE_SOLID,2);
   SetIndexBuffer(2, HistogramBuffer);
   SetIndexDrawBegin(2, SlowMAPeriod + SignalMAPeriod);
   SetIndexStyle(3, DRAW_ARROW);
   SetIndexArrow(3, 233);
   SetIndexBuffer(3, bullishDivergence);
   SetIndexStyle(4, DRAW_ARROW);
   SetIndexArrow(4, 234);
   SetIndexBuffer(4, bearishDivergence);
   //---- name for DataWindow and indicator subwindow label
   indicatorName =("MACD(" + FastMAPeriod+"," + SlowMAPeriod + "," + SignalMAPeriod + ")");
   SetIndexLabel(2, "MACD");
   SetIndexLabel(3, "Signal");
   SetIndexLabel(4, "Histogr");
   IndicatorShortName(indicatorName);  
   //----
	  alpha = 2.0 / (SignalMAPeriod + 1.0);
	  alpha_1 = 1.0 - alpha;
   //----
   return(0);
}
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   for(int i = ObjectsTotal() - 1; i >= 0; i--)
     {
       string label = ObjectName(i);
       if(StringSubstr(label, 0, 19) != "MACD_DivergenceLine")
           continue;
       ObjectDelete(label);   
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int limit;
   int counted_bars = IndicatorCounted();
   //---- check for possible errors
   if(counted_bars < 0) 
       return(-1);
   //---- last counted bar will be recounted
   if(counted_bars > 0) 
       counted_bars--;
   limit = Bars - counted_bars;
   CalculateIndicator(counted_bars);
//----
   for(int i = limit; i >= 0; i--)
     {
       MACDLineBuffer[i] = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, i) - 
                           iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, i);
       SignalLineBuffer[i] = alpha*MACDLineBuffer[i] + alpha_1*SignalLineBuffer[i+1];
       HistogramBuffer[i] = MACDLineBuffer[i] - SignalLineBuffer[i];
     }
//----
   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)
  {
   MACDLineBuffer[i] = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, i) - 
                       iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, i);
   SignalLineBuffer[i] = alpha*MACDLineBuffer[i] + alpha_1*SignalLineBuffer[i+1];
   HistogramBuffer[i] = MACDLineBuffer[i] - SignalLineBuffer[i];      
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CatchBullishDivergence(int shift)
  {
   if(IsIndicatorTrough(shift) == false)
       return;  
   int currentTrough = shift;
   int lastTrough = GetIndicatorLastTrough(shift);
//----   
   if(MACDLineBuffer[currentTrough] > MACDLineBuffer[lastTrough] && 
      Low[currentTrough] < Low[lastTrough])
     {
       bullishDivergence[currentTrough] = MACDLineBuffer[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                             Low[lastTrough], Lime, STYLE_SOLID);
       //----
       if(drawIndicatorTrendLines == true)
          DrawIndicatorTrendLine(Time[currentTrough], 
                                 Time[lastTrough], 
                                 MACDLineBuffer[currentTrough],
                                 MACDLineBuffer[lastTrough], 
                                 Lime, STYLE_SOLID);
       //----
       if(displayAlert == true)
          DisplayAlert("Classical bullish divergence on: ", 
                        currentTrough);  
     }
//----   
   if(MACDLineBuffer[currentTrough] < MACDLineBuffer[lastTrough] && 
      Low[currentTrough] > Low[lastTrough])
     {
       bullishDivergence[currentTrough] = MACDLineBuffer[currentTrough] - 
                                          arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentTrough], Time[lastTrough], 
                              Low[currentTrough], 
                              Low[lastTrough], Lime, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)                            
           DrawIndicatorTrendLine(Time[currentTrough], 
                                  Time[lastTrough], 
                                  MACDLineBuffer[currentTrough],
                                  MACDLineBuffer[lastTrough], 
                                  Lime, 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(MACDLineBuffer[currentPeak] < MACDLineBuffer[lastPeak] && 
      High[currentPeak] > High[lastPeak])
     {
       bearishDivergence[currentPeak] = MACDLineBuffer[currentPeak] + 
                                        arrowsDisplacement;
      
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], Red, STYLE_SOLID);
                            
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  MACDLineBuffer[currentPeak],
                                  MACDLineBuffer[lastPeak], Red, STYLE_SOLID);

       if(displayAlert == true)
           DisplayAlert("Classical bearish divergence on: ", 
                        currentPeak);  
     }
   if(MACDLineBuffer[currentPeak] > MACDLineBuffer[lastPeak] && 
      High[currentPeak] < High[lastPeak])
     {
       bearishDivergence[currentPeak] = MACDLineBuffer[currentPeak] + 
                                        arrowsDisplacement;
       //----
       if(drawPriceTrendLines == true)
           DrawPriceTrendLine(Time[currentPeak], Time[lastPeak], 
                              High[currentPeak], 
                              High[lastPeak], Red, STYLE_DOT);
       //----
       if(drawIndicatorTrendLines == true)
           DrawIndicatorTrendLine(Time[currentPeak], Time[lastPeak], 
                                  MACDLineBuffer[currentPeak],
                                  MACDLineBuffer[lastPeak], Red, STYLE_DOT);
       //----
       if(displayAlert == true)
           DisplayAlert("Reverse bearish divergence on: ", 
                        currentPeak);   
     }   
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorPeak(int shift)
  {
   if(MACDLineBuffer[shift] >= MACDLineBuffer[shift+1] && MACDLineBuffer[shift] > MACDLineBuffer[shift+2] && 
      MACDLineBuffer[shift] > MACDLineBuffer[shift-1])
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsIndicatorTrough(int shift)
  {
   if(MACDLineBuffer[shift] <= MACDLineBuffer[shift+1] && MACDLineBuffer[shift] < MACDLineBuffer[shift+2] && 
      MACDLineBuffer[shift] < MACDLineBuffer[shift-1])
       return(true);
   else 
       return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastPeak(int shift)
  {
   for(int i = shift + 5; i < Bars; i++)
     {
       if(SignalLineBuffer[i] >= SignalLineBuffer[i+1] && SignalLineBuffer[i] >= SignalLineBuffer[i+2] &&
          SignalLineBuffer[i] >= SignalLineBuffer[i-1] && SignalLineBuffer[i] >= SignalLineBuffer[i-2])
         {
           for(int j = i; j < Bars; j++)
             {
               if(MACDLineBuffer[j] >= MACDLineBuffer[j+1] && MACDLineBuffer[j] > MACDLineBuffer[j+2] &&
                  MACDLineBuffer[j] >= MACDLineBuffer[j-1] && MACDLineBuffer[j] > MACDLineBuffer[j-2])
                   return(j);
             }
         }
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int GetIndicatorLastTrough(int shift)
  {
    for(int i = shift + 5; i < Bars; i++)
      {
        if(SignalLineBuffer[i] <= SignalLineBuffer[i+1] && SignalLineBuffer[i] <= SignalLineBuffer[i+2] &&
           SignalLineBuffer[i] <= SignalLineBuffer[i-1] && SignalLineBuffer[i] <= SignalLineBuffer[i-2])
          {
            for (int j = i; j < Bars; j++)
              {
                if(MACDLineBuffer[j] <= MACDLineBuffer[j+1] && MACDLineBuffer[j] < MACDLineBuffer[j+2] &&
                   MACDLineBuffer[j] <= MACDLineBuffer[j-1] && MACDLineBuffer[j] < MACDLineBuffer[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 = "MACD_DivergenceLine.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 = "MACD_DivergenceLine.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