2 nen: More regarding "options". Now one of the conditions for extremum switching: current low is higher than current low by more than ExtDeviation points (similar for high). The code allows to implement other options quite easily, if necessary. Well, following klot I would like to add that my current interest in the zigzag is caused solely by my interest in your design.
Corrected the source code again - yesterday I found out that the first significant bar rule is sometimes not respected on minutes. To check it, I only had an hour and a half of online time, but it seems that it was a matter of comparing double with zero.
Another bug: Extremes can only be switched at the end of a bar, otherwise there is a difference between real time and history. It is not difficult to fix. I have not corrected the source code in the branch yet - let the new version run on minutes.
On the subject of the peculiarities of different zigzags. The main feature of this zigzag is that everything is done in one pass, the revisiting of historical data is done only when an extremum is fixed, and only for data after that extremum. That is, it must be quite fast. Particulars of drawing will of course depend on the criteria of extremum fixing but various options can easily be implemented here. For example, I have already made variants switching by percentage of a previous move, by departure of High from the minimum (respectively Low from the maximum) and binding the switch to the average bar size.
Here's another problem with the indicator: I found a kink in my zigzag (cursor cross in the picture). The time of the kink corresponds to when the terminal was switched off, the price corresponds to when it was switched back on.
To clarify my suspicions, I inserted the Print in the code:
if (shift<5) Print ("shift=",shift,", Bars=",Bars,", Time[shift]=",TimeToStr(Time[shift],TIME_DATE|TIME_MINUTES),", High[shift]=",High[shift],", Low[shift]=",Low[shift]);
The terminal was then closed and restarted a few minutes later. And here is a fragment of the log:
You can see that at 23:58:23 the history was not pumped yet, and by 23:58:25 the last 1 bar was pumped. And only by 2006.10.31 23:58:26 all intermediate bars were pumped. Question to the developers: is this the normal paging sequence? And if so, what is the point of it? Clearly, it is desirable to have the current price value early. But the planned existence of a hole in the history for some time essentially means a guaranteed failure of indicators for this time. Isn't it safer for the user to postpone the calculation of indicators until the history is completely swapped? Or at least re-initialize them after the full swap?
Klot, interesting option.
If your zigzag variants show interesting results, can I apply them in my development?
Of course you can, I am following the development with interest and I like your work very much.
More regarding "options". Now one of the conditions for extremum switching: current low is higher than current low by more than ExtDeviation points (similar for high). The code allows to implement other options quite easily, if necessary.
Well, following klot I would like to add that my current interest in the zigzag is caused solely by my interest in your design.
Included your zigzag as an external zigzag. As soon as a stable working version appears, I will change it.
//+------------------------------------------------------------------+ //| CZigZag.mq4 | //| Copyright © 2006, Candid | //| likh@yandex.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Candid" #property link "likh@yandex.ru" #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 Navy //---- indicator parameters extern int ExtDepth=12; extern int ExtDeviation=5; //extern int ExtBackstep=3; int shift; double res=0; int i; double CurMax,CurMin; int CurMaxPos,CurMinPos; int CurMaxBar,CurMinBar; double hPoint; double mhPoint; double EDev; int MaxDist,MinDist; bool FirstRun; bool AfterMax,AfterMin; int BarTime; //---- indicator buffers double ZigZag[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- indicators SetIndexStyle(0,DRAW_SECTION); //---- indicator buffers mapping SetIndexBuffer(0,ZigZag); SetIndexEmptyValue(0,0.0); //---- indicator short name IndicatorShortName("ZigZag("+ExtDepth+","+ExtDeviation+")"); FirstRun = true; //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { int counted_bars=IndicatorCounted(); int fBar; if (FirstRun) { hPoint = 0.5*Point; mhPoint = -hPoint; EDev = (ExtDeviation+0.5)*Point; AfterMax = true; AfterMin = true; fBar = Bars-1; CurMax = High[fBar]; CurMaxBar = 1; CurMin = Low[fBar]; CurMinBar = 1; MaxDist = 0; MinDist = 0; BarTime = 0; FirstRun = false; } //---- fBar = Bars-counted_bars-1; if (fBar > Bars-2) fBar = Bars-2; for(shift=fBar; shift>=0; shift--) { if (BarTime!=Time[shift]) { BarTime=Time[shift]; if (res > hPoint ) { MaxDist = Bars-CurMaxBar-shift+1; MinDist = Bars-CurMinBar-shift+1; if ((MaxDist>ExtDepth && MinDist>ExtDepth) || res > EDev) { if (AfterMax) { AfterMax = false; AfterMin = true; CurMaxBar = CurMinBar+1; CurMaxPos = Bars-CurMaxBar; CurMax = High[CurMaxPos]; for (i=CurMaxPos-1;i>=shift;i--) { if (High[i] > CurMax+hPoint) { CurMaxBar = Bars-i; CurMax = High[i]; } } // for (i=CurMaxPos-1;i>=shift;i--) ZigZag[Bars-CurMaxBar] = CurMax; } else { // if (AfterMax) AfterMin = false; AfterMax = true; CurMinBar = CurMaxBar+1; CurMinPos = Bars-CurMinBar; CurMin = Low[CurMinPos]; for (i=CurMinPos-1;i>=shift;i--) { if (Low[i] < CurMin-hPoint) { CurMinBar = Bars-i; CurMin = Low[i]; } } // for (i=CurMinPos-1;i>=shift;i--) ZigZag[Bars-CurMinBar] = CurMin; } // else if (AfterMax) } // if ((MaxDist>ExtDepth && MinDist>ExtDepth) || res > EDev) } // if (res > hPoint ) } // if (BarTime!=Time[0]) if (AfterMax) { res = Low[shift]-CurMin; if (res < mhPoint) { ZigZag[Bars-CurMinBar] = 0; CurMin = Low[shift]; CurMinBar = Bars-shift; ZigZag[Bars-CurMinBar] = CurMin; } // if (res < mhPoint) } // if (AfterMax) if (AfterMin) { res = CurMax-High[shift]; if (res < mhPoint) { ZigZag[Bars-CurMaxBar] = 0; CurMax = High[shift]; CurMaxBar = Bars-shift; ZigZag[Bars-CurMaxBar] = CurMax; } // if (res < mhPoint) } // if (AfterMin) } // for(shift=fBar; shift>=0; shift--) //---- return(0); } //+------------------------------------------------------------------+On the subject of the peculiarities of different zigzags. The main feature of this zigzag is that everything is done in one pass, the revisiting of historical data is done only when an extremum is fixed, and only for data after that extremum. That is, it must be quite fast. Particulars of drawing will of course depend on the criteria of extremum fixing but various options can easily be implemented here. For example, I have already made variants switching by percentage of a previous move, by departure of High from the minimum (respectively Low from the maximum) and binding the switch to the average bar size.
To clarify my suspicions, I inserted the Print in the code:
if (shift<5) Print ("shift=",shift,", Bars=",Bars,", Time[shift]=",TimeToStr(Time[shift],TIME_DATE|TIME_MINUTES),", High[shift]=",High[shift],", Low[shift]=",Low[shift]);The terminal was then closed and restarted a few minutes later. And here is a fragment of the log:
You can see that at 23:58:23 the history was not pumped yet, and by 23:58:25 the last 1 bar was pumped. And only by 2006.10.31 23:58:26 all intermediate bars were pumped.
Question to the developers: is this the normal paging sequence? And if so, what is the point of it? Clearly, it is desirable to have the current price value early. But the planned existence of a hole in the history for some time essentially means a guaranteed failure of indicators for this time. Isn't it safer for the user to postpone the calculation of indicators until the history is completely swapped? Or at least re-initialize them after the full swap?