Author: Copyright � 2007, MetaQuotes Software Corp.
ZigZag_R_

This 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 level variable). 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:

  1. Depth: How far back the script looks to find a previous price point.
  2. 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.
  3. 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.

Miscellaneous
Implements a curve of type %1
18 Views
0 Downloads
0 Favorites
ZigZag_R_
//+------------------------------------------------------------------+
//|                                                    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