Ticker ZigZag
Download scriptThis script functions as a specialized "ZigZag" price tracker designed to map out significant price movements and structural pivots in the market. Unlike standard indicators that might rely on simple averages, this tool focuses on capturing key highs and lows based on specific price thresholds, providing a clearer view of market trends and reversals.
Core Logic and Behavior
Price Movement Tracking The script continuously monitors the live "Bid" price (the current selling price). It ignores minor fluctuations and only reacts when the price moves significantly enough to meet a user-defined threshold (the "Stop" value). This ensures that the resulting visual map isn't cluttered with every tiny market twitch, but instead highlights meaningful shifts in momentum.
Trend Identification The indicator operates by identifying whether the current trend is moving upward or downward:
- Upward Trend: The script tracks the highest price reached during a move.
- Downward Trend: The script tracks the lowest price reached during a move.
Dynamic Reversal Logic The most critical logic within this script is its "reversal" trigger. A new trend point is created only when the price moves against the current direction by more than the designated "Stop" distance. For example, if the market is currently in an uptrend and the price drops significantly below the previous high, the script recognizes this as a potential reversal. It then "locks in" the new peak and begins tracking the downward movement.
Historical Data Synchronization Upon initialization, the script performs a deep scan of historical data. It looks back at past price action to reconstruct the sequence of highs and lows. During this process, it intelligently organizes open, high, and low prices to ensure the ZigZag line connects logically across time, providing a continuous and coherent visual history of the market's path.
Visual Representation The resulting output is plotted as a connected line in a separate window on your trading platform. By following this line, traders can easily visualize:
- Major swing highs and lows.
- The "distance" of price retracements.
- The overall structure of the market trend over a specific number of bars.
Key User Controls
- Stop: This acts as the sensitivity filter. A higher value will result in a "smoother" ZigZag with fewer points, while a lower value will capture more frequent, smaller price fluctuations.
- BarsCount: This determines the depth of the history displayed, allowing users to choose how far back they want to see the historical trend map.
// Ticker ZigZag.mq4
// Èíäèêàòîð
#property copyright "mandorr@gmail.com"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Gray
#property indicator_width1 2
#property indicator_style1 0
extern int Stop=100; // Îñòàíîâêà è ðàçâîðîò
extern int BarsCount=1000; // Êîëè÷åñòâî îòîáðàæàåìûõ áàðîâ
double buffer0[];
int bar_size;
int bar_high[];
int bar_low [];
int bar_dir [];
int stop;
int price_prev;
int win_index;
string obj_name;
string win_name;
void init() {
SetIndexBuffer(0,buffer0);
SetIndexStyle (0,DRAW_LINE);
SetIndexLabel(0,"ZigZag");
SetIndexDrawBegin(0,0);
SetIndexEmptyValue(0,0.0);
bar_size=0;
price_prev=0;
stop=MathMax(1,Stop);
win_name="Ticker ZigZag ("+stop+")";
}
void deinit() {
ObjectsDeleteAll(win_index);
}
void start() {
int i, price;
bool reverse;
price=MathRound(Bid/Point);
if (price==0) {return;}
if (price==price_prev) {return;}
price_prev=price;
if (bar_size==0) {
Clean();
Setup();
}
reverse=false;
if ((price>bar_high[0]) && (bar_dir[0]>0)) {
bar_high[0]=price;
}
if ((price<bar_low[0]) && (bar_dir[0]<0)) {
bar_low[0]=price;
}
if ((price>bar_low[0]) && (bar_dir[0]<0)) {
if (price>bar_low[0]+stop) {reverse=true;}
}
if ((price<bar_high[0]) && (bar_dir[0]>0)) {
if (price<bar_high[0]-stop) {reverse=true;}
}
if (reverse) {
bar_size++;
if (bar_size>BarsCount) {bar_size=BarsCount;}
else {
ArrayResize(bar_high,bar_size);
ArrayResize(bar_low ,bar_size);
ArrayResize(bar_dir ,bar_size);
}
for (i=bar_size-1; i>0; i--) {
bar_high[i]=bar_high[i-1];
bar_low [i]=bar_low [i-1];
bar_dir [i]=bar_dir [i-1];
}
if (bar_dir[1]<0) {
bar_high[0]=price;
bar_low [0]=bar_low[1];
bar_dir [0]=1;
}
if (bar_dir[1]>0) {
bar_high[0]=bar_high[1];
bar_low [0]=price;
bar_dir [0]=-1;
}
}
IndicatorShortName(win_name);
win_index=WindowFind(win_name);
obj_name="Win"+win_index+"_Bid";
if (ObjectFind(obj_name)!=win_index) {
ObjectCreate(obj_name,OBJ_HLINE,win_index,Time[0],Bid);
}
ObjectSet(obj_name,OBJPROP_PRICE1,Bid);
ObjectSet(obj_name,OBJPROP_STYLE,DRAW_LINE);
ObjectSet(obj_name,OBJPROP_WIDTH,1);
ObjectSet(obj_name,OBJPROP_COLOR,Silver);
}
// î÷èñòèòü ãðàôèê
void Clean() {
for (int i=0; i<=BarsCount; i++) {
buffer0[i]=0.0;
}
IndicatorShortName(win_name);
win_index=WindowFind(win_name);
ObjectsDeleteAll(win_index);
}
// Èñïîëüçîâàíèå ïîñëåäîâàòåëüíîñòè òèêîâ èç OHL ìèíóòíîãî ãðàôèêà
void Setup() {
int i, j, k, total, value_prev, value[4], box_count;
bool reverse;
double open, high, low, median;
// íà÷àëüíûé áàð
bar_size=1;
ArrayResize(bar_high,1);
ArrayResize(bar_low ,1);
ArrayResize(bar_dir, 1);
total=stop*BarsCount; if (total>iBars(NULL,PERIOD_M1)) {total=iBars(NULL,PERIOD_M1);}
open=iOpen(NULL,PERIOD_M1,total-1);
value[0]=MathRound(open/Point);
bar_high[0]=value[0];
bar_low [0]=value[0];
bar_dir [0]=1;
// Ýìóëÿöèÿ ïîñëåäîâàòåëüíîñòè òèêîâ èç OHL ìèíóòíîãî ãðàôèêà
for (i=total-1; i>=0; i--) {
open=iOpen(NULL,PERIOD_M1,i);
high=iHigh(NULL,PERIOD_M1,i);
low =iLow (NULL,PERIOD_M1,i);
median=0.5*(high+low);
value[0]=MathRound(open/Point);
value[1]=MathRound(high/Point);
value[2]=MathRound(low /Point);
value[3]=0;
if (open<median) {
// Ïîìåíÿòü ïîñëåäîâàòåëüíîñòü ñ OHL íà OLH
value[3]=value[1];
value[1]=value[2];
value[2]=value[3];
}
for (k=0; k<=2; k++) {
if (value[k]==value_prev) {continue;}
value_prev=value[k];
reverse=false;
if ((value[k]>bar_high[0]) && (bar_dir[0]>0)) {
bar_high[0]=value[k];
}
if ((value[k]<bar_low[0]) && (bar_dir[0]<0)) {
bar_low[0]=value[k];
}
if ((value[k]>bar_low[0]) && (bar_dir[0]<0)) {
if (value[k]>bar_low[0]+stop) {reverse=true;}
}
if ((value[k]<bar_high[0]) && (bar_dir[0]>0)) {
if (value[k]<bar_high[0]-stop) {reverse=true;}
}
if (reverse) {
bar_size++;
if (bar_size>BarsCount) {bar_size=BarsCount;}
else {
ArrayResize(bar_high,bar_size);
ArrayResize(bar_low ,bar_size);
ArrayResize(bar_dir ,bar_size);
}
for (j=bar_size-1; j>0; j--) {
bar_high[j]=bar_high[j-1];
bar_low [j]=bar_low [j-1];
bar_dir [j]=bar_dir [j-1];
}
if (bar_dir[1]<0) {
bar_high[0]=value[k];
bar_low [0]=bar_low[1];
bar_dir [0]=1;
}
if (bar_dir[1]>0) {
bar_high[0]=bar_high[1];
bar_low [0]=value[k];
bar_dir [0]=-1;
}
}
}
}
for (i=0; i<bar_size; i++) {
buffer0[i]=0.0;
if (bar_dir[i]>0) {buffer0[i]=bar_high[i]*Point;}
if (bar_dir[i]<0) {buffer0[i]=bar_low [i]*Point;}
}
buffer0[bar_size]=0.0;
RefreshRates();
price_prev=MathRound(Bid/Point);
}
// End
Comments