forked from 93744399/FMIC
529 lines
19 KiB
MQL4
529 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 ) );
| |||
}
| |||
}
| |||
| |||
| |||
//+------------------------------------------------------------------------------------+
|