Watch how to download trading robots for free
Find us on Telegram!
Join our fan page
Interesting script?
So post a link to it -
let others appraise it
You liked the script? Try it in the MetaTrader 5 terminal
Indicators

Ideal ZigZag - indicator for MetaTrader 5

Views:
20720
Rating:
(61)
Published:
2012.07.20 14:07
Updated:
2016.11.22 07:32
idealzz.mq5 (7.33 KB) view
idealzzp.mq5 (7.33 KB) view
Need a robot or indicator based on this code? Order it on Freelance Go to Freelance

This is a simple but very fast zigzag.

No suspended or wrong peaks. Peaks retrieval has been time-optimized.

Ideal ZigZag

Advantages:

  1. The most expensive function in calculations is iBarShift. It totally replaces all cycles needed for peaks retrieval. Therefore, it has been replaced by ArrayBSearch. It means that the indicator will be more efficient than its MQL4 equivalent;
  2. All necessary data for each bar is accessible not only in every moment but also available to EA for any moment in history;
  3. No suspended picks;
  4. Efficient method to find peaks without searching the indicator values;
  5. Very fast;
  6. Works correctly at history insertions and when switching timeframes;
  7. Perfect for use in EAs.

Disadvantages:

  1. Memory requirements. ZigZag needs 2 buffers (one is not enough because of lags) for correct drawing, while 5 buffers are used here. In my opinion, this drawback is completely outshined by advantage #6. None of fast ZigZags can correctly process history insertions on two buffers.
  2. Additional lines are available. This is required to make the data visible to an Expert Advisor. These lines should never be visible.

Principle:

ZigZag is drawn by the channeling principle. The channel width can be defined in points (IdealZZ) or in percentage terms (IdealZZP)

Peaks retrieval:

input int ChannelWidth=100;

#property indicator_chart_window

datetime LastTime;
int ZZHandle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
   LastTime = 0;
   ZZHandle = iCustom(_Symbol, Period(), "IdealZZ", ChannelWidth);
  }
//+------------------------------------------------------------------+
//| GetValue                                                         |
//+------------------------------------------------------------------+
bool GetValue(double dir,int bar,int prevBar,double &peak,
             int &peakBar,datetime &peakTime,const datetime &T[])
  {
   if(dir<0)
     {
      double t[1];
      if(0>=CopyBuffer(ZZHandle,2,bar,1,t)) return false;
      int i= ArrayBsearch(T, (datetime)t[0]);

      if(i==prevBar)
        {
         if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false;
         i=ArrayBsearch(T,(datetime)t[0]);
        }

      double v[1];
      if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false;

      if(v[0]==EMPTY_VALUE)
        {
         if(0>=CopyBuffer(ZZHandle,2,bar+1,1,t)) return false;
         i=ArrayBsearch(T,(datetime)t[0]);
         if(0>=CopyBuffer(ZZHandle,1,i,1,v)) return false;
        }

      peak=v[0];
      peakBar=i;
      peakTime=(datetime)t[0];
     }
   else if(dir>0)
     {
      double t[1];
      if(0>=CopyBuffer(ZZHandle,3,bar,1,t)) return false;
      int i= ArrayBsearch(T, (datetime)t[0]);

      if(i==prevBar)
        {
         if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false;
         i=ArrayBsearch(T,(datetime)t[0]);
        }

      double v[1];
      if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false;

      if(v[0]==EMPTY_VALUE)
        {
         if(0>=CopyBuffer(ZZHandle,3,bar+1,1,t)) return false;
         i=ArrayBsearch(T,(datetime)t[0]);
         if(0>=CopyBuffer(ZZHandle,0,i,1,v)) return false;
        }

      peak=v[0];
      peakBar=i;
      peakTime=(datetime)t[0];
     }
   else
     {
      return(false);
     }

   return(true);
  }
//+------------------------------------------------------------------+
//| GetValue                                                         |
//+------------------------------------------------------------------+
void SetPt(string name,double price,datetime time)
  {
   ObjectCreate(0,name,OBJ_ARROW,0,time,price);
   ObjectSetInteger(0,name,OBJPROP_ARROWCODE,108);
   ObjectSetDouble(0,name,OBJPROP_PRICE,price);
   ObjectSetInteger(0,name,OBJPROP_TIME,time);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &T[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   if(LastTime==T[0]) return(rates_total);
   LastTime=T[0];

   ArraySetAsSeries(T,true);

   double dir_[1];
   if(0>=CopyBuffer(ZZHandle,4,1,1,dir_)) return rates_total;
   double dir=dir_[0];
   double rdir=-dir;

   if(dir==EMPTY_VALUE) return(rates_total);

   double v1,v2,v3,v4,v5;
   int    i1,i2,i3,i4,i5;
   datetime t1,t2,t3,t4,t5;

   if(
      GetValue(dir,1,0,v1,i1,t1,T) && 
      GetValue(rdir,i1,0,v2,i2,t2,T) && 
      GetValue(dir,i2,i1,v3,i3,t3,T) && 
      GetValue(rdir,i3,i2,v4,i4,t4,T) && 
      GetValue(dir,i4,i3,v5,i5,t5,T)
      )
     {
      SetPt("1",v1,t1);
      SetPt("2",v2,t2);
      SetPt("3",v3,t3);
      SetPt("4",v4,t4);
      SetPt("5",v5,t5);
      Print(v1,"   ",v2,"  ",v3,"  ",v4," ",v5," ",i1,"  ",i2,"  ",i3," ",i4," ",i5);
     }
   else
     {
      Print("Seems to be error available...");
     }

   return(rates_total);
  }
//+------------------------------------------------------------------+

This example is an indicator that marks (one time per bar) first five peaks (including the current forming one).

Attention! The code may work incorrectly, if zero bar mode is enabled

Zero Bar Mode:

The mode can be enabled in DrawZeroBar variable code. It is disabled by default. It is not recommended to enable it, especially if the indicator is used in an Expert Advisor.

Enjoy using it. Please inform me of any revealed drawbacks.

Translated from Russian by MetaQuotes Ltd.
Original code: https://www.mql5.com/ru/code/925

Jolly Roger EA Version Jolly Roger EA Version

Inspired by Pirat's Expert Advisor submitted to the Automated Trading Championship 2011.

The Example of IndicatorParameters() usage The Example of IndicatorParameters() usage

This Expert Advisor illustrates the usage of the IndicatorParameters() function to get the information about the number of input parameters, their type and values.

Triangle Hedge Triangle Hedge

Opens a virtual hedge position in MetaTrader 5.

Weather Vane Weather Vane

This indicator calculates last average price for a symbol and determines the trend direction, so it can be a signal to commit a trade operation.