Zigzag_with_line_at_lows_and_line_at_highs
Download scriptThis script is designed to visualize significant price movements on a trading chart by identifying key "peaks" (highs) and "valleys" (lows). It automates the process of recognizing these turning points to help traders see the overall structure of the market trend.
Core Functionality
The tool operates by scanning historical price data to filter out minor market noise, focusing instead on substantial price shifts. It uses three primary parameters to determine how it identifies these points:
- Depth: Defines the look-back window used to find high and low prices.
- Deviation: Sets a minimum threshold for price movement; if a move is smaller than this value, the script ignores it as "noise."
- Backstep: Ensures that the identified points are distinct and not clustered too closely together in time.
Logic Workflow
The script processes the market data through several logical layers:
1. Identification of Candidates First, the script sweeps through the price history to identify every potential high and low point based on the Depth and Deviation settings. It creates a "map" of these points, ensuring that only significant extremes are recorded.
2. Filtering and Refinement Not every high or low is a valid turning point. The script performs a refinement process where it checks "Backstep" values. If two peaks or valleys occur too close to one another, the script discards the lesser one, ensuring that only the most prominent price extremes remain.
3. Trend Connection and Drawing The final stage of the logic determines how to connect these points visually:
- Dynamic Updating: The script actively monitors the current price to see if it breaks a previous "high" or "low." If the price moves significantly past a previously recorded point, the script updates that point to the new extreme.
- Visual Segregation: It separates upward movements (peaks) and downward movements (valleys) into distinct visual categories. This allows the user to see a continuous line representing the primary "ZigZag" of the market, while also highlighting specific high-level lines and low-level lines independently.
Summary of User Experience
For the end user, this means the chart will automatically draw lines connecting the most important structural turns in the market. It eliminates the need to manually identify price trends by automatically "snapping" a line from one major peak to the next major valley (or vice versa), providing a clear visual map of market momentum.
//+------------------------------------------------------------------+
//| Zigzag_with_line_at_lows_and_line_at_highs.mq4 |
//| Copyright © 2013, deVries |
//| http://forum.mql4.com/54660 |
//| |
//| Now the Highs (buffer4) of ZigZag are also connected with a line |
//| and the Lows (buffer5) of ZigZag are connected with a line |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, deVries"
#property link "http://forum.mql4.com/54660"
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 Red //ZigZag Buffer
#property indicator_width1 3
#property indicator_color2 Green
#property indicator_color3 Yellow
#property indicator_color4 Magenta //ZigZag High
#property indicator_width4 3
#property indicator_color5 LightSkyBlue //ZigZag Low
#property indicator_width5 3
//---- indicator parameters
extern int ExtDepth=12;
extern int ExtDeviation=5;
extern int ExtBackstep=3;
//---- indicator buffers
double ZigzagBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
double UPBuffer[];
double DNBuffer[];
int level=3; // recounting's depth
bool downloadhistory=false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(5);
//---- drawing settings
SetIndexStyle(0,DRAW_SECTION);
SetIndexStyle(1,DRAW_SECTION);
SetIndexStyle(2,DRAW_SECTION);
SetIndexStyle(3,DRAW_SECTION);
SetIndexStyle(4,DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0,ZigzagBuffer);
SetIndexBuffer(1,HighMapBuffer);
SetIndexBuffer(2,LowMapBuffer);
SetIndexBuffer(3,UPBuffer);
SetIndexBuffer(4,DNBuffer);
SetIndexEmptyValue(0,0.0);
SetIndexEmptyValue(1,0.0);
SetIndexEmptyValue(2,0.0);
SetIndexEmptyValue(3,0.0);
SetIndexEmptyValue(4,0.0);
//---- indicator short name
IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+","+ExtBackstep+")");
//---- initialization done
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
int i, counted_bars = IndicatorCounted();
int limit,counterZ,whatlookfor;
int shift,back,lasthighpos,lastlowpos;
double val,res;
double curlow,curhigh,lasthigh,lastlow;
if (counted_bars==0 && downloadhistory) // history was downloaded
{
ArrayInitialize(ZigzagBuffer,0.0);
ArrayInitialize(HighMapBuffer,0.0);
ArrayInitialize(LowMapBuffer,0.0);
ArrayInitialize(UPBuffer,0.0);
ArrayInitialize(DNBuffer,0.0);
}
if (counted_bars==0)
{
limit=Bars-ExtDepth;
downloadhistory=true;
}
if (counted_bars>0)
{
while (counterZ<level && i<100)
{
res=ZigzagBuffer[i];
if (res!=0) counterZ++;
i++;
}
i--;
limit=i;
if (LowMapBuffer[i]!=0)
{
curlow=LowMapBuffer[i];
whatlookfor=1;
}
else
{
curhigh=HighMapBuffer[i];
whatlookfor=-1;
}
for (i=limit-1;i>=0;i--)
{
ZigzagBuffer[i]=0.0;
LowMapBuffer[i]=0.0;
HighMapBuffer[i]=0.0;
UPBuffer[i]=0.0;
DNBuffer[i]=0.0;
}
}
for(shift=limit; shift>=0; shift--)
{
val=Low[iLowest(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=LowMapBuffer[shift+back];
if((res!=0)&&(res>val)) LowMapBuffer[shift+back]=0.0;
}
}
}
if (Low[shift]==val)
LowMapBuffer[shift]=val;else LowMapBuffer[shift]=0.0;
//--- high
val=High[iHighest(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=HighMapBuffer[shift+back];
if((res!=0)&&(res<val)) HighMapBuffer[shift+back]=0.0;
}
}
}
if (High[shift]==val) HighMapBuffer[shift]=val; else HighMapBuffer[shift]=0.0;
}
// final cutting
if (whatlookfor==0)
{
lastlow=0;
lasthigh=0;
}
else
{
lastlow=curlow;
lasthigh=curhigh;
}
for (shift=limit;shift>=0;shift--)
{
res=0.0;
switch(whatlookfor)
{
case 0: // look for peak or lawn
if (lastlow==0 && lasthigh==0)
{
if (HighMapBuffer[shift]!=0)
{
lasthigh=High[shift];
lasthighpos=shift;
whatlookfor=-1;
ZigzagBuffer[shift]=lasthigh;
UPBuffer[shift]=lasthigh;
res=1;
}
if (LowMapBuffer[shift]!=0)
{
lastlow=Low[shift];
lastlowpos=shift;
whatlookfor=1;
ZigzagBuffer[shift]=lastlow;
DNBuffer[shift]=lastlow;
res=1;
}
}
break;
case 1: // look for peak
if (LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)
{
ZigzagBuffer[lastlowpos]=0.0;
DNBuffer[lastlowpos]=0.0;
lastlowpos=shift;
lastlow=LowMapBuffer[shift];
ZigzagBuffer[shift]=lastlow;
DNBuffer[shift]=lastlow;
res=1;
}
if (HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
{
lasthigh=HighMapBuffer[shift];
lasthighpos=shift;
ZigzagBuffer[shift]=lasthigh;
UPBuffer[shift]=lasthigh;
whatlookfor=-1;
res=1;
}
break;
case -1: // look for lawn
if (HighMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh && LowMapBuffer[shift]==0.0)
{
ZigzagBuffer[lasthighpos]=0.0;
UPBuffer[lasthighpos]=0.0;
lasthighpos=shift;
lasthigh=HighMapBuffer[shift];
ZigzagBuffer[shift]=lasthigh;
UPBuffer[shift]=lasthigh;
}
if (LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
{
lastlow=LowMapBuffer[shift];
lastlowpos=shift;
ZigzagBuffer[shift]=lastlow;
DNBuffer[shift]=lastlow;
whatlookfor=1;
}
break;
default: return;
}
}
return(0);
}
//+------------------------------------------------------------------+
Comments