MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal

Source code library - Expert Advisors, Indicators and Scripts

Interview with Alexey Masterov (ATC 2012) Interview with Alexey Masterov (ATC 2012) Screenshot
USDCAD, D1
Demo
Compression DuoCompression Duo Try product
Compression Duo
Author: Progid
Subscribe to signal
Forex Capital Italy Tony
14.52%, 73.63 USD
VGridLine_Intraday X4 Indicator
VGridLine_Intraday X4
Author: GODZILLA
To post a new code, please log in or register

Interesting script?
So post a link to it -
let others appraise it

You liked the script? Try it in the MetaTrader 5 terminal

2012.07.20 14:07
Ideal ZigZag

Ideal ZigZag [ru]

TheXpert

Downloads:
2437
Views:
4476
Rating:
votes: 36
Files:
\MQL5\Indicators\
idealzz.mq5 (7.33 KB)view
idealzzp.mq5 (7.33 KB)view

Description:

This is a simple but very fast zigzag.

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

Image:

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 Software Corp.
Original code: http://www.mql5.com/ru/code/925