Moved: How to use ZigZag indicator to build an EA ?

 
Alain Verleyen:
I am not sure what you are asking for ?

I mean, for the  rates_total and prev_calculated, is it just used as global variables?

I try to convert indi zigzag into EA, but we have different result with the actual indi.

can you help me please?

is it correct with the using of CopyLow, CopyHigh.. etc and with the rates_total and prev_calculated?

thank you


This is the source (indicator) :

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq4 |
//|                   Copyright 2006-2014, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2006-2014, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property strict

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  Red
//---- indicator parameters
input int InpDepth=12;     // Depth
input int InpDeviation=5;  // Deviation
input int InpBackstep=3;   // Backstep
//---- indicator buffers
double ExtZigzagBuffer[];
double ExtHighBuffer[];
double ExtLowBuffer[];
//--- globals
int    ExtLevel=3; // recounting's depth of extremums
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(InpBackstep>=InpDepth)
     {
      Print("Backstep cannot be greater or equal to Depth");
      return(INIT_FAILED);
     }
//--- 2 additional buffers
   IndicatorBuffers(3);
//---- drawing settings
   SetIndexStyle(0,DRAW_SECTION);
//---- indicator buffers
   SetIndexBuffer(0,ExtZigzagBuffer);
   SetIndexBuffer(1,ExtHighBuffer);
   SetIndexBuffer(2,ExtLowBuffer);
   SetIndexEmptyValue(0,0.0);
//---- indicator short name
   IndicatorShortName("ZigZag("+string(InpDepth)+","+string(InpDeviation)+","+string(InpBackstep)+")");
//---- initialization done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   int    i,limit,counterZ,whatlookfor=0;
   int    back,pos,lasthighpos=0,lastlowpos=0;
   double extremum;
   double curlow=0.0,curhigh=0.0,lasthigh=0.0,lastlow=0.0;
//--- check for history and inputs
   if(rates_total<InpDepth || InpBackstep>=InpDepth)
      return(0);
//--- first calculations
   if(prev_calculated==0)
      limit=InitializeAll();
   else
     {
      //--- find first extremum in the depth ExtLevel or 100 last bars
      i=counterZ=0;
      while(counterZ<ExtLevel && i<100)
        {
         if(ExtZigzagBuffer[i]!=0.0)
            counterZ++;
         i++;
        }
      //--- no extremum found - recounting all from begin
      if(counterZ==0)
         limit=InitializeAll();
      else
        {
         //--- set start position to found extremum position
         limit=i-1;
         //--- what kind of extremum?
         if(ExtLowBuffer[i]!=0.0)
           {
            //--- low extremum
            curlow=ExtLowBuffer[i];
            //--- will look for the next high extremum
            whatlookfor=1;
           }
         else
           {
            //--- high extremum
            curhigh=ExtHighBuffer[i];
            //--- will look for the next low extremum
            whatlookfor=-1;
           }
         //--- clear the rest data
         for(i=limit-1; i>=0; i--)
           {
            ExtZigzagBuffer[i]=0.0;
            ExtLowBuffer[i]=0.0;
            ExtHighBuffer[i]=0.0;
           }
        }
     }
//--- main loop      
   for(i=limit; i>=0; i--)
     {
      //--- find lowest low in depth of bars
      extremum=low[iLowest(NULL,0,MODE_LOW,InpDepth,i)];
      //--- this lowest has been found previously
      if(extremum==lastlow)
         extremum=0.0;
      else
        {
         //--- new last low
         lastlow=extremum;
         //--- discard extremum if current low is too high
         if(low[i]-extremum>InpDeviation*Point)
            extremum=0.0;
         else
           {
            //--- clear previous extremums in backstep bars
            for(back=1; back<=InpBackstep; back++)
              {
               pos=i+back;
               if(ExtLowBuffer[pos]!=0 && ExtLowBuffer[pos]>extremum)
                  ExtLowBuffer[pos]=0.0;
              }
           }
        }
      //--- found extremum is current low
      if(low[i]==extremum)
         ExtLowBuffer[i]=extremum;
      else
         ExtLowBuffer[i]=0.0;
      //--- find highest high in depth of bars
      extremum=high[iHighest(NULL,0,MODE_HIGH,InpDepth,i)];
      //--- this highest has been found previously
      if(extremum==lasthigh)
         extremum=0.0;
      else
        {
         //--- new last high
         lasthigh=extremum;
         //--- discard extremum if current high is too low
         if(extremum-high[i]>InpDeviation*Point)
            extremum=0.0;
         else
           {
            //--- clear previous extremums in backstep bars
            for(back=1; back<=InpBackstep; back++)
              {
               pos=i+back;
               if(ExtHighBuffer[pos]!=0 && ExtHighBuffer[pos]<extremum)
                  ExtHighBuffer[pos]=0.0;
              }
           }
        }
      //--- found extremum is current high
      if(high[i]==extremum)
         ExtHighBuffer[i]=extremum;
      else
         ExtHighBuffer[i]=0.0;
     }
