This script is designed to identify and visualize "ZigZag" patterns on a trading chart. A ZigZag is a common technical analysis tool that filters out minor price fluctuations to highlight the significant peaks (highs) and valleys (lows) of a market trend.
Core Logic and Functionality
1. Dynamic Trend Tracking The script monitors price movements in real-time to determine whether the current market direction is moving upward or downward. Instead of showing every tiny movement, it waits for the price to reach specific thresholds before confirming a new "peak" or "valley."
2. Price Reference Options The logic allows for two different ways to interpret price data:
- High/Low Mode: By default, it looks at the absolute highest and lowest prices reached during a specific timeframe.
- Close Price Mode: When enabled, the script ignores the "wicks" (the extremes) and only considers the actual closing price of each candle to determine trend changes.
3. Smart Detection Rules The indicator uses a three-layered logic to decide when to draw a new line:
- Extension: If the price continues to move in the current direction (higher highs or lower lows), the script updates the current peak/valley point to the newest extreme.
- Minimum Movement (MinPoints): To prevent the chart from becoming cluttered with tiny wobbles, it requires a minimum amount of price movement before it will recognize a trend change.
- Forceful Movement (ForcePoints): This acts as a secondary trigger; if the price moves significantly enough in the opposite direction (regardless of other ratios), the script will "force" a new turn in the ZigZag line.
- Proportional Ratio (MinRatio): The script calculates a percentage-based movement. It looks for a reversal that is significant enough relative to the previous trend's size, ensuring the turns captured are meaningful and not just random noise.
4. Historical Accuracy and Stability One of the key features of this specific logic is its commitment to stability. It is designed to be "non-redrawing," meaning it seeks to establish points based on solid price action rather than constantly shifting past lines as new data comes in.
5. Initialization & Calibration Upon starting, the script scans back through the chart history to find the most recent established ZigZag points. This ensures that when you apply it to a live chart, the lines connect seamlessly from the existing historical data rather than starting abruptly from the current moment.
Summary for the User
In simple terms, this tool acts as a "filter" for market noise. It cleans up the visual clutter of a price chart by connecting only the most important turning points. By adjusting the MinPoints, ForcePoints, and MinRatio settings, you can control how "sensitive" the indicator is—choosing whether you want to see every small ripple in the market or only the major structural shifts.
//+------------------------------------------------------------------+
//| ZZ_Orlova.mq4 |
//| Denis Orlov, http://denis-or-love.narod.ru |
//| http://denis-or-love.narod.ru |
/*
ZigZag Îðëîâà
ÇèãÇàã ñ ïðîñòûì, ïîíÿòíûì è åñòåñòâåííûì ïðèíöèïîì ðàáîòû. Ïî öåíàì çàêðûòèÿ. Áåç ïåðåðèñîâêè.
Ïîäðîáíî: http://codebase.mql4.com/7277
ZigZag of Orlov
Zigzag with a simple, clear and natural principle of work. By the Close prices. Without redrawing.
In detail: http://codebase.mql4.com/7278
*/
//+------------------------------------------------------------------+
#property copyright "Denis Orlov, http://denis-or-love.narod.ru"
#property link "http://denis-or-love.narod.ru"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_width1 2
//---- input parameters
extern double MinRatio=0.33;
extern int MinPoints=20;
extern int ForcePoints=50;
extern bool ByClose=False;
extern int History=5000;
//---- buffers
double ZZ_Orlova[];
double LastUp;
double LastDn;
bool LastIsUp;
datetime LastPicTime=0;
int Zbar[3]; //íîìåð áàðà ñ ïåðåãèáîì
double Zval[3]; //çíà÷åíèå çèãçàãà â òî÷êå ïåðåãèáà Zval[1] - â òî÷êå 1 è òä.
int ZObar[6]; //íîìåð áàðà ñ ïåðåãèáîì
double ZOval[6]; //çíà÷åíèå çèãçàãà â òî÷êå ïåðåãèáà Zval[1] - â òî÷êå 1 è òä.
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0,DRAW_SECTION);
SetIndexBuffer(0,ZZ_Orlova);
SetIndexEmptyValue(0,0.0);
//----
if(ForcePoints<MinPoints) ForcePoints=MinPoints;
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
if(ByClose)
{
static datetime perB;
if (perB== Time[0]) return(0); // îäèí ðàç â áàð
perB = Time[0];
}
double upPrice, dnPrice;
int limit;
int counted_bars=IndicatorCounted();
//---- ïîñëåäíèé ïîñ÷èòàííûé áàð áóäåò ïåðåñ÷èòàí
// if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars-1;
if (History>0 && limit>History)
limit=History;
int fstBar=0; if(ByClose)fstBar=1;
for(int i =limit; i>=fstBar; i--)
{
if (LastPicTime==0)//íàõîäèì ñàìûå ïåðâûå òî÷êè ïî ñò ÇÇ, ïðîñòî ÷òîáû íà÷àòü...
{
FindZigZag(i, 3);
if(Zval[0]==Low[Zbar[0]])
{
LastIsUp=False;
LastUp=Zval[1]; LastDn=Zval[0];
}
else
{
LastIsUp=True;
LastUp=Zval[0]; LastDn=Zval[1];
}
//LastIsUp=Zval[1]==High[Zbar[1]];
ZZ_Orlova[Zbar[1]]=Zval[1];
ZZ_Orlova[Zbar[0]]=Zval[0];
LastPicTime=Time[Zbar[0]]; //Alert("ðàññòàâèëè!");
// continue;
}
int LastBar=iBarShift(NULL,0,LastPicTime);//èíäåêñ(áàð) ïîñëåäíåãî ïèêà
if(ByClose)//îïðåäåëÿåì ðåæèì öåíû ïî ýêñòðåìóìàì èëè ïî çàêðûòèþ
{
upPrice=Close[i]; dnPrice=Close[i];
}
else {upPrice=High[i]; dnPrice=Low[i]; }
//----------------------------
if(LastIsUp)
{
if(upPrice>=LastUp)
{
LastUp=upPrice;
ZZ_Orlova[LastBar]=0.0;
ZZ_Orlova[i]=upPrice;
LastPicTime=Time[i];
}
else
if(
(dnPrice<=LastUp-(LastUp-LastDn)*MinRatio
&& (LastUp-dnPrice)/Point>=MinPoints
)
|| (LastUp-dnPrice)/Point>=ForcePoints
)
{
LastDn=dnPrice;
LastIsUp=False;
ZZ_Orlova[i]=dnPrice;
LastPicTime=Time[i];
}
} //if(LastIsUp)
else
if(!LastIsUp)
{
if(dnPrice<=LastDn)
{
LastDn=dnPrice;
ZZ_Orlova[LastBar]=0.0;
ZZ_Orlova[i]=dnPrice;
LastPicTime=Time[i];
}
else
if(
(upPrice>=LastDn+(LastUp-LastDn)*MinRatio
&& (upPrice-LastDn)/Point>=MinPoints
)
|| (upPrice-LastDn)/Point>=ForcePoints
)
{
LastUp=upPrice;
LastIsUp=True;
ZZ_Orlova[i]=upPrice;
LastPicTime=Time[i];
}
}// if(!LastIsUp)
}
//----
return(0);
}
//+------------------------------------------------------------------+
datetime FindZigZag(int bar, int nP )
{
int ExtDepth=12;
int ExtDeviation=5;
int ExtBackstep=3;
int n; datetime res;
for(int i=bar;i<Bars;i++)
{
double zz=iCustom(NULL,0,"ZigZag",ExtDepth,ExtDeviation,ExtBackstep,0,i);
if(zz!=0 && zz!=EMPTY_VALUE)
{
Zbar[n]=i;
Zval[n]=zz;
if(n==1) res=Time[Zbar[n]];//iTime(NULL, 0 , Zbar[n]);
n++;
if(n>=nP)break;
}
}
return(res);
}
//+------------------------------------------------------------------+
int FindZZO(int bar, int nP )
{
int n; datetime res;
for(int i=bar;i<Bars;i++)
{
double zz=ZZ_Orlova[i];
if(zz!=0 && zz!=EMPTY_VALUE)
{
ZObar[n]=i;
ZOval[n]=zz;
n++;
if(n>=nP)break;
}
}
return(n);
}
//+------------------------------------------------------------------+
Comments