ZigZag_Pointer_alert_email
Download scriptThe ZigZag Pointer is a specialized technical analysis tool designed to simplify market price action by identifying significant structural turning points—specifically the major "peaks" and "valleys" in a financial chart. Instead of showing every minor fluctuation, this script filters out market noise to highlight the primary trends and reversals.
Core Logic and Operation
The script operates through a multi-stage filtering process to ensure that only meaningful price movements are plotted:
1. Identification of Extremes The tool constantly scans historical price data within a specific "depth" (a user-defined lookback period). It looks for the highest highs and lowest lows during these intervals. By using these parameters, the script ignores minor price jitters and focuses on substantial movements.
2. Deviation and Backstep Filtering To prevent the tool from marking every tiny move as a turn, it employs two critical logic gates:
- Deviation: It ensures that a new peak or valley is significant enough in distance from the previous one to be considered "important." If a move is too small, the script ignores it.
- Backstep: This acts as a refinement layer. It checks recently identified points and ensures that if a new, more extreme high or low appears very close to an existing one, the older, less significant point is removed in favor of the more prominent one.
3. Trend Verification (The "Final Cutting" Process) Once the initial highs and lows are found, the script performs a secondary logical sweep. It compares consecutive peaks and valleys to ensure they alternate correctly. For example, it confirms that a "High" must be followed by a "Low" before another "High" can be confirmed. This prevents the chart from showing two consecutive highs or lows in a row, ensuring a clean, zigzagging path that accurately represents market structure.
4. Real-Time Alerts and Notifications The script is equipped with an intelligent monitoring system. It tracks the positions of the most recent structural turns (the current "zigzag" points). If the market dynamics shift such that a new structural turn is confirmed in the opposite direction, the script triggers a notification.
Depending on your settings, these alerts can:
- Pop up as a visual alert on your trading platform.
- Be sent directly to your email, providing you with an immediate notification of a "Possible change in direction" without you needing to watch the screen constantly.
Summary for the User
In essence, this tool acts as a structural filter. It cleans up the "messy" price data and draws a clear path of significant highs and lows. By highlighting these major pivot points, it allows traders to see the underlying trend more clearly and receive automated notifications when the market structure potentially shifts from one direction to another.
//+------------------------------------------------------------------+
//| ZigZag Pointer.mq4 |
//| zigzag modified by Dr. Gaines |
//| dr_richard_gaines@yahoo.com |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "dr_richard_gaines"
#property link "http://www.metaquotes.net/"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_width1 1
#property indicator_color2 Red
#property indicator_width2 1
//---- indicator parameters
extern int ExtDepth=100;
extern int ExtDeviation=75;
extern int ExtBackstep=15;
extern bool SendAnEmail=false;
//---- indicator buffers
double ExtMapBuffer[];
double ExtMapBuffer2[];
int OldLastZigZag, OldPreviousZigZag;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(2);
//---- drawing settings
SetIndexStyle(0,DRAW_ARROW);
SetIndexArrow(0, 233);
SetIndexStyle(1,DRAW_ARROW);
SetIndexArrow(1, 234);
//---- indicator buffers mapping
SetIndexBuffer(0,ExtMapBuffer);
SetIndexBuffer(1,ExtMapBuffer2);
SetIndexEmptyValue(0,0.0);
//---- indicator short name
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int shift, back,lasthighpos,lastlowpos;
double val,res;
double curlow,curhigh,lasthigh,lastlow;
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
val=Low[Lowest(NULL,0,MODE_LOW,ExtDepth,shift)];
if(val==lastlow) val=0.0;
else
{
lastlow=val;
if((Low[shift]-val)>(ExtDeviation*Point)) val=0.0;
else
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer[shift+back];
if((res!=0)&&(res>val)) ExtMapBuffer[shift+back]=0.0;
}
}
}
ExtMapBuffer[shift]=val;
//--- high
val=High[Highest(NULL,0,MODE_HIGH,ExtDepth,shift)];
if(val==lasthigh) val=0.0;
else
{
lasthigh=val;
if((val-High[shift])>(ExtDeviation*Point)) val=0.0;
else
{
for(back=1; back<=ExtBackstep; back++)
{
res=ExtMapBuffer2[shift+back];
if((res!=0)&&(res<val)) ExtMapBuffer2[shift+back]=0.0;
}
}
}
ExtMapBuffer2[shift]=val;
}
// final cutting
lasthigh=-1; lasthighpos=-1;
lastlow=-1; lastlowpos=-1;
for(shift=Bars-ExtDepth; shift>=0; shift--)
{
curlow=ExtMapBuffer[shift];
curhigh=ExtMapBuffer2[shift];
if((curlow==0)&&(curhigh==0)) continue;
//---
if(curhigh!=0)
{
if(lasthigh>0)
{
if(lasthigh<curhigh) ExtMapBuffer2[lasthighpos]=0;
else ExtMapBuffer2[shift]=0;
}
//---
if(lasthigh<curhigh || lasthigh<0)
{
lasthigh=curhigh;
lasthighpos=shift;
}
lastlow=-1;
}
//----
if(curlow!=0)
{
if(lastlow>0)
{
if(lastlow>curlow) ExtMapBuffer[lastlowpos]=0;
else ExtMapBuffer[shift]=0;
}
//---
if((curlow<lastlow)||(lastlow<0))
{
lastlow=curlow;
lastlowpos=shift;
}
lasthigh=-1;
}
}
for(shift=Bars-1; shift>=0; shift--)
{
if(shift>=Bars-ExtDepth) ExtMapBuffer[shift]=0.0;
else
{
res=ExtMapBuffer2[shift];
if(res!=0.0) ExtMapBuffer2[shift]=res;
}
int i=0;
int LastZigZag, PreviousZigZag;
int h=0;
while ( ExtMapBuffer[h]==0 && ExtMapBuffer2[h]==0) {
h++;
}
LastZigZag=h;
h++;
while(ExtMapBuffer[h]==0 && ExtMapBuffer2[h]==0) {
h++;
}
PreviousZigZag=h;
if (OldLastZigZag!=LastZigZag || OldPreviousZigZag!=PreviousZigZag) {
if(OldLastZigZag>LastZigZag) {
Alert("Possible change in direction... (M",Period()," ",Symbol(),")");
if (SendAnEmail) SendMail("Possible change in direction", "(M" + Period() + " " + Symbol() + ")");
}
OldLastZigZag=LastZigZag;
OldPreviousZigZag=PreviousZigZag;
//ObjectDelete("Fibo");
//ObjectCreate("Fibo", OBJ_FIBO, 0, Time[PreviousZigZag], ExtMapBuffer[LastZigZag], Time[LastZigZag], ExtMapBuffer[PreviousZigZag]);
}
if (OldLastZigZag!=LastZigZag || OldPreviousZigZag!=PreviousZigZag) {
if(OldLastZigZag<LastZigZag) {
Alert("Possible change in direction... (M",Period()," ",Symbol(),")");
if (SendAnEmail) SendMail("Possible change in direction", "(M" + Period() + " " + Symbol() + ")");
}
OldLastZigZag=LastZigZag;
OldPreviousZigZag=PreviousZigZag;
//ObjectDelete("Fibo");
//ObjectCreate("Fibo", OBJ_FIBO, 0, Time[PreviousZigZag], ExtMapBuffer[LastZigZag], Time[LastZigZag], ExtMapBuffer[PreviousZigZag]);
}
}
}
//end//
Comments