//--- final cutting 
   if(whatlookfor==0)
     {
      lastlow=0.0;
      lasthigh=0.0;
     }
   else
     {
      lastlow=curlow;
      lasthigh=curhigh;
     }
   for(i=limit; i>=0; i--)
     {
      switch(whatlookfor)
        {
         case 0: // look for peak or lawn 
            if(lastlow==0.0 && lasthigh==0.0)
             {
               if(ExtHighBuffer[i]!=0.0)
                 {
                  lasthigh=High[i];
                  lasthighpos=i;
                  whatlookfor=-1;
                  ExtZigzagBuffer[i]=lasthigh;
                 }
               if(ExtLowBuffer[i]!=0.0)
                 {
                  lastlow=Low[i];
                  lastlowpos=i;
                  whatlookfor=1;
                  ExtZigzagBuffer[i]=lastlow;
                 }
              }
            break;
         case 1: // look for peak
            if(ExtLowBuffer[i]!=0.0 && ExtLowBuffer[i]<lastlow && ExtHighBuffer[i]==0.0)
              {
               ExtZigzagBuffer[lastlowpos]=0.0;
               lastlowpos=i;
               lastlow=ExtLowBuffer[i];
               ExtZigzagBuffer[i]=lastlow;
              }
            if(ExtHighBuffer[i]!=0.0 && ExtLowBuffer[i]==0.0)
              {
               lasthigh=ExtHighBuffer[i];
               lasthighpos=i;
               ExtZigzagBuffer[i]=lasthigh;
               whatlookfor=-1;
              }
            break;
         case -1: // look for lawn
            if(ExtHighBuffer[i]!=0.0 && ExtHighBuffer[i]>lasthigh && ExtLowBuffer[i]==0.0)
              {
               ExtZigzagBuffer[lasthighpos]=0.0;
               lasthighpos=i;
               lasthigh=ExtHighBuffer[i];
               ExtZigzagBuffer[i]=lasthigh;
              }
            if(ExtLowBuffer[i]!=0.0 && ExtHighBuffer[i]==0.0)
              {
               lastlow=ExtLowBuffer[i];
               lastlowpos=i;
               ExtZigzagBuffer[i]=lastlow;
               whatlookfor=1;
              }
            break;
        }
     }
//--- done
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int InitializeAll()
  {
   ArrayInitialize(ExtZigzagBuffer,0.0);
   ArrayInitialize(ExtHighBuffer,0.0);
   ArrayInitialize(ExtLowBuffer,0.0);
//--- first counting position
   return(Bars-InpDepth);
  }
//+------------------------------------------------------------------+




and this is my try of the conversion :

//----- Set Zigzag --------------//

int InpDepth=12;     // Depth

int InpDeviation=5;  // Deviation

int InpBackstep=3;   // Backstep

double ExtZigzagBuffer[];

double ExtHighBuffer[];

double ExtLowBuffer[];



//--- globals

int    ExtLevel=3; // recounting's depth of extremums

int rates_total = 0;

int prev_calculated = 0;

datetime time_array[];

double open_array[], high_array[], low_array[], close_array[];

long tick_volume_array[], volume_array[];

int spread_array[];



