ZigZagZug_v1_3
Download scriptThis script is designed for the MetaTrader 4 platform to provide traders with a visual representation of significant price movements using a modified "ZigZag" logic. Its primary goal is to filter out market noise and highlight the core structural shifts in price—specifically identifying the major peaks (highs) and valleys (lows).
Core Functionality
The script identifies key turning points in the market by analyzing historical price data based on three main user-defined criteria:
- Depth: How far back the tool looks to find a significant high or low.
- Backstep: A mechanism to ensure that points are not identified too close to one another, preventing the chart from becoming cluttered with minor fluctuations.
- Deviation: The minimum price change required to consider a new point as a valid "turn."
How the Logic Works
The script follows a multi-stage process to determine where to draw its lines:
-
Data Scanning and Filtering: The tool constantly scans the most recent price history. It identifies potential highs and lows but immediately filters out any movements that do not meet the "Deviation" threshold. This ensures that small, insignificant wobbles in price are ignored.
-
Peak and Valley Identification: Once the data is filtered, the script looks for "peaks" (the highest points) and "valleys" (the lowest points). It uses a logical sequence to ensure the lines alternate correctly—meaning it won't draw two "highs" in a row without a "low" in between. This creates a clean, zigzagging path that clearly shows the trend.
-
Dynamic Adjustment: The script is intelligent enough to recalculate points if a new, more extreme high or low occurs within a specific look-back window. If the price moves significantly beyond a previously identified peak, the script "adjusts" the line to reflect this new extreme, ensuring the visual stays accurate to the most recent market reality.
-
Breakout Detection: Beyond just drawing lines, this specific version includes an optional breakout tracking system. It monitors if the current price is breaking through the highs or lows identified by the ZigZag logic.
-
User Notifications: If enabled, the script can provide real-time alerts. When the market price breaks through a significant structural high or low, it can trigger a pop-up notification on the user's screen, specifying exactly which symbol and timeframe the breakout occurred on.
Visual Output
The script renders these findings directly onto the price chart:
- ZigZag Lines: Solid lines connecting the major peaks and valleys.
- Markers: Specific icons (arrows) to clearly mark exactly where a high or low was confirmed.
- Breakout Markers: Distinct icons that appear only when the price breaches a significant structural level, providing a visual cue for potential trend continuations or reversals.
//+------------------------------------------------------------------------------------+
#define _NAME_ "ZigZagZug"
#define _TITLE_ "ZigZagZug (v1.3r1) - MetaTrader 4 Indicator"
#define _ABSTRACT_ "ZigZag Indicator with Extra Features"
#property copyright "Copyright © 2014, Fernando M. I. Carreiro"
#property link "mailto:fmi@carreiro.co.pt?subject=ZigZagZug.v1.3"
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_width1 2
#property indicator_style1 0
#property indicator_color1 Silver
#property indicator_width2 1
#property indicator_style2 0
#property indicator_color2 Aqua
#property indicator_width3 1
#property indicator_style3 0
#property indicator_color3 Magenta
#property indicator_width4 1
#property indicator_style4 2
#property indicator_color4 Aqua
#property indicator_width5 1
#property indicator_style5 2
#property indicator_color5 Magenta
#property indicator_width6 1
#property indicator_style6 0
#property indicator_color6 Aqua
#property indicator_width7 1
#property indicator_style7 0
#property indicator_color7 Magenta
//+------------------------------------------------------------------------------------+
// Please note that the TAB Size is based on 4, not 3
//+------------------------------------------------------------------------------------+
//+------------------------------------------------------------------------------------+
// Indicator Settings
//+------------------------------------------------------------------------------------+
//--- Primary Indicator Settings
extern string
strPrimarySettings = "--- Primary Indicator Settings ---"
;
//---- Define ZigZag Parameters
extern int
intDepth = 12 // Depth Search of ZigZag Extreems
, intBackStep = 3 // BackStep for ZigZag Extreems
;
extern double
dblDeviation = 5.0 // Price Deviation of ZigZag Extreems
;
extern bool
boolShowBreakOut = false // Show where Breakouts occured
, boolAlertOnBreakOut = false // Alert User of a Breakout
;
extern string
strBreakoutMsgUpper = "(High) Breakout has occured!"
, strBreakoutMsgLower = "(Low) Breakout has occured!"
;
//---- Define ZigZagZug Buffers
double
dblArrayZigZag[] // ZigZag Points
, dblArrayZigZagHigh[] // ZigZag Highs
, dblArrayZigZagLow[] // ZigZag Lows
, dblArrayHigh[] // Running High of Depth Search
, dblArrayLow[] // Running Low of Depth Search
, dblArrayBreakOutHigh[] // BreakOut High of Depth Search
, dblArrayBreakOutLow[] // BreakOut Low of Depth Search
;
//---- Define Extra Variables
bool
boolDownloadHistory = false // Download History Data
;
int
intLevel = 3 // For Depth Recounting
, intIndexLimit = 100 // Limit Count of Index
;
datetime
dtAlertLastUpper = NULL // Date/Time of last Upper Alert
, dtAlertLastLower = NULL // Date/Time of last Lower Alert
;
string
strSymbolName // Current Chart Symbol Name
, strTimeFrameName // Current Chart TimeFrame Name
;
//---- Define Search States
#define _SEARCH_PEAK_ +1
#define _SEARCH_BOTH_ 0
#define _SEARCH_VALLEY_ -1
//+------------------------------------------------------------------------------------+
// Indicator Functions
//+------------------------------------------------------------------------------------+
//---- Initialise Buffer Index and other Properties
int init()
{
// Set Number of Buffers to be used
if( boolShowBreakOut || boolAlertOnBreakOut )
IndicatorBuffers( 7 );
else
IndicatorBuffers( 5 );
// Set Number of Digits (Precision)
IndicatorDigits( Digits );
// Set Indicator Name
IndicatorShortName(
StringConcatenate( _NAME_,
" (", intDepth
, ",", intBackStep
, ",", dblDeviation, ")"
) );
// Set Buffer Index
SetIndexBuffer( 0, dblArrayZigZag );
SetIndexBuffer( 1, dblArrayZigZagHigh );
SetIndexBuffer( 2, dblArrayZigZagLow );
SetIndexBuffer( 3, dblArrayHigh );
SetIndexBuffer( 4, dblArrayLow );
// Set Index Label
SetIndexLabel( 0, "ZigZag Points" );
SetIndexLabel( 1, "ZigZag Highs" );
SetIndexLabel( 2, "ZigZag Lows" );
SetIndexLabel( 3, "Depth High" );
SetIndexLabel( 4, "Depth Low" );
// Set Line Style
SetIndexStyle( 0, DRAW_SECTION, STYLE_SOLID );
SetIndexStyle( 1, DRAW_ARROW, STYLE_SOLID );
SetIndexStyle( 2, DRAW_ARROW, STYLE_SOLID );
SetIndexStyle( 3, DRAW_LINE, STYLE_DOT );
SetIndexStyle( 4, DRAW_LINE, STYLE_DOT );
// Set Arrow Types
SetIndexArrow( 1, 108 );
SetIndexArrow( 2, 108 );
// Set Empty Value
SetIndexEmptyValue( 0, NULL );
SetIndexEmptyValue( 1, NULL );
SetIndexEmptyValue( 2, NULL );
SetIndexEmptyValue( 3, NULL );
SetIndexEmptyValue( 4, NULL );
if( boolShowBreakOut || boolAlertOnBreakOut ) // Extra Indicator Buffers
{
// Set Buffer Index
SetIndexBuffer( 5, dblArrayBreakOutHigh );
SetIndexBuffer( 6, dblArrayBreakOutLow );
// Set Index Label
SetIndexLabel( 5, "BreakOut High" );
SetIndexLabel( 6, "BreakOut Low" );
// Set Empty Value
SetIndexEmptyValue( 5, NULL );
SetIndexEmptyValue( 6, NULL );
if( boolShowBreakOut ) // Extra Indicator Settings to show Breakouts
{
// Set Line Style
SetIndexStyle( 5, DRAW_ARROW, STYLE_SOLID );
SetIndexStyle( 6, DRAW_ARROW, STYLE_SOLID );
// Set Arrow Types
SetIndexArrow( 5, 161 );
SetIndexArrow( 6, 161 );
}
else
{
// Set Line Style
SetIndexStyle( 5, DRAW_NONE );
SetIndexStyle( 6, DRAW_NONE );
}
}
//---- Adjust for 3 or 5 Digit Brokers
if( ( Digits == 3 ) || ( Digits == 5 ) ) dblDeviation *= 10;
// Correct External Variables
if( intDepth < 1 ) intDepth = 1;
if( intBackStep < 1 ) intBackStep = 1;
dblDeviation = MathRound( MathAbs( dblDeviation ) ) * Point;
//---- Get Current Chart Symbol and TimeFrame
strSymbolName = Symbol();
strTimeFrameName = strTimeFrame( Period() );
return( NULL );
}
//---- Initialise Buffer Index and other Properties
int start()
{
int
intLimitBars, intCountedBars = IndicatorCounted()
, intCounter, intSearch = _SEARCH_BOTH_
, intLowPosition, intHighPosition
, intShift, intBack
, intIndex
;
double
dblResult, dblValue
, dblCurrentLow, dblCurrentHigh
, dblPreviousLow, dblPreviousHigh
;
if ( intCountedBars < 0 )
return( EMPTY );
if( intCountedBars == 0 )
{
// Check for Downloaded History Data
if( boolDownloadHistory )
{
ArrayInitialize( dblArrayZigZag, NULL );
ArrayInitialize( dblArrayZigZagHigh, NULL );
ArrayInitialize( dblArrayZigZagLow, NULL );
ArrayInitialize( dblArrayHigh, NULL );
ArrayInitialize( dblArrayLow, NULL );
ArrayInitialize( dblArrayBreakOutHigh, NULL );
ArrayInitialize( dblArrayBreakOutLow, NULL );
}
intLimitBars = Bars - intDepth;
boolDownloadHistory = true;
}
if ( intCountedBars > 0 )
{
for( intIndex = 0, intCounter = 0;
( intCounter < intLevel ) && ( intIndex < intIndexLimit );
intIndex++ )
{
dblResult = dblArrayZigZag[ intIndex ];
if( dblResult !=0 ) intCounter++;
}
intIndex--;
intLimitBars = intIndex;
dblResult = dblArrayZigZagLow[ intIndex ];
if( dblResult != 0 )
{
dblCurrentLow = dblResult;
intSearch = _SEARCH_PEAK_;
}
else
{
dblCurrentHigh = dblArrayZigZagHigh[ intIndex ];
intSearch = _SEARCH_VALLEY_;
}
for( intIndex = intLimitBars - 1; intIndex >= 0; intIndex-- )
{
dblArrayZigZag[ intIndex ] = NULL;
dblArrayZigZagLow[ intIndex ] = NULL;
dblArrayZigZagHigh[ intIndex ] = NULL;
dblArrayBreakOutLow[ intIndex ] = NULL;
dblArrayBreakOutHigh[ intIndex ] = NULL;
}
}
//---- Initial Analysis of Data
for( intShift = intLimitBars; intShift >= 0; intShift-- )
{
//---- Verify the High Value
dblArrayHigh[ intShift ]
= High[ iHighest( NULL, 0, MODE_HIGH, intDepth, intShift ) ];
dblValue = dblArrayHigh[ intShift ];
if( boolShowBreakOut || boolAlertOnBreakOut )
{
if( High[ intShift ] == dblValue)
dblArrayBreakOutHigh[ intShift ] = dblValue;
else
dblArrayBreakOutHigh[ intShift ] = NULL;
}
if( dblValue == dblPreviousHigh )
dblValue = NULL;
else
{
dblPreviousHigh = dblValue;
if( ( dblValue - High[ intShift ] ) > dblDeviation )
dblValue = NULL;
else
{
for( intBack = 1; intBack <= intBackStep; intBack++ )
{
dblResult = dblArrayZigZagHigh[ intShift + intBack ];
if( ( dblResult != 0 ) && ( dblResult < dblValue ) )
dblArrayZigZagHigh[ intShift + intBack ] = NULL;
}
}
}
if( High[ intShift ] == dblValue)
dblArrayZigZagHigh[ intShift ] = dblValue;
else
dblArrayZigZagHigh[ intShift ] = NULL;
//---- Verify the Low Value
dblArrayLow[ intShift ]
= Low[ iLowest( NULL, 0, MODE_LOW, intDepth, intShift ) ];
dblValue = dblArrayLow[ intShift ];
if( boolShowBreakOut || boolAlertOnBreakOut )
{
if( Low[ intShift ] == dblValue)
dblArrayBreakOutLow[ intShift ] = dblValue;
else
dblArrayBreakOutLow[ intShift ] = NULL;
}
if( dblValue == dblPreviousLow )
dblValue = NULL;
else
{
dblPreviousLow = dblValue;
if( ( Low[ intShift ] - dblValue ) > dblDeviation )
dblValue = NULL;
else
{
for( intBack = 1; intBack <= intBackStep; intBack++ )
{
dblResult = dblArrayZigZagLow[ intShift + intBack ];
if( ( dblResult != 0 ) && ( dblResult > dblValue ) )
dblArrayZigZagLow[ intShift + intBack ] = NULL;
}
}
}
if( Low[ intShift ] == dblValue)
dblArrayZigZagLow[ intShift ] = dblValue;
else
dblArrayZigZagLow[ intShift ] = NULL;
}
//---- Final Filtering and Adjustments
if( intSearch == _SEARCH_BOTH_ )
{
dblPreviousLow = NULL;
dblPreviousHigh = NULL;
}
else
{
dblPreviousLow = dblCurrentLow;
dblPreviousHigh = dblCurrentHigh;
}
for( intShift = intLimitBars; intShift >= 0; intShift-- )
{
switch( intSearch )
{
case _SEARCH_BOTH_:
if( ( dblPreviousLow == NULL ) && ( dblPreviousHigh == NULL ) )
{
if( dblArrayZigZagHigh[ intShift ] != NULL )
{
intHighPosition = intShift;
dblPreviousHigh = High[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousHigh;
intSearch = _SEARCH_VALLEY_;
}
if( dblArrayZigZagLow[ intShift ] != NULL )
{
intLowPosition = intShift;
dblPreviousLow = Low[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousLow;
intSearch = _SEARCH_PEAK_;
}
}
break;
case _SEARCH_PEAK_:
if( dblArrayZigZagHigh[ intShift ] == NULL )
{
if( ( dblArrayZigZagLow[ intShift ] != NULL ) &&
( dblArrayZigZagLow[ intShift ] < dblPreviousLow ) )
{
dblArrayZigZag[ intLowPosition ] = NULL;
intLowPosition = intShift;
dblPreviousLow = dblArrayZigZagLow[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousLow;
}
}
else
{
if( dblArrayZigZagLow[ intShift ] == NULL )
{
intHighPosition = intShift;
dblPreviousHigh = dblArrayZigZagHigh[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousHigh;
intSearch = _SEARCH_VALLEY_;
}
}
break;
case _SEARCH_VALLEY_:
if( dblArrayZigZagLow[ intShift ] == NULL )
{
if( ( dblArrayZigZagHigh[ intShift ] != NULL ) &&
( dblArrayZigZagHigh[ intShift ] > dblPreviousHigh ) )
{
dblArrayZigZag[ intHighPosition ] = NULL;
intHighPosition = intShift;
dblPreviousHigh = dblArrayZigZagHigh[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousHigh;
}
}
else
{
if( dblArrayZigZagHigh[ intShift ] == NULL )
{
intLowPosition = intShift;
dblPreviousLow = dblArrayZigZagLow[ intShift ];
dblArrayZigZag[ intShift ] = dblPreviousLow;
intSearch = _SEARCH_PEAK_;
}
}
break;
}
}
// Check current bar for breakouts and alert user
if( boolAlertOnBreakOut )
{
if( High[ 0 ] == dblArrayBreakOutHigh[ 0 ] )
{
if( Time[ 0 ] != dtAlertLastUpper )
{
Alert( strBreakoutMsgUpper, " [ ", DoubleToStr( High[ 0 ], Digits ),
"; " , strSymbolName, "; " , strTimeFrameName, " ]" );
dtAlertLastUpper = Time[ 0 ];
}
}
if( Low[ 0 ] == dblArrayBreakOutLow[ 0 ] )
{
if( Time[ 0 ] != dtAlertLastLower )
{
Alert( strBreakoutMsgLower, " [ ", DoubleToStr( Low[ 0 ], Digits ),
"; " , strSymbolName, "; " , strTimeFrameName, " ]" );
dtAlertLastLower = Time[ 0 ];
}
}
}
return( NULL );
}
//---- Initialise Buffer Index and other Properties
string strTimeFrame( int intPeriod )
{
switch( intPeriod )
{
case PERIOD_M1: return( "M1" );
case PERIOD_M2: return( "M2" );
case PERIOD_M3: return( "M3" );
case PERIOD_M4: return( "M4" );
case PERIOD_M5: return( "M5" );
case PERIOD_M6: return( "M6" );
case PERIOD_M10: return( "M10" );
case PERIOD_M12: return( "M12" );
case PERIOD_M15: return( "M15" );
case PERIOD_M20: return( "M20" );
case PERIOD_M30: return( "M30" );
case PERIOD_H1: return( "H1" );
case PERIOD_H2: return( "H2" );
case PERIOD_H3: return( "H3" );
case PERIOD_H4: return( "H4" );
case PERIOD_H6: return( "H6" );
case PERIOD_H8: return( "H8" );
case PERIOD_H12: return( "H12" );
case PERIOD_D1: return( "D1" );
case PERIOD_W1: return( "W1" );
case PERIOD_MN1: return( "MN" );
default: return( StringConcatenate( "U", intPeriod ) );
}
}
//+------------------------------------------------------------------------------------+
Comments