//+——————————————————————-+
//| Extreme_Spike.mq4
//| Based on Symphonie_Extreme_Cycle_Indikator
//| !!! this file is created with Tab size 4 and no space indentation
//+——————————————————————-+
#property copyright “”
#property link “”
#property indicator_separate_window
#property indicator_minimum -1.2
#property indicator_maximum +1.2
#property indicator_buffers 5
#property indicator_color1 Red
#property indicator_width1 3
#property indicator_style1 STYLE_SOLID
#property indicator_color2 DodgerBlue
#property indicator_width2 3
#property indicator_style2 STYLE_SOLID
#property indicator_color3 DimGray
#property indicator_width3 0
#property indicator_color4 White
#property indicator_width4 1
#property indicator_style4 STYLE_SOLID
#property indicator_color5 White
#property indicator_width5 2
#property indicator_style5 STYLE_SOLID
#define ALERT_TOP 1
#define ALERT_BOTTOM 2
#define ALERT_STABLE 3
#define LINE_MINOR 1
#define LINE_MAJOR 2
#define LINE_SHADOW 3
#define LINE_STABLE 4
#define LINE_VALUE_UP 1.0
#define LINE_VALUE_FLAT 0.0
#define LINE_VALUE_DOWN -1.0
#define MODE_LOOKING_FOR_BOTTOM 1
#define MODE_LOOKING_FOR_TOP -1
#define MODE_UNDETERMINED 0
//—- input parameters
extern bool NoRepaint = FALSE;
extern double MinorMinExtremeHeightATRs = 2.0;
extern double MajorToMinorHeightRatio = 2.5;
extern int MinorMinExtremeWidth = 2;
extern int MajorMinExtremeWidth = 2;
extern bool AlertMajorBottomEnabled = FALSE;
extern bool AlertMajorTopEnabled = FALSE;
extern bool AlertMinorTopEnabled = FALSE;
extern bool AlertMinorBottomEnabled = FALSE;
extern bool AlertStableEnabled = FALSE;
//—- buffers
double line1[]; // lineMajorUp
double line2[]; // lineMajorDown
double line3[]; // lineShadowUp, lineShadowDown
double line4[]; // lineStableUp, lineStableDown
double line5[]; // lineMinorUp, lineMinorDown
int MinorLowExtremeIdx = 1;
bool MinorFirstLow = TRUE;
int MinorHiExtremeIdx = 1;
bool MinorFirstHigh = TRUE;
int MinorExtremeMode = 0;
double MinorLowExtremePrice;
double MinorHiExtremePrice;
int MajorLowExtremeIdx = 1;
bool MajorFirstLow = TRUE;
int MajorHiExtremeIdx = 1;
bool MajorFirstHigh = TRUE;
int MajorExtremeMode = 0;
double MajorLowExtremePrice;
double MajorHiExtremePrice;
double MinorMinExtremeHeight;
double MajorMinExtremeHeight;
datetime AlertMinorTopIdx;
datetime AlertMinorBottomIdx;
datetime AlertMajorTopIdx;
datetime AlertMajorBottomIdx;
datetime AlertStableIdx;
string periodName;
int BarNumber;
#define RANGE_AVERAGING_PERIOD 250
int init() {
int line = 0;
// order of these calls is important – for example the ‘spike’ line is last – it will be drawn last and therefore will be on top of all other lines
SetIndexStyle ( line, DRAW_HISTOGRAM );
SetIndexBuffer ( line, line1 );
line++;
SetIndexStyle ( line, DRAW_HISTOGRAM );
SetIndexBuffer ( line, line2 );
line++;
SetIndexStyle ( line, DRAW_ARROW );
SetIndexArrow ( line, 108 );
SetIndexBuffer ( line, line3 );
line++;
SetIndexStyle ( line, DRAW_HISTOGRAM );
SetIndexBuffer ( line, line4 );
line++;
SetIndexStyle ( line, DRAW_LINE );
SetIndexBuffer ( line, line5 );
line++;
return (0);
}
int deinit() {
return(0);
}
int start() {
BarNumber = IndicatorCounted();
// ‘BarNumber’ changes from 1 to ‘Bars’, so the array index is [Bars-1 .. 0]
for( ; BarNumber < Bars; ) {
BarNumber++;
processBar();
}
return (0);
}
void processBar() {
switch( BarNumber ) {
case 0:
break;
case 1:
periodName = getPeriodName();
AlertMinorTopIdx = Time[Bars-1];
AlertMinorBottomIdx = Time[Bars-1];
AlertMajorTopIdx = Time[Bars-1];
AlertMajorBottomIdx = Time[Bars-1];
MinorLowExtremePrice = getLow();
MinorHiExtremePrice = getHigh();
MajorLowExtremePrice = getLow();
MajorHiExtremePrice = getHigh();
break;
default:
MinorMinExtremeHeight = average() * MinorMinExtremeHeightATRs;
MajorMinExtremeHeight = MinorMinExtremeHeight * MajorToMinorHeightRatio;
checkForExtremes( MinorLowExtremeIdx, MinorLowExtremePrice, MinorFirstLow,
MinorHiExtremeIdx, MinorHiExtremePrice, MinorFirstHigh,
MinorExtremeMode, MinorMinExtremeHeight, MinorMinExtremeWidth, LINE_MINOR );
checkForExtremes( MajorLowExtremeIdx, MajorLowExtremePrice, MajorFirstLow,
MajorHiExtremeIdx, MajorHiExtremePrice, MajorFirstHigh,
MajorExtremeMode, MajorMinExtremeHeight, MajorMinExtremeWidth, LINE_MAJOR );
break;
}
return (0);
}
void checkForExtremes( int& lowExtremeIdx, double& lowExtremePrice, bool& firstLow,
int& hiExtremeIdx, double& hiExtremePrice, bool& firstHigh,
int& extremeMode, double MinExtremeHeight, int MinExtremeWidth, int lineType ) {
// ———– check for Bottom —————-
if( extremeMode > -1 ) {
if( getLow() < lowExtremePrice ) {
if( !firstLow )
eraseExtreme( lineType, lowExtremeIdx, LINE_VALUE_DOWN ); // to repaint (erase) the spike
lowExtremePrice = getLow(); // set LowestLow to this low (getLow)
lowExtremeIdx = BarNumber; // remember the LL bar number
firstLow = FALSE; // the was a Bottom
}
else
if( getLow() > lowExtremePrice ) { // higher low (getLow) – not necesserally higher than the last bar – could be lower than the last bar, but still higher than the bottom
// there was bottom (lower low then higher low) – final or intermediate
drawExtreme( lineType, lowExtremeIdx, LINE_VALUE_DOWN ); // update LowestLow bar with the spike DOWN and mark it as unstable
alert( ALERT_BOTTOM, lineType, lowExtremeIdx );
firstLow = FALSE;
if( ((getLow() – lowExtremePrice) >= MinExtremeHeight) // the bottom was distinct enough (difference between it and price is big enough)
&& ((BarNumber – lowExtremeIdx) >= MinExtremeWidth) ) { // and the bottom was long enough ago in the past (there was no another bottom since)
extremeMode = -1; // set flags to start looking for top
hiExtremePrice = getHigh();
hiExtremeIdx = BarNumber;
firstHigh = TRUE;
firstLow = TRUE;
if( NoRepaint ) // only draw extreme when it is not going to be repainted (WILL in troduce a lag)
draw( lineType, lowExtremeIdx, LINE_VALUE_DOWN );
if( drawStableLine( lineType, lowExtremeIdx, LINE_VALUE_FLAT ) ) // this spike will not repaint
alert( ALERT_STABLE, lineType, lowExtremeIdx );
}
}
}
// ———– check for Top —————-
if( extremeMode < 1 ) { // extremeMode could have been MinExtremeHeighted in the code above so can’t really put “Else” here; initial goes here as well (0)
if( getHigh() > hiExtremePrice ) {
if( !firstHigh )
eraseExtreme( lineType, hiExtremeIdx, LINE_VALUE_UP ); // to repaint (erase) the spike
hiExtremePrice = getHigh();
hiExtremeIdx = BarNumber;
firstHigh = FALSE;
}
else
if( getHigh() < hiExtremePrice ) {
drawExtreme( lineType, hiExtremeIdx, LINE_VALUE_UP );
alert( ALERT_TOP, lineType, hiExtremeIdx );
firstHigh = FALSE;
if( ((hiExtremePrice – getHigh()) >= MinExtremeHeight)
&& ((BarNumber – hiExtremeIdx) >= MinExtremeWidth) ) {
extremeMode = 1;
lowExtremePrice = getLow();
lowExtremeIdx = BarNumber;
firstHigh = TRUE;
firstLow = TRUE;
if( NoRepaint ) // only draw extreme when it is not going to be repainted (WILL in troduce a lag)
draw( lineType, hiExtremeIdx, LINE_VALUE_UP );
if( drawStableLine( lineType, hiExtremeIdx, LINE_VALUE_FLAT ) ) // this spike will not repaint
alert( ALERT_STABLE, lineType, hiExtremeIdx );
}
}
}
draw( lineType, BarNumber, LINE_VALUE_FLAT );
}
void eraseExtreme( int lineType, int barIdx, double value ) {
bool drawShadow = (lineType == LINE_MAJOR) && (
NoRepaint // in non-repainting mode always alert of the possible extreme
|| ((value == LINE_VALUE_UP) && (line1[Bars-barIdx] != 0))
|| ((value == LINE_VALUE_DOWN) && (line2[Bars-barIdx] != 0))
);
drawExtreme( lineType, barIdx, LINE_VALUE_FLAT );
if( drawShadow )
draw( LINE_SHADOW, barIdx, value );
}
void drawExtreme( int lineType, int barIdx, double value ) {
if( !NoRepaint ) { // only draw extreme when it is not going to be repainted (WILL in troduce a lag)
draw( lineType, barIdx, value );
drawStableLine( lineType, barIdx, value );
}
}
bool drawStableLine( int lineType, int barIdx, double value ) {
if( lineType == LINE_MAJOR )
return (FALSE);
draw( LINE_STABLE, barIdx, value );
return (TRUE);
}
void draw( int lineType, int barIdx, double value ) {
switch( lineType ) {
case LINE_MAJOR:
updateLine( line1, line2, barIdx, value );
break;
case LINE_MINOR:
updateLine( line5, line5, barIdx, value );
break;
case LINE_SHADOW:
updateLine( line3, line3, barIdx, value );
break;
case LINE_STABLE:
updateLine( line4, line4, barIdx, value );
break;
}
}
void updateLine( double& lineUp[], double& lineDown[], int barIdx, double value ) {
if( (value == LINE_VALUE_FLAT) || (value == LINE_VALUE_UP) )
lineUp[ Bars-barIdx ] = value;
if( (value == LINE_VALUE_FLAT) || (value == LINE_VALUE_DOWN) )
lineDown[ Bars-barIdx ] = value;
}
double average() {
// original code uses 250-bar SMA of the simple range (high-low)
return (iATR( NULL, 0, RANGE_AVERAGING_PERIOD, 0 ));
}
double getLow() {
return (Close[ Bars-BarNumber ]);
}
double getHigh() {
return (Close[ Bars-BarNumber ]);
}
void alert( int alertType, int lineType, int barIdx ) {
datetime barTime = Time[Bars-barIdx];
switch( alertType ) {
case ALERT_TOP:
switch( lineType ) {
case LINE_MAJOR:
if( AlertMajorTopEnabled && (barTime != AlertMajorTopIdx) ) {
Alert( Symbol(), ” “, periodName, “: Major Top Detected” );
AlertMajorTopIdx = barTime;
}
break;
case LINE_MINOR:
if( AlertMinorTopEnabled && (barTime != AlertMinorTopIdx) ) {
Alert( Symbol(), ” “, periodName, “: Minor Top Detected” );
AlertMinorTopIdx = barTime;
}
break;
}
break;
case ALERT_BOTTOM:
switch( lineType ) {
case LINE_MAJOR:
if( AlertMajorBottomEnabled && (barTime != AlertMajorBottomIdx) ) {
Alert( Symbol(), ” “, periodName, “: Major Bottom Detected” );
AlertMajorBottomIdx = barTime;
}
break;
case LINE_MINOR:
if( AlertMinorBottomEnabled && (barTime != AlertMinorBottomIdx) ) {
Alert( Symbol(), ” “, periodName, “: Minor Bottom Detected” );
AlertMinorBottomIdx = barTime;
}
break;
}
break;
case ALERT_STABLE:
if( AlertStableEnabled && (barTime != AlertStableIdx) ) {
Alert( Symbol(), ” “, periodName, “: Latest extreme will not repaint anymore” );
AlertStableIdx = barTime;
}
break;
}
}
string getPeriodName() {
switch( Period() ) {
case PERIOD_M1:
return (“M1”);
case PERIOD_M5:
return (“M5”);
case PERIOD_M15:
return (“M15”);
case PERIOD_M30:
return (“M30”);
case PERIOD_H1:
return (“H1”);
case PERIOD_H4:
return (“H4”);
case PERIOD_D1:
return (“D1”);
case PERIOD_W1:
return (“W1”);
case PERIOD_MN1:
return (“MN1”);
}
}
相关资源
暂无评论...