530 lines
19 KiB
MQL4
530 lines
19 KiB
MQL4
|
//+------------------------------------------------------------------------------------+
|
||
|
#define _NAME_ "ZigZagExtras"
|
||
|
#define _VERSION_ "1.5"
|
||
|
#define _TITLE_ "ZigZagExtras (v"_VERSION_") - MetaTrader 4 Indicator"
|
||
|
#define _ABSTRACT_ "ZigZag Indicator with Extra Features"
|
||
|
#property version _VERSION_
|
||
|
#property copyright "Copyright \x00A9 2022, Fernando M. I. Carreiro"
|
||
|
#property link "https://www.mql5.com/en/users/FMIC"
|
||
|
#property strict
|
||
|
#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
|
||
|
, boolExtraBuffers // Use extra buffers
|
||
|
;
|
||
|
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
|
||
|
boolExtraBuffers = ( boolShowBreakOut || boolAlertOnBreakOut );
|
||
|
if( boolExtraBuffers )
|
||
|
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( boolExtraBuffers ) // 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 = Bars - intDepth
|
||
|
, intCountedBars = IndicatorCounted()
|
||
|
, intCounter, intSearch = _SEARCH_BOTH_
|
||
|
, intLowPosition, intHighPosition
|
||
|
, intShift, intBack
|
||
|
, intIndex
|
||
|
;
|
||
|
double
|
||
|
dblResult, dblValue
|
||
|
, dblCurrentLow = NULL
|
||
|
, dblCurrentHigh = NULL
|
||
|
, dblPreviousLow = NULL
|
||
|
, dblPreviousHigh = NULL
|
||
|
;
|
||
|
|
||
|
if( ( intCountedBars < 0 ) || ( Bars <= intDepth ) )
|
||
|
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 );
|
||
|
if( boolExtraBuffers )
|
||
|
{
|
||
|
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_;
|
||
|
}
|
||
|
|
||
|
if( intLimitBars > 0 )
|
||
|
{
|
||
|
for( intIndex = intLimitBars - 1; intIndex >= 0; intIndex-- )
|
||
|
{
|
||
|
dblArrayZigZag[ intIndex ] = NULL;
|
||
|
dblArrayZigZagLow[ intIndex ] = NULL;
|
||
|
dblArrayZigZagHigh[ intIndex ] = NULL;
|
||
|
if( boolExtraBuffers )
|
||
|
{
|
||
|
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( boolExtraBuffers )
|
||
|
{
|
||
|
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( boolExtraBuffers )
|
||
|
{
|
||
|
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 ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------------------------+
|