ZigZag WaveSize

Author: Copyright © 2024, iboot@yandex.ru
Miscellaneous
Implements a curve of type %1It issuies visual alerts to the screenIt plays sound alertsIt sends emails
0 Views
0 Downloads
0 Favorites
ZigZag WaveSize
ÿþ//+------------------------------------------------------------------+

//|                                              ZigZag WaveSize.mq4 |

//|                                    Copyright 2024, by Ivan Butko |

//|                        https://www.mql5.com/ru/users/capitalplus |

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



#property copyright "Copyright © 2024, iboot@yandex.ru"

#property link      "https://www.mql5.com/ru/users/capitalplus"

#property strict



#property indicator_chart_window

#property indicator_buffers 1

#property indicator_color1  Red



//---- indicator parameters

input string str_1 = " ----------------------------  MAIN";

input int InpDepth     = 12;       // Depth

input int InpDeviation = 5;        // Deviation

input int InpBackstep  = 3;        // Backstep



input string str_2 = " ----------------------------  FONT";



input int   Font_size  = 10;       // Font size

input color Font_color = clrGray;  // Font color



input string str_3 = " ----------------------------  ALERT";



input bool Alert_use = false;            // Alert

input bool Push_use  = false;            // Push

input bool Sound_use = false;            // Sound

input string Sound_file = "alert.wav";   // Sound file

input bool Mail_use  = false;            // Mail

input string Mail_subject = "MT notif";  // Mail subject



input string str_O  = "";      // ------------------------ 



enum delete_obj

  {

    Delete,

    Keep,

  };

input delete_obj OnDeinit_delete_obj = Delete; // Objects on the chart when deinitialized









//---- indicator buffers

double ExtZigzagBuffer[];

double ExtHighBuffer[];

double ExtLowBuffer[];





//--- globals



string alert_text, last_mode, alert_mode = "", last_alert_mode = " ", last_size = ""; 

double last_buf, cur_buf;

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

datetime t;

int n;

string last_zig;







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

//| 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)+")");

   

   for(int i=n+1; i>=0; i--)     ObjectDelete("ZigZag " + i);

   

   n = 0;   

   

//---- 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;

   

   for(i=n+1; i>=0; i--)      ObjectDelete("ZigZag " + i);



   n = 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 (i < 1000)

               {

               n--;            

               ObjectDelete("ZigZag " + n);  

               n++;                                                                             

                                                                                                      

               t = iTime(_Symbol, PERIOD_CURRENT, i);

               string text = DoubleToString((lasthigh - lastlow) * pow(10, _Digits), 0);

               DrawSize(n, t, lastlow, text, "Down");

               n++;

               }

              }

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

              {

               lasthigh=ExtHighBuffer[i];

               lasthighpos=i;

               ExtZigzagBuffer[i]=lasthigh;

               

               if (i < 1000)

               {

               t = iTime(_Symbol, PERIOD_CURRENT, i);

               string text = DoubleToString((lasthigh - lastlow) * pow(10, _Digits), 0);

               if (i == 1) alert_mode = "Up";

               DrawSize(n, t, lasthigh, text, "Up");

               n++;

               }

               

               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 (i < 1000)

               {

               n--;            

               ObjectDelete("ZigZag " + n);  

               n++;

                     

               t = iTime(_Symbol, PERIOD_CURRENT, i);

               string text = DoubleToString((lasthigh - lastlow) * pow(10, _Digits), 0);

               DrawSize(n, t, lasthigh, text, "Up");

               n++;

               }

               

              }

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

              {

               lastlow=ExtLowBuffer[i];

               lastlowpos=i;

               ExtZigzagBuffer[i]=lastlow;

               

               if (i < 1000)

               {

               t = iTime(_Symbol, PERIOD_CURRENT, i);

               string text = DoubleToString((lasthigh - lastlow) * pow(10, _Digits), 0);

               if (i == 1) alert_mode = "Down";

               DrawSize(n, t, lastlow, text, "Down");

               n++;

               }

               

               whatlookfor=1;

              }   

            break;               

        }

     }

 

   

//--- done

   return(rates_total);

  }

  

  

  

  

  

  

void DrawSize(int n, datetime t, double p, string text, string mode)

  {

    ObjectCreate(0, "ZigZag " + n, OBJ_TEXT, 0, t, p);

      ObjectSetString(0, "ZigZag " + n, OBJPROP_TEXT, text);    

      if (mode == "Up")      ObjectSetInteger(0, "ZigZag " + n, OBJPROP_ANCHOR, ANCHOR_LOWER);      

      if (mode == "Down")      ObjectSetInteger(0, "ZigZag " + n, OBJPROP_ANCHOR, ANCHOR_UPPER);

      ObjectSetInteger(0, "ZigZag " + n, OBJPROP_FONTSIZE, Font_size); 

      ObjectSetInteger(0, "ZigZag " + n, OBJPROP_COLOR, Font_color);    

      

    if ((alert_mode != last_alert_mode && alert_mode == "Up") || (alert_mode != last_alert_mode && alert_mode == "Down"))

      {

        string alert_text = Symbol() + " " + TF() + "    " + mode + "    last wave = " + last_size + " p.";

        if (Alert_use) Alert(alert_text);

        if (Push_use)  SendNotification(alert_text);

        if (Sound_use) PlaySound(Sound_file); 

        if (Mail_use)  SendMail(Mail_subject, alert_text);

        

        last_alert_mode = alert_mode;

      }

      

    last_size = text;

  }

  

  

  

  

  

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

//| GetTimeFrame function - returns the textual timeframe               |

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

string TF()

  {

    switch(Period())

      {         

        case PERIOD_M1  :  return("M1" );          

        case PERIOD_M5  :  return("M5" );     

        case PERIOD_M15 :  return("M15");       

        case PERIOD_M30 :  return("M30");         

        case PERIOD_H1  :  return("H1" );    

        case PERIOD_H4  :  return("H4" );  

        case PERIOD_D1  :  return("Daily" );         

        case PERIOD_W1  :  return("Weekly" );         

        case PERIOD_MN1 :  return("Monthly");

                  

        default:return("Unable to determine timeframe");         

      }

  }

  

  

  

  

  

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

//|                                                                  |

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

int InitializeAll()

  {   

   ArrayInitialize(ExtZigzagBuffer,0.0);

   ArrayInitialize(ExtHighBuffer,0.0);

   ArrayInitialize(ExtLowBuffer,0.0);

//--- first counting position

   return(Bars-InpDepth);

  }

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



void OnDeinit(const int reason)

  {      

    if (OnDeinit_delete_obj == Delete && _UninitReason == REASON_REMOVE)

      {

        for(int i=n+1; i>=0; i--)      ObjectDelete("ZigZag " + i);

      }  

  }

Comments