Author: Copyright � 2012, TheXpert
XLab_ZZP

This script is a technical analysis tool designed to identify and map significant price "peaks" and "troughs" on a trading chart, creating a visual zigzag pattern. It helps traders see the underlying structure of price movements by filtering out minor market noise and highlighting major trends.

Core Functionality

The logic operates by scanning historical price data to determine when the market has reached a new significant high or low. Instead of marking every tiny fluctuation, it uses a specific mathematical threshold—defined by a percentage—to decide whether a price movement is substantial enough to be considered a "turning point."

How the Logic Works

  • Trend Tracking: The script constantly monitors the current direction of the market (whether it is moving upward or downward). It keeps a memory of the most recent significant peak and the most recent significant trough.
  • Dynamic Peak/Trough Identification:
    • In an Uptrend: If the price continues to rise, the script updates the "peak" value. However, if the price drops significantly below that peak (based on your specified percentage), the script recognizes a reversal and marks a new "trough."
    • In a Downtrend: Conversely, if the price is falling, the script tracks the lowest point. If the price climbs back up significantly above that trough, the script identifies a reversal and marks a new "peak."
  • Smart Filtering: The tool includes logic to distinguish between "high" and "low" prices based on whether a candle closed higher or lower than it opened. This ensures that the zigzag lines are drawn more accurately relative to the actual price action of each individual bar.

Key Features for the User

  • Customizable Sensitivity: Through the ChannelPercent setting, you can control how "strict" the indicator is. A smaller percentage will result in more frequent zigzag points (more sensitive to small moves), while a larger percentage will only highlight major structural shifts in the market.
  • Visual Clarity: The script automatically handles the drawing of the zigzag lines on your chart, allowing you to see the flow of the market at a glance without cluttering your screen with every minor price tick.

Important Usage Notes

The script includes specific internal warnings regarding the "Zero Bar" (the current live candle). Because the current bar's price is constantly changing, the last point of the zigzag may shift or "repaint" until that bar is closed. For the sake of accuracy, it is recommended to base any long-term strategy on the completed points rather than the real-time fluctuating end of the line.

Miscellaneous
Implements a curve of type %1
3 Views
1 Downloads
0 Favorites
XLab_ZZP
//+------------------------------------------------------------------+
//|                                                          ZZP.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012, TheXpert"
#property link      "theforexpert@gmail.com"

#property indicator_chart_window

extern double ChannelPercent = 0.08;

// attention! when used, this option can lead to incorrect visualization of last ZZ ray at 0 bar
// incorrect visualization will be redrawn when new bar appears
// use it carefully and don't expect complete correctness
// never(!) use this indicator values from 0 bar in your automated strategies.


// never(!) use this option if this indicator is used in automated strategy.
// if used, this option can lead to incorrect extremum parsing in your EA

/* extern */ bool DrawZeroBar = false;

#property indicator_buffers 5

#property indicator_color1 LightGray
#property indicator_color2 LightGray

double Maxs[];
double Mins[];

double Direction[];

double MaxTime[];
double MinTime[];

string symbol;

#define UP 0.0001
#define DN -0.0001
#define NONE 0

bool Inited;

datetime LastTime;

int init()
{
   SetIndexBuffer(0, Maxs);
   SetIndexBuffer(1, Mins);
   
   SetIndexBuffer(2, MinTime);
   SetIndexBuffer(3, MaxTime);
   
   SetIndexBuffer(4, Direction);

   SetIndexStyle(0, DRAW_ZIGZAG);
   SetIndexStyle(1, DRAW_ZIGZAG);

   SetIndexStyle(2, DRAW_NONE);
   SetIndexStyle(3, DRAW_NONE);
   SetIndexStyle(4, DRAW_NONE);

   symbol = Symbol();
   
   IndicatorDigits(Digits);

   Inited = false;
   LastTime = 0;
   
   return(0);
}

int start()
{
   if (!Inited)
   {
      ArrayInitialize(Mins, EMPTY_VALUE);
      ArrayInitialize(Maxs, EMPTY_VALUE);
      ArrayInitialize(MinTime, EMPTY_VALUE);
      ArrayInitialize(MaxTime, EMPTY_VALUE);
      ArrayInitialize(Direction, EMPTY_VALUE);
   }
   
   int ToCount = Bars - IndicatorCounted();
   
   // DON'T fix to >= 0. For the 0 bar the logic is in DrawZeroBar block
   for (int i = ToCount - 1; i > 0; i--)
   {
      if (i < Bars - 1)
      {
         MinTime[i] = MinTime[i + 1];
         MaxTime[i] = MaxTime[i + 1];
         Direction[i] = Direction[i + 1];
         Maxs[i] = EMPTY_VALUE;
         Mins[i] = EMPTY_VALUE;
      }
      
      Check(i);
   }
   
   if (DrawZeroBar)
   {
      if (LastTime != Time[0])
      {
         LastTime = Time[0];

         MinTime[0] = MinTime[1];
         MaxTime[0] = MaxTime[1];
         Direction[0] = Direction[1];
         Maxs[0] = EMPTY_VALUE;
         Mins[0] = EMPTY_VALUE;
      }
      
      CheckPrice(0, Close[0]);
   }
   else
   {
      Maxs[0] = EMPTY_VALUE;
      Mins[0] = EMPTY_VALUE;
   }
   
   return(0);
}

void Check(int offset)
{
   double o = Open[offset];
   double h = High[offset];
   double l = Low[offset];
   double c = Close[offset];

   if (c < o)
   {
      CheckPrice(offset, h);
      CheckPrice(offset, l);
   }
   else
   {
      CheckPrice(offset, l);
      CheckPrice(offset, h);
   }
}

void CheckPrice(int offset, double p)
{
   if (!Inited)
   {
      CheckInit(offset, p);
      Inited = true;
   }
   else
   {
      if (Direction[offset] == UP) CheckUp(offset, p);
      else if (Direction[offset] == DN) CheckDn(offset, p);
   }
}

void CheckInit(int offset, double c)
{
   MaxTime[offset] = Time[offset];
   MinTime[offset] = Time[offset];
   
   Maxs[offset] = c;
   Mins[offset] = c;
      
   Direction[offset] = UP;
}

void CheckUp(int offset, double c)
{
   int lastOffset = iBarShift(symbol, 0, MaxTime[offset]);
   if (Maxs[lastOffset] == EMPTY_VALUE)
   {
      Maxs[lastOffset] = High[lastOffset];
   }
   
   if (c > Maxs[lastOffset])
   {
      Maxs[lastOffset] = EMPTY_VALUE;
      Maxs[offset] = c;
      MaxTime[offset] = Time[offset];
      lastOffset = offset;
   }
   
   if (c*(1 + ChannelPercent/100.0) < Maxs[lastOffset])
   {
      Direction[offset] = DN;
      
      Mins[offset] = c;
      MinTime[offset] = Time[offset];
   }
}

void CheckDn(int offset, double c)
{
   int lastOffset = iBarShift(symbol, 0, MinTime[offset]);
   if (Mins[lastOffset] == EMPTY_VALUE)
   {
      Mins[lastOffset] = Low[lastOffset];
   }
   
   if (c < Mins[lastOffset])
   {
      Mins[lastOffset] = EMPTY_VALUE;
      Mins[offset] = c;
      MinTime[offset] = Time[offset];
      lastOffset = offset;
   }
   
   if (c*(1 - ChannelPercent/100.0) > Mins[lastOffset])
   {
      Direction[offset] = UP;

      Maxs[offset] = c;
      MaxTime[offset] = Time[offset];
   }
}

Comments