ZigZag_R_
Download scriptThis script provides an optimized version of the classic ZigZag indicator, a popular tool used by traders to filter out "market noise" and identify significant price structural points like peaks and valleys.
Core Logic and Performance
The primary purpose of this specific version is efficiency. In standard versions of the ZigZag, calculating historical data can be extremely slow and taxing on computer resources, which often makes it difficult to test trading strategies effectively.
This script solves that problem by intelligently managing how much data it recalculates:
- Initial Load: The first time you run the indicator, it processes the entire available price history to build a complete visual map.
- Real-Time Updates: Once the initial load is finished, the script does not re-scan everything. Instead, it identifies the most recent major price movements and only recalculates a specific "depth" of data (defined by the
levelvariable). This allows the indicator to provide real-time updates while remaining lightweight and fast.
How it Identifies Price Points
The script scans the market history to find significant highs and lows based on three main criteria defined by the user:
- Depth: How far back the script looks to find a previous price point.
- Deviation: The minimum price change required to consider a new movement "significant." If the price fluctuates slightly, the script ignores it; if it moves beyond this threshold, it marks it as a potential point.
- Backstep: A mechanism that ensures the identified points are distinct and not clustered too closely together, helping to smooth out the resulting lines.
Visual Filtering
To ensure the chart remains clean, the script includes a specific cleaning logic:
- Removing "Floating" Points: It automatically filters out erratic price points that might appear on smaller timeframes (like 1-minute charts) which could clutter the visual display.
- Dynamic Updating: As new prices come in, the script can "delete" a preliminary peak if a higher one is formed before the movement is finalized, ensuring that the lines always represent the most accurate trend of the market.
Summary for the User
In simple terms, this tool creates a clear, "zigzag" path of price action by ignoring minor fluctuations. It is designed to be much faster than standard versions because it smartly remembers what it has already calculated and only updates the necessary parts of the chart as new price data arrives.
//+------------------------------------------------------------------+
//| Zigzag_R_.mq4 |
//| Copyright © 2005-2007, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
/* Ýòîò âàðèàíò Zigzag'à ÿâëÿåòñÿ ïðîñòîé îïòèìèçàöèåé ñòàðîãî |
âàðèàíòà, ê êîòîðîìó ïðèâûêëè ñîòíè òûñÿ÷ ïîëüçîâàòåëåé Metatrader |
åùå ñ âåðñèè ÌÒ3 (ÿçûê MQL2). |
Èñïîëüçîâàíèå èíäèêàòîðà áåç îïòèìèçàöèè äåëàëî ñëîæíûì è äîëãèì |
òåñòèðîâàíèå ñîâåòíèêîâ, èñïîëüçóþùèõ çíà÷åíèÿ ïîëüçîâàòåëüñêîãî |
èíäèêàòîðà Zigzag. Îïòèìèçèðîâàííûé âàðèàíò ðåøàåò äàííóþ ïðîáëåìó. |
 ïåðâûé ðàç, ïðè ïåðâîì çàïóñêå èíäèêàòîð ïðîñ÷èòûâàåò âñþ èñòîðèþ. |
Ïðè ïîñëåäóþùèõ âûçîâàõ ïðè ïðèõîäå íîâûõ òèêîâ â ðåàëüíîì âðåìåíè |
èëè ïðè èñïîëüçîâàíèè â òåñòåðå íàõîäèòñÿ òðåòèé ýêñòðåìóì îò |
òåêóùåãî âðåìåíè âãëóáü èñòîðèè è ïåðåñ÷åò íà÷èíàåòñÿ ñ íåãî. Åñëè |
Âû õîòèòå íà÷èíàòü ïåðåñ÷åò ñî âòîðîãî ýêñòðåìóìà, ïîìåíÿéòå |
çíà÷åíèå ïåðåìåííîé level, êîòîðàÿ îïðåäåëÿåò ãëóáèíó ïåðåñ÷åòà: |
int level = 3; // recounting's depth |
Âñå íàçâàíèÿ âíåøíèõ ïåðåìåííûõ ñîõðàíåíû èç ñîîáðàæåíèé |
ïðååìñòâåííîñòè. Êðîìå òîãî, óáðàíû ýêñòðåìóìû, âèñÿùèå â âîçäóõå, |
êîòîðûå îáðàçîâûâàëèñü íà ìèíóòíûõ òàéì-ôðåéìàõ. |
//+------------------------------------------------------------------+
*/
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
//----
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
//---- indicator parameters
extern int ExtDepth = 12;
extern int ExtDeviation = 5;
extern int ExtBackstep =3;
//---- indicator buffers
double ZigzagBuffer[];
double HighMapBuffer[];
double LowMapBuffer[];
// recounting's depth
int level = 3;
bool downloadhistory = false;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
IndicatorBuffers(3);
//---- drawing settings
SetIndexStyle(0, DRAW_SECTION);
//---- indicator buffers mapping
SetIndexBuffer(0, ZigzagBuffer);
SetIndexBuffer(1, HighMapBuffer);
SetIndexBuffer(2, LowMapBuffer);
SetIndexEmptyValue(0, 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;
// history was downloaded
if(counted_bars == 0 && downloadhistory)
{
ArrayInitialize(ZigzagBuffer, 0.0);
ArrayInitialize(HighMapBuffer, 0.0);
ArrayInitialize(LowMapBuffer, 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;
}
}
//----
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)
{
// look for peak or lawn
case 0: if(lastlow == 0 && lasthigh == 0)
{
if(HighMapBuffer[shift] != 0)
{
lasthigh = High[shift];
lasthighpos = shift;
whatlookfor = -1;
ZigzagBuffer[shift] = lasthigh;
res = 1;
}
if(LowMapBuffer[shift] != 0)
{
lastlow = Low[shift];
lastlowpos = shift;
whatlookfor = 1;
ZigzagBuffer[shift] = lastlow;
res = 1;
}
}
break;
// look for peak
case 1: if(LowMapBuffer[shift] != 0.0 && LowMapBuffer[shift] < lastlow &&
HighMapBuffer[shift] == 0.0)
{
ZigzagBuffer[lastlowpos]=0.0;
lastlowpos=shift;
lastlow=LowMapBuffer[shift];
ZigzagBuffer[shift]=lastlow;
res=1;
}
if(HighMapBuffer[shift] != 0.0 && LowMapBuffer[shift] == 0.0)
{
lasthigh = HighMapBuffer[shift];
lasthighpos = shift;
ZigzagBuffer[shift] = lasthigh;
whatlookfor = -1;
res = 1;
}
break;
// look for lawn
case -1: if(HighMapBuffer[shift] != 0.0 &&
HighMapBuffer[shift] > lasthigh &&
LowMapBuffer[shift] == 0.0)
{
ZigzagBuffer[lasthighpos] = 0.0;
lasthighpos = shift;
lasthigh = HighMapBuffer[shift];
ZigzagBuffer[shift] = lasthigh;
}
if(LowMapBuffer[shift] != 0.0 && HighMapBuffer[shift] == 0.0)
{
lastlow = LowMapBuffer[shift];
lastlowpos = shift;
ZigzagBuffer[shift] = lastlow;
whatlookfor = 1;
}
break;
default: return;
}
}
//----
return(0);
}
//+------------------------------------------------------------------+
Comments