//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

  {

//---



//---

   return(INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//---

   

  }

//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

  {

//---

   int nBarsTF;

   nBarsTF = iBars(Symbol(),0);

   rates_total = nBarsTF;



   if(ArraySize(ExtZigzagBuffer) < nBarsTF){

      ArraySetAsSeries(ExtZigzagBuffer, false);

      ArraySetAsSeries(ExtHighBuffer, false);

      ArraySetAsSeries(ExtLowBuffer, false);

      //----  

      ArrayResize(ExtZigzagBuffer, nBarsTF); 

      ArrayResize(ExtHighBuffer, nBarsTF); 

      ArrayResize(ExtLowBuffer, nBarsTF); 

      //----

      ArraySetAsSeries(ExtZigzagBuffer, true);

      ArraySetAsSeries(ExtHighBuffer, true); 

      ArraySetAsSeries(ExtLowBuffer, true);

   }

   

   //-------------- Indi_Zigzag -----------------------------------------------//   

   CopyTime(Symbol(),0,0,nBarsTF,time_array);

   CopyOpen(Symbol(),0,0,nBarsTF,open_array);

   CopyHigh(Symbol(),0,0,nBarsTF,high_array);

   CopyLow(Symbol(),0,0,nBarsTF,low_array);

   CopyClose(Symbol(),0,0,nBarsTF,close_array);

   CopyTickVolume(Symbol(),0,0,nBarsTF,tick_volume_array);

   CopyRealVolume(Symbol(),0,0,nBarsTF,volume_array);

   CopySpread(Symbol(),0,0,nBarsTF,spread_array);

   

   

   int    i,limit,counterZ,whatlookfor=0;

   int    back,pos,lasthighpos=0,lastlowpos=0;

   double extremum;

   double curlow=0.0,curhigh=0.0,lasthigh=0.0,lastlow=0.0;



   if(rates_total<InpDepth || InpBackstep>=InpDepth) return;   //--- check for history and inputs

   if(nBarsTF < 100) return;



   if(prev_calculated==0) {                                    //--- first calculations

      Print("----");

      for(int z = nBarsTF - 1; z >= 0; z--) {

        ExtZigzagBuffer[z] = 0.0;

        ExtHighBuffer[z] = 0.0;

        ExtLowBuffer[z] = 0.0;

      }

      limit = nBarsTF - InpDepth;

   }

      

   else {

      i = counterZ = 0;                                        //--- find first extremum in the depth ExtLevel or 100 last bars

      while(counterZ<ExtLevel && i<100){

         if(ExtZigzagBuffer[i]!=0.0)

            counterZ++;

         i++;

        }

      

      if(counterZ==0){                                         //--- no extremum found - recounting all from begin

         for(int z = nBarsTF - 1; z >= 0; z--) {

            ExtZigzagBuffer[z] = 0.0;

            ExtHighBuffer[z] = 0.0;

            ExtLowBuffer[z] = 0.0;

         }

         limit = nBarsTF - InpDepth;

      }

      else {

         limit = i-1;                                          //--- set start position to found extremum position

         if(ExtLowBuffer[i]!=0.0){                             //--- what kind of extremum?

            curlow = ExtLowBuffer[i];                          //--- low extremum

            whatlookfor = 1;                                   //--- will look for the next high extremum

           }

         else {

            curhigh=ExtHighBuffer[i];                          //--- high extremum

            whatlookfor = -1;                                  //--- will look for the next low extremum

           }

         for(i=limit-1; i>=0; i--){                            //--- clear the rest data

            ExtZigzagBuffer[i]=0.0;

            ExtLowBuffer[i]=0.0;

            ExtHighBuffer[i]=0.0;

           }

        }

     }

     

//--- main loop      

   for(i=limit; i>=0; i--) {

      extremum = low_array[iLowest(Symbol(),0,MODE_LOW,InpDepth,i)]; //--- find lowest low in depth of bars

      if(extremum==lastlow)                                          //--- this lowest has been found previously

         extremum = 0.0;

      else {

         lastlow = extremum;                                         //--- new last low

         if(low_array[i]-extremum>InpDeviation*Point)                //--- discard extremum if current low is too high

            extremum = 0.0;

         else {

            for(back=1; back<=InpBackstep; back++){                  //--- clear previous extremums in backstep bars

               pos=i+back;

               if(ExtLowBuffer[pos]!=0 && ExtLowBuffer[pos]>extremum)

                  ExtLowBuffer[pos]=0.0;

              }

           }

        }

      

      if(low_array[i]==extremum){                                    //--- found extremum is current low

         ExtLowBuffer[i]=extremum;

      }

      else

         ExtLowBuffer[i]=0.0;

      

      extremum=high_array[iHighest(Symbol(),0,MODE_HIGH,InpDepth,i)];   //--- find highest high in depth of bars

      if(extremum==lasthigh)                                            //--- this highest has been found previously

         extremum = 0.0;

      else {

         lasthigh = extremum;                                           //--- new last high

         if(extremum-high_array[i]>InpDeviation*Point)                  //--- discard extremum if current high is too low

            extremum = 0.0;

         else {

            for(back=1; back<=InpBackstep; back++) {                    //--- clear previous extremums in backstep bars

               pos=i+back;

               if(ExtHighBuffer[pos]!=0 && ExtHighBuffer[pos]<extremum)

                  ExtHighBuffer[pos]=0.0;

            }

         }

      }

      if(high_array[i]==extremum)                                       //--- found extremum is current high

         ExtHighBuffer[i] = extremum;

      else

         ExtHighBuffer[i]=0.0;

   }

     

//--- final cutting 

   if(whatlookfor==0) {

      lastlow = 0.0;

      lasthigh = 0.0;

   }

   else {

      lastlow = curlow;

      lasthigh = curhigh;

   }

   for(i=limit; i>=0; i--){

      switch(whatlookfor){

         case 0:                                                                          // look for peak or lawn 

            if(lastlow==0.0 && lasthigh==0.0) {

               if(ExtHighBuffer[i]!=0.0) {

                  lasthigh=High[i];

                  lasthighpos=i;

                  whatlookfor=-1;

                  ExtZigzagBuffer[i]=lasthigh;

               }

               if(ExtLowBuffer[i]!=0.0) {

                  lastlow=Low[i];

                  lastlowpos=i;

                  whatlookfor=1;

                  ExtZigzagBuffer[i]=lastlow;

               }

            }

            break;

         

         case 1:                                                                          // look for peak

            if(ExtLowBuffer[i]!=0.0 && ExtLowBuffer[i]<lastlow && ExtHighBuffer[i]==0.0){

               ExtZigzagBuffer[lastlowpos]=0.0;

               lastlowpos = i;

               lastlow = ExtLowBuffer[i];

               ExtZigzagBuffer[i] = lastlow;

            }

            if(ExtHighBuffer[i]!=0.0 && ExtLowBuffer[i]==0.0) {

               lasthigh = ExtHighBuffer[i];

               lasthighpos = i;

               ExtZigzagBuffer[i] = lasthigh;

               whatlookfor = -1;

            }

            break;

         

         case -1:                                                                          // look for lawn

            if(ExtHighBuffer[i]!=0.0 && ExtHighBuffer[i]>lasthigh && ExtLowBuffer[i]==0.0){

               ExtZigzagBuffer[lasthighpos]=0.0;

               lasthighpos = i;

               lasthigh = ExtHighBuffer[i];

               ExtZigzagBuffer[i] = lasthigh;

            }

            if(ExtLowBuffer[i]!=0.0 && ExtHighBuffer[i]==0.0){

               lastlow = ExtLowBuffer[i];

               lastlowpos = i;

               ExtZigzagBuffer[i] = lastlow;

               whatlookfor = 1;

            }

            break;

        }

     }

   

   prev_calculated = rates_total;

  }

 
Alain Verleyen:


Okay. I'm sorry, my first time inserting some code.. 

 
Donald Reeves Sihombing:

Okay. I'm sorry, my first time inserting some code.. 

You don't need to use the ZigZag code inside your EA. You should use iCustom.

I am moving your topic to mql4 section, you will most probably receive more help there.

 
Alain Verleyen:

You don't need to use the ZigZag code inside your EA. You should use iCustom.

I am moving your topic to mql4 section, you will most probably receive more help there.


Thank you for your help.

Actually I'm on progress automatic validation for uploading my EA into market. Then the system found an error in my EA : array out of range in 'ZigZag.mq4' (77,28)

I used zigzag as one of my indicator in that ea. Then I think that I should include the zigzag into the ea..

But I still have problem with the conversion..

 
Donald Reeves Sihombing: I think that I should include the zigzag into the ea.. But I still have problem with the conversion..
Don't try do that. There are no buffers, no IndicatorCounted() or prev_calculated. No way to know if older bars have changed or been added (history update.)

Just get the value of the indicator into the EA and do what you want with it. You should encapsulate your iCustom calls to make your code self-documenting.
 
whroeder1:
Don't try do that. There are no buffers, no IndicatorCounted() or prev_calculated. No way to know if older bars have changed or been added (history update.)

Just get the value of the indicator into the EA and do what you want with it. You should encapsulate your iCustom calls to make your code self-documenting.

But I tried this to macd in my ea and it worked well. It is because the code is simple, no OnCalculate in it..

But in zigzag, it has OnCalculate, so I think that it need additional work by converting all the item/parameter in OnCalculate into ea code..

 

Thank you all friends..

We already get the code..! :)

I reset the array setting (aray size, set as series, array resize) of all the parameters copylow, copyhigh, etc just like the parameters of the buffers.. 

 

Just compile the indicator with the EA by including it as a resource.

Example:

#property strict
#resource "ZigZag.ex4"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   for(int i=0,cnt=0; i<Bars && cnt<10; i++)
   {
      double z = zigzag(i);
      if(z!=0.0 && z!=EMPTY_VALUE)
         Print("ZigZag value = ",z," cnt = ",++cnt);
   }
}
//+------------------------------------------------------------------+
double zigzag(const int i)
{
   return iCustom(Symbol(),Period(),"::ZigZag.ex4",12,5,3,0,i);
}


 The attached script has the ZigZag indicator compiled with it, so as you can see there's no need for a separate indicator file.

Files:
 
nicholishen:

Just compile the indicator with the EA by including it as a resource.

Example:


 The attached script has the ZigZag indicator compiled with it, so as you can see there's no need for a separate indicator file.


Thank you. I'll try to check it out.

Reason: