#ForexHomeExpert_image_slider1 #ForexHomeExpert_image_slider2 #ForexHomeExpert_image_slider3 #ForexHomeExpert_image_slider4

Sunday, February 1, 2026

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert

1. Introduction

In the fast-paced world of Forex trading, the ability to see the Big Picture while maintaining focus on execution is what separates a professional from an amateur. Today, I am proud to introduce ZigZag Multi-timeframe (ZigZag_MTF), a high-performance multi-timeframe dashboard for MetaTrader 5 that redefines how we monitor market structure.

In high-speed forex trading, switching between timeframes to find a trend is a chore that often leads to missed opportunities. A true professional needs a Bird’s Eye View of the market. This is why I developed ZigZag_MTF for MetaTrader 5—not just an indicator, but a comprehensive multi-timeframe command center.

The ZigZag Multi-timeframe Indicator for MT5 (ZigZag_MTF) utilizes a template and displays a panel on the chart. Its function, operation, and usage are identical to the William's Percent Range Multi-Timeframe Indicator for MT5 (WPR_MTF) as detailed in the previous article. For a comprehensive guide on creating a multi-timeframe indicator, you can refer to the following resources: William's Percent Range Multi-Timeframe Indicator for MT5

USDCADH4_ZigZag_MTF - The ZiGZag_MTF indicator is displayed on the upper of the chartFigure 1: The ZiGZag_MTF indicator is displayed on the upper of the chart.
USDCADH4_ZigZag_MTF_bottom - The ZiGZag_MTF indicator is displayed on the bottom of the chartFigure 2: The ZiGZag_MTF indicator is displayed on the bottom of the chart.

2. The Interactive Dashboard Feature

The standout feature of my ZigZag_MTF is the Interactive UI Controller. Unlike standard MTF indicators that clutter your screen with messy lines, this tool provides a clean, clickable dashboard:

  • Instant Sync: Click any timeframe button (from M1 to MN) on the screen to instantly switch the chart.
  • Symbol Switcher: Navigate between different currency pairs directly from the dashboard.
  • Real-time Scanning: The indicator works in the background, calculating ZigZag points for every timeframe to ensure your data is always current.

3. The Fractal Nature of the Market

The market moves in fractals. A single trend on a Daily chart is composed of hundreds of smaller waves on the lower timeframes. To trade effectively, you need to see both. ZigZag_MTF provides a centralized command center, scanning ZigZag patterns across multiple timeframes simultaneously, ensuring you never miss a structural shift.

By tracking ZigZag patterns across all timeframes simultaneously, you can:

  • Identify the Major Trend from Daily/Monthly charts.
  • Pinpoint Optimal Entry on lower timeframes.
  • Avoid Noise by filtering out minor price fluctuations that don't align with the higher-order structure.

4. The "Engine" Logic: Stability vs. Agility

A unique feature of this indicator lies in its core calculation function: ZigZagMovementCalculation(). Unlike standard MTF indicators that treat all timeframes equally, ZigZag_MTF is engineered with a selective logic:

  • 1. Strategic Stability (H2 to MN1): On higher timeframes (H2, H4, up to Monthly), the ZigZag points represent the Grand Structure of the market. These levels are stable and serve as massive support and resistance zones. In my code, these timeframes provide the visual context (color-coding) but are not used for volatile signal generation, as their movement is naturally static.
  • 2. Tactical Agility (M1 to H1): The real energy of a trend reversal occurs within the lower timeframes. By using the logic `if(x < 12)`, the indicator focuses its analytical power on the 11 timeframes from M1 to H1. This is where the ZigZag Rise or Down signals are calculated. This ensures that your entry signals are fresh, agile, and reactive to current price action, while still being protected by the Big Picture trend from above.

5. Key Features of the Dashboard

  • Interactive UI Controller: Switch between timeframes (M1 to MN) or change currency symbols with a single click directly on your chart. No more messy terminal tabs.
  • Optimized Performance: Built with efficient handle management, this indicator is light on your CPU, making it ideal for traders who run multiple assets simultaneously.
  • Responsive Scaling: Whether you use a 4K monitor or a laptop, the dashboard scales perfectly thanks to its internal window-scaling logic.

6. How to Trade with ZigZag_MTF

  • Identify the Anchor: Use the dashboard to see if higher timeframes (like D1) are showing a stable ZigZag Low.
  • Wait for the Pulse: Look for the active signal (Rise) on the lower timeframes (M15-H1) as calculated by the ZigZagMovementCalculation() function logic and look at the arrows and alerts provided by the indicator
  • Confirm the Break: As discussed in our previous article on Newtonian mechanics, use the 30% / 70% threshold for a high-probability entry.

7. Conclusion

ZigZag_MTF is not just an indicator; it is a tactical map. By separating structural stability from execution agility, it allows you to trade with the calmness of a long-term investor and the precision of a scalper.

⚠️ Important: Risk Disclaimer

Trading foreign exchange on margin carries a high level of risk and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to invest in foreign exchange, you should carefully consider your investment objectives, level of experience, and risk appetite. The ZigZag Multi-timeframe (ZigZag_MTF) logic and indicators provided in this article are for educational purposes and do not guarantee profits. Past performance is not indicative of future results.

Vital Records

If you think the ZigZag Multi-timeframe (ZigZag_MTF) is worthy of being used for automated trading as an Expert Advisor, please leave a comment below this article.

If at least 25 people agree that this indicator is worthy of being used as an Expert Advisor, I will create an Expert Advisor based on its signals and share it on this blog.

Thanks for reading this article.

Risk Warning: Trading Forex and CFDs involves significant risk and may not be suitable for all investors. All content provided is for educational purposes only.


//+------------------------------------------------------------------+
//|                                                   ZigZag_MTF.mq5 |
//|        Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-26-01 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright   "Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-01-26"
#property link        "https://www.mql5.com/en/users/3rjfx"
#property version     "1.00"
#property description "ZigZag_MTF is the ZigZag Indicator in Multi Timeframe"
#property description "for MT5 which is calculated and scan ZigZag on each timeframe."
//---
#property indicator_chart_window
#property indicator_plots   1
#property indicator_buffers 1
//---
//--
enum YN
  {
   No,
   Yes
  };
//--
enum fonts
  {
   Verdana,
   Bodoni_MT_Black
  };
//--
//---
//--- ZigZag Indicator Input Properties
input group              "=== ZigZag Indicator Input Properties ===";  // ZigZag Indicator Input Properties
input int                zzDepth = 12;               // Input ZigZag Depth, default 12
input int                zzDevia = 5;                // Input ZigZag Deviation, default 5
input int                zzBackS = 3;                // Input ZigZag Back Step, default 3
input group   "====  Indicator Color and Font   ===="
input color              ArrowUp = clrMediumSeaGreen; // Arrow Up Color
input color              ArrowDn = clrDeepPink;       // Arrow Down Color
input color              NTArrow = clrGold;           // Arrow No Signal
input fonts              f_model = Bodoni_MT_Black;   // Select Font Model
input group   "====  Input parameters for alerts  ===="
input YN                  alerts = Yes;               // Display Alerts Pop-up on Chart (Yes) or (No)
input YN           UseEmailAlert = No;                // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;                // Send Notification (Yes) or (No)
//---
//---------//
//+------------------------------------------------------------------+
//| class for MTF indicator                                          |
//+------------------------------------------------------------------+
class MTF_Indi
  {
   //---
   public:
   //--
   int               fbar;
   int               star,
                     tstar,
                     bstar;
   int               hZigZag[];
   int               TNamex,
                     TNamexn,
                     TNamey1,
                     TNamey2,
                     TNamey3,
                     TNamey1n,
                     TNamey2n,
                     TNamey3n;
   int               tfxar;
   int               up,dw;
   int               tfhalf;
   int               maxbar;
   int               ttlbars;
   int               scaleX,
                     scaleA,
                     scaleY,
                     horizL1,
                     horizL2,
                     horizL3,
                     horizL4,
                     horizL5,
                     horizL6,
                     vertiL1,
                     vertiL2,
                     vertiL3,
                     vertiL4,
                     vertiL5,
                     vertiL6,
                     offsetX,
                     offsetY,
                     fontSize,
                     windchar,
                     windsize;
   int               corx,
                     cory,
                     txttf;
   int               curmin,
                     prvmin;
   int               corpos;
   int               pospos,
                     postop,
                     posbot;
   int               curAlert;
   int               prvAlert;
   int               ZZ_Period;
   //--
   long              CI;
   string            posisi,
                     sigpos,
                     indname,
                     msgText,
                     InHname,
                     ObjName;
   string            cstar,
                     artop,
                     arbot;
   string            hName1,
                     hName2,
                     hName3;
   string            font_mode;
   bool              display;
   double            OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
   long              VOLUME[];
   datetime          TIME[];
   datetime          cbartime;
   //--
   int               year,  // Year
                     mon,   // Month
                     day,   // Day
                     hour,  // Hour
                     min,   // Minutes
                     sec,   // Seconds
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
   //---- buffers
   double            PowerMove[];
   string            TFSc[];
   color             Arwcolor[];
   color             TColor;
   ENUM_TIMEFRAMES   TFId[];
   ENUM_BASE_CORNER  bcor;
   ENUM_ANCHOR_POINT ancp;
   //---
   //---
   //- Constructor
                     MTF_Indi(void):
                     year(0),
                     mon(1),
                     day(2),
                     hour(3),
                     min(4),
                     sec(5),
                     dow(6),
                     doy(7),
                     fbar(125),
                     star(181),
                     maxbar(3),
                     pospos(0),
                     postop(0),
                     posbot(1),
                     tstar(217),
                     bstar(218),
                     tfhalf(11),
                     scaleX(35),
                     scaleA(36),
                     scaleY(50),
                     offsetY(18),
                     offsetX(120),
                     fontSize(7),
                     cbartime(0),
                     posisi(""),
                     sigpos(""),
                     msgText(""),
                     curAlert(0),
                     prvAlert(0),
                     windsize(12),
                     windchar(108),
                     CI(ChartID()),
                     display(false),
                     ObjName("ZigZag_"),
                     font_mode(FontsModel(f_model)),
                     cstar(CharToString((uchar)star)),
                     artop(CharToString((uchar)tstar)),
                     arbot(CharToString((uchar)bstar)),
                     InHname("Examples\\ZigZag.ex5"),
                     indname(MQLInfoString(MQL_PROGRAM_NAME))
     {
     }
   //---
   //- Destructor
                    ~MTF_Indi(void)
     {
     }
   //---
   //---
   virtual void      VZZ_MTF_Config(void)
     {
      //--
      ENUM_TIMEFRAMES TFIx[]= {PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,
                               PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,
                               PERIOD_D1,PERIOD_W1,PERIOD_MN1};
      tfxar=ArraySize(TFIx);
      ArrayResize(TFId,tfxar,tfxar);
      ArrayResize(Arwcolor,tfxar,tfxar);
      ArrayCopy(TFId,TFIx,0,0,WHOLE_ARRAY);
      //--
      string TFxc[]= {"M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30","H1",
                      "H2","H3","H4","H6","H8","H12","D1","W1","MN1"}; // 21 Timeframes
      //--
      ArrayResize(hZigZag,tfxar,tfxar);
      ArrayResize(TFSc,tfxar,tfxar);
      ArrayCopy(TFSc,TFxc,0,0,WHOLE_ARRAY);
      //--
      if(zzDepth<5 || zzDepth>fbar)
        {
         ZZ_Period=12;
         PrintFormat("Incorrect value for input variable zzDepth = %d. Indicator will use value %d for calculations.",
                  zzDepth,ZZ_Period);
        }
      else
         ZZ_Period=zzDepth;
      //--
      ttlbars=fbar;
      //--
      for(int x=0; x<tfxar; x++)
        hZigZag[x]=iCustom(Symbol(),TFId[x],InHname,ZZ_Period,zzDevia,zzBackS); // Handle of ZigZag Indicator on each timeframe
      //--
      DeletedZigZagObject();
      ZigZagMovementCalculation(25);
      PositionCore();
      //--
      if(display)
         DrawZigZagObject();
      //---
     }
   //---
   //---
   void              PositionCore(void)
     {
      corpos=pospos;
      if(corpos>-1)
        {
         if(corpos==postop)
           {
            bcor=CORNER_LEFT_UPPER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=13;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=39;
            vertiL2=18;
            vertiL3=69;
            vertiL4=48;
            vertiL5=52;
            vertiL6=67;
            TNamex=554;
            TNamexn=562;
            TNamey1=30;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=38;
            TNamey2n=54;
            TNamey3n=70;
            hName1="Z";
            hName2="Z";
            hName3="I";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("arbot");
            //--
           }
         if(corpos==posbot)
           {
            bcor=CORNER_LEFT_LOWER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=74;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=34;
            vertiL2=29;
            vertiL3=65;
            vertiL4=59;
            vertiL5=49;
            vertiL6=61;
            TNamex=554;
            TNamexn=562;
            TNamey1=13;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=18;
            TNamey2n=33;
            TNamey3n=49;
            hName1="I";
            hName2="Z";
            hName3="Z";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("artop");
            //--
           }
         display=true;
        }
     }
   //---
   //---
   void              DrawZigZagObject(void)
     {
      //--
      CreateButtonTemplate(CI,ObjName+"Template",397,66,STYLE_SOLID,9,BORDER_RAISED,clrMistyRose,clrLavenderBlush,clrWhite,bcor,corx,cory,true);
      for(int x=0; x<tfhalf; x++)
        {
         CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                             txttf+horizL1+(x*scaleX)+offsetX+x,vertiL1,true,"Arrow_"+TFSc[x]);
         CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                              bcor,txttf+horizL2+(x*scaleA)+offsetX,vertiL2,true,
                              "Change Timeframe to : "+TFSc[x]);
        }
      for(int x=tfhalf, x2=0; x<tfxar; x++, x2++)
        {
         CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x),CharToString((uchar)windchar),"Wingdings",windsize,Arwcolor[x],bcor,
                             txttf+horizL3+(x2*scaleX)+offsetX+x2,vertiL3,true,"Arrow_"+TFSc[x]);
         CreateButtonClick(CI,TFSc[x],27,15,font_mode,fontSize,BORDER_FLAT,TFSc[x],clrBurlyWood,clrSilver,clrBlue,
                              bcor,txttf+horizL4+(x2*scaleA)+offsetX,vertiL4,true,
                              "Change Timeframe to : "+TFSc[x]);
         //--
         if(x==20)
           {
            int arrowChar=TColor==ArrowUp ? 200 : TColor==ArrowDn ? 202 : windchar;
            CreateArrowLabel(CI,ObjName+"_tfx_arrow_"+string(x+1),"Move",font_mode,fontSize,clrBlue,bcor,
                                519+horizL5,vertiL5,true,"Move");
            CreateArrowLabel(CI,ObjName+"_win_arrow_"+string(x+1),CharToString((uchar)arrowChar),"Wingdings",15,TColor,bcor,
                                522+horizL6,vertiL6,true,"Arrow Indicator Movement");
           }
        }
      DisplayButtonClick("X");
      CreateButtonTemplate(CI,ObjName+"TemplateName1",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey1,true);
      CreateButtonTemplate(CI,ObjName+"TemplateName2",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey2,true);
      CreateButtonTemplate(CI,ObjName+"TemplateName3",17,15,STYLE_SOLID,1,BORDER_FLAT,clrMistyRose,clrLavenderBlush,clrWhite,bcor,TNamex,TNamey3,true);
      CreateArrowLabel(CI,ObjName+"_name1",hName1,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey1n,true,hName1);
      CreateArrowLabel(CI,ObjName+"_name2",hName2,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey2n,true,hName2);
      CreateArrowLabel(CI,ObjName+"_name3",hName3,font_mode,fontSize+1,clrBlue,bcor,TNamexn,TNamey3n,true,hName3);
      //--
      if(corpos==postop)
        {
          DisplayButtonClick("cstar");
          DisplayButtonClick("arbot");
        }
      if(corpos==posbot)
        {
          DisplayButtonClick("cstar");
          DisplayButtonClick("artop");
        }
      //--
      return;
      //---
     } //-end DrawZigZagObject()
   //---
   //---
   void              PanelPosChange(int inpos)
     {
      corpos=inpos;
      //--
      if(inpos>=0)
        {
         if(inpos==postop)
           {
            bcor=CORNER_LEFT_UPPER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=13;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=39;
            vertiL2=18;
            vertiL3=69;
            vertiL4=48;
            vertiL5=52;
            vertiL6=67;
            TNamex=554;
            TNamexn=562;
            TNamey1=30;
            TNamey2=46;
            TNamey3=62;
            TNamey1n=38;
            TNamey2n=54;
            TNamey3n=70;
            hName1="Z";
            hName2="Z";
            hName3="I";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("arbot");
            //--
           }
         if(inpos==posbot)
           {
            bcor=CORNER_LEFT_LOWER;
            ancp=ANCHOR_CENTER;
            corx=155;
            cory=74;
            txttf=45;
            horizL1=8;
            horizL2=-5;
            horizL3=8;
            horizL4=-5;
            horizL5=11;
            horizL6=10;
            vertiL1=34;
            vertiL2=29;
            vertiL3=65;
            vertiL4=59;
            vertiL5=49;
            vertiL6=61;
            TNamex=554;
            TNamexn=562;
            TNamey1=25;
            TNamey2=41;
            TNamey3=57;
            TNamey1n=18;
            TNamey2n=33;
            TNamey3n=49;
            hName1="I";
            hName2="Z";
            hName3="Z";
            //--
            DisplayButtonClick("cstar");
            DisplayButtonClick("artop");
            //--
           }
         display=true;
        }
      //---
     }
   //---
   //---
   void              UpdatePrice(ENUM_TIMEFRAMES xtf)
     {
      maxbar=fbar;
      //--
      ArrayFree(OPEN);
      ArrayFree(HIGH);
      ArrayFree(LOW);
      ArrayFree(CLOSE);
      ArrayFree(TIME);
      ArrayFree(VOLUME);
      //--
      ArrayResize(OPEN,maxbar,maxbar);
      ArrayResize(HIGH,maxbar,maxbar);
      ArrayResize(LOW,maxbar,maxbar);
      ArrayResize(CLOSE,maxbar,maxbar);
      ArrayResize(TIME,maxbar,maxbar);
      ArrayResize(VOLUME,maxbar,maxbar);
      //--
      ArraySetAsSeries(OPEN,true);
      ArraySetAsSeries(HIGH,true);
      ArraySetAsSeries(LOW,true);
      ArraySetAsSeries(CLOSE,true);
      ArraySetAsSeries(TIME,true);
      ArraySetAsSeries(VOLUME,true);
      //--
      ArrayInitialize(OPEN,0.0);
      ArrayInitialize(HIGH,0.0);
      ArrayInitialize(LOW,0.0);
      ArrayInitialize(CLOSE,0.0);
      ArrayInitialize(TIME,0);
      ArrayInitialize(VOLUME,0);
      //--
      int barx=PeriodSeconds(xtf)/60*maxbar;
      RefreshPrice(PERIOD_M1,maxbar);
      RefreshPrice(xtf,barx);
      //--
      int co=CopyOpen(Symbol(),xtf,0,maxbar,OPEN);
      int ch=CopyHigh(Symbol(),xtf,0,maxbar,HIGH);
      int cl=CopyLow(Symbol(),xtf,0,maxbar,LOW);
      int cc=CopyClose(Symbol(),xtf,0,maxbar,CLOSE);
      int ct=CopyTime(Symbol(),xtf,0,maxbar,TIME);
      int cv=CopyTickVolume(Symbol(),xtf,0,maxbar,VOLUME);
      //--
      return;
      //---
     } //-end UpdatePrice()
   //---
   //---
   void              RefreshPrice(ENUM_TIMEFRAMES xtf,int bars)
     {
      //--
      MqlRates parray[];
      ArraySetAsSeries(parray,true);
      int copied=CopyRates(Symbol(),xtf,0,bars,parray);
      //--
      return;
      //---
     } //-end RefreshPrice()
   //---
   //---
   int               ZigZagDirectionScan(const ENUM_TIMEFRAMES stf) // Scan ZigZag Direction
     {
      //--
      int ret=0;
      int rise=1,
          down=-1;
      int zzH=-1;
      int zzL=-1;
      //--
      bool ZZUps=false;
      bool ZZDwn=false;
      //--
      double res=0.0;
      UpdatePrice(stf);
      //--
      double VZZ[];
      ArrayResize(VZZ,fbar,fbar);
      ArraySetAsSeries(VZZ,true);
      //--
      int xx=TFIndexArray(stf);
      CopyBuffer(hZigZag[xx],0,0,fbar,VZZ);
      //--
      for(int i=fbar-1; i>=0; i--)
        {
          if(VZZ[i]==HIGH[i]) zzH=i;
          if(VZZ[i]==LOW[i])  zzL=i; 
        }
      //--
      ZZUps=(zzL<zzH && zzL>0)||(zzL>zzH && zzH==0);
      ZZDwn=(zzH<zzL && zzH>0)||(zzH>zzL && zzL==0);
      //--
      if(ZZUps) ret=rise; 
      if(ZZDwn) ret=down;
      //--
      return(ret);
      //---
     } //-end ZigZagDirectionScan()
   //---
   //---
   void              ZigZagMovementCalculation(int barCnt) // Scan the direction of ZigZag on each timeframe
     {
      //--
      ArrayResize(PowerMove,barCnt,barCnt);
      ArraySetAsSeries(PowerMove,true);
      //--
      for(int i=barCnt-1; i>=0; i--)
        {
         up=0;
         dw=0;
         //--
         for(int x=0; x<tfxar; x++)
           {
            Arwcolor[x]=NTArrow;
            PowerMove[i]=0.0;
            int PPM=ZigZagDirectionScan(TFId[x]);
            //--
            if(PPM>0)
              {
               up++;
               Arwcolor[x]=ArrowUp;
              }
            if(PPM<0)
              {
               dw++;
               Arwcolor[x]=ArrowDn;
              }
            //--
            if(x<12)
              {
                //--
                if(up>dw+1)
                  {
                   PowerMove[i]=1.0;
                   TColor=ArrowUp;
                   curAlert=1;
                  }
                if(dw>up+1)
                  {
                   PowerMove[i]=-1.0;
                   TColor=ArrowDn;
                   curAlert=-1;
                  }
              }
           }
        }
      //--
      return;
      //---
     } //-end ZigZagMovementCalculation()
   //---
   //---
   double NonZeroDiv(double val1,double val2)
     {
      //--
      double resval=0;
      if(val1==0.0 || val2==0.0) resval=0.00;
      else
      resval=val1/val2;
      //--
      return(resval);
      //---
     } //-end NonZeroDiv()
   //---
   //---
   int TFIndexArray(ENUM_TIMEFRAMES TF)
     {
      //--
      int res=-1;
      //--
      for(int x=0; x<tfxar; x++)
        {
          if(TF==TFId[x])
            {
              res=x;
              break;
            }
        }
      //--
      return(res);
      //---
     } //-end TFIndexArray()
   //---
   //---
   int               ThisTime(const int reqmode)
     {
      //--
      MqlDateTime tm;
      TimeCurrent(tm);
      int valtm=0;
      //--
      switch(reqmode)
        {
         case 0:
            valtm=tm.year;
            break;        // Return Year
         case 1:
            valtm=tm.mon;
            break;        // Return Month
         case 2:
            valtm=tm.day;
            break;        // Return Day
         case 3:
            valtm=tm.hour;
            break;        // Return Hour
         case 4:
            valtm=tm.min;
            break;        // Return Minutes
         case 5:
            valtm=tm.sec;
            break;        // Return Seconds
         case 6:
            valtm=tm.day_of_week;
            break;        // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
         case 7:
            valtm=tm.day_of_year;
            break;        // Return Day number of the year (January 1st is assigned the number value of zero)
        }
      //--
      return(valtm);
      //---
     } //-end ThisTime()
   //---
   //---
   void              Do_Alerts(string msg)
     {
      //--
      Print(indname," --- "+Symbol()+","+strTF(Period())+": "+msg+
            "\n--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
      //--
      if(alerts==Yes)
        {
         Alert(indname," --- "+Symbol()+","+strTF(Period())+": "+msg+
               "--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
        }
      //--
      if(UseEmailAlert==Yes)
         SendMail(indname," --- "+Symbol()+" "+strTF(Period())+": "+msg+
                  "\n--- at: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
      //--
      if(UseSendnotify==Yes)
         SendNotification(indname+" --- "+Symbol()+" "+strTF(Period())+": "+msg+
                          "\n--- at: "+TimeToString(iTime(Symbol(),0,0),TIME_DATE|TIME_MINUTES));
      //--
      return;
      //---
     } //-end Do_Alerts()
   //---
   //---
   string            FontsModel(int mode)
     {
      string str_font;
      switch(mode)
        {
         case 0:
            str_font="Verdana";
            break;
         case 1:
            str_font="Bodoni MT Black";
            break;
        }
      //--
      return(str_font);
      //---
     } //-end FontsModel()
   //---
   //---
   void              ChangeChartSymbol(string tf_name,ENUM_TIMEFRAMES stf)
     {
      //---
      //--- unpress the button
      ObjectSetInteger(CI,tf_name,OBJPROP_STATE,false);
      ObjectSetInteger(CI,tf_name,OBJPROP_ZORDER,0);
      //--
      DeletedZigZagObject();
      PanelPosChange(corpos);
      ChartSetSymbolPeriod(CI,Symbol(),stf);
      if(display)
         DrawZigZagObject();
      //--
      ChartRedraw(CI);
      //--
      return;
      //---
     } //-end ChangeChartSymbol()
   //---
   //---
   void              DisplayPanelButton(void)
     {
      //--
      ObjectDelete(CI,cstar);
      ObjectDelete(CI,artop);
      ObjectDelete(CI,arbot);
      //--
      CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
      CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
      CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
      //--
      ChartRedraw(CI);
      //--
      return;
      //---
     } //-end DisplayPanelButton()
   //---
   //---
   void              DisplayButtonClick(string actreq)
     {
      //--
      if(actreq=="cstar")
         CreateButtonClick(CI,cstar,20,20,"Wingdings",13,BORDER_FLAT,cstar,clrWhite,clrWhite,TColor,CORNER_RIGHT_UPPER,25,40,true,"Open Panel Indicator");
      if(actreq=="artop")
         CreateButtonClick(CI,artop,18,18,"Wingdings",11,BORDER_FLAT,artop,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,20,true,"Change Panel to Top");
      if(actreq=="arbot")
         CreateButtonClick(CI,arbot,18,18,"Wingdings",11,BORDER_FLAT,arbot,clrWhite,clrWhite,clrGreen,CORNER_RIGHT_UPPER,24,62,true,"Change Panel to Bottom");
      if(actreq=="X")
         CreateButtonClick(CI,"X",17,15,"Arial Black",fontSize,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,bcor,txttf-7+(11*scaleA)+offsetX,cory,true,"Close Panel");
      //--
      ChartRedraw(CI);
      //--
      return;
      //---
     } //-end DisplayButtonClick()
   //---
   //---
   void              DeletedZigZagObject(void)
     {
      //--
      string name;
      for(int i=ObjectsTotal(CI,-1,-1)-1; i>=0; i--)
        {
         name=ObjectName(CI,i,-1,-1);
         if(StringFind(name,ObjName,0)>-1)
            ObjectDelete(CI,name);
         for(int x=0; x<tfxar; x++)
           {
            if(StringFind(name,TFSc[x],0)>-1)
               ObjectDelete(CI,name);
           }
         //--
         ObjectDelete(CI,"X");
         ObjectDelete(CI,cstar);
         ObjectDelete(CI,artop);
         ObjectDelete(CI,arbot);
        }
      //--
      return;
      //---
     } //-end DeletedZigZagObject()
   //---
   //---
   string            strTF(ENUM_TIMEFRAMES period)
     {
      string intf="";
      //--
      switch(period)
        {
         //--
         case PERIOD_M1:
           {intf="M1";  break;}
         case PERIOD_M2:
           {intf="M2";  break;}
         case PERIOD_M3:
           {intf="M3";  break;}
         case PERIOD_M4:
           {intf="M4";  break;}
         case PERIOD_M5:
           {intf="M5";  break;}
         case PERIOD_M6:
           {intf="M6";  break;}
         case PERIOD_M10:
           {intf="M10"; break;}
         case PERIOD_M12:
           {intf="M12"; break;}
         case PERIOD_M15:
           {intf="M15"; break;}
         case PERIOD_M20:
           {intf="M20"; break;}
         case PERIOD_M30:
           {intf="M30"; break;}
         case PERIOD_H1:
           {intf="H1";  break;}
         case PERIOD_H2:
           {intf="H2";  break;}
         case PERIOD_H3:
           {intf="H3";  break;}
         case PERIOD_H4:
           {intf="H4";  break;}
         case PERIOD_H6:
           {intf="H6";  break;}
         case PERIOD_H8:
           {intf="H8";  break;}
         case PERIOD_H12:
           {intf="H12"; break;}
         case PERIOD_D1:
           {intf="D1";  break;}
         case PERIOD_W1:
           {intf="W1";  break;}
         case PERIOD_MN1:
           {intf="MN1"; break;}
            //--
        }
      return(intf);
      //---
     } //-end strTF()
   //---
   //---
   string            getUninitReasonText(int reasonCode)
     {
      //--
      string text="";
      //--
      switch(reasonCode)
        {
         case REASON_PROGRAM:
            text="The EA has stopped working calling by remove function.";
            break;
         case REASON_REMOVE:
            text="Program "+__FILE__+" was removed from chart";
            break;
         case REASON_RECOMPILE:
            text="Program recompiled.";
            break;
         case REASON_CHARTCHANGE:
            text="Symbol or timeframe was changed";
            break;
         case REASON_CHARTCLOSE:
            text="Chart was closed";
            break;
         case REASON_PARAMETERS:
            text="Input-parameter was changed";
            break;
         case REASON_ACCOUNT:
            text="Account was changed";
            break;
         case REASON_TEMPLATE:
            text="New template was applied to chart";
            break;
         case REASON_INITFAILED:
            text="The OnInit() handler returned a non-zero value.";
            break;
         case REASON_CLOSE:
            text="Terminal closed.";
            break;
         default:
            text="Another reason";
            break;
        }
      //--
      return text;
      //---
     } //-end getUninitReasonText()
   //---
   //---
   int               WS(int width) // Width Scaling factor wide button
     {
      //--
      int res=0;
      int reswidth=0;
      //-- Calculating the scaling factor wide button on a screen
      int scale_factor=(TerminalInfoInteger(TERMINAL_SCREEN_DPI));
      // The basic width in the screen points for standard monitors with DPI=96
      //-- Use of the scaling factor
      reswidth=(width * scale_factor) / 96;
      res=(int)NormalizeDouble(reswidth*1.25,0);
      //--
      return(res);
      //---
     } //-end WS()
   //---
   //---
   void              CreateButtonClick(long   chartid,
                                       string button_name,
                                       int    button_x_size,
                                       int    button_y_size,
                                       string button_font_model,
                                       int    button_font_size,
                                       int    button_border,
                                       string button_name_text,
                                       color  button_bord_color,
                                       color  button_bg_color,
                                       color  button_color,
                                       int    button_corner,
                                       int    button_xdist,
                                       int    button_ydist,
                                       bool   button_hidden,
                                       string tooltip)
     {
      //--
      ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
      ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size));
      ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,WS(button_y_size));
      ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text);
      ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
      ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,WS(button_font_size));
      ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,WS(button_border));
      ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
      ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color);
      ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
      ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,ancp);
      ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner);
      ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
      ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,WS(button_ydist));
      ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
      ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
      ChartRedraw(chartid);
      //--
      return;
      //---
     } //-end CreateButtonClick()
   //---
   //---
   bool              CreateArrowLabel(long   chart_id,
                                      string lable_name,
                                      string label_text,
                                      string font_model,
                                      int    font_size,
                                      color  label_color,
                                      int    chart_corner,
                                      int    x_cor,
                                      int    y_cor,
                                      bool   price_hidden,
                                      string tooltip)
     {
      //--
      ObjectDelete(chart_id,lable_name);
      //--
      if(!ObjectCreate(chart_id,lable_name,OBJ_LABEL,0,0,0,0,0)) // create Label
        {
         Print(__FUNCTION__, ": failed to create \"Arrow Label\" sign! Error code = ",GetLastError());
         return(false);
        }
      //--
      ObjectSetString(chart_id,lable_name,OBJPROP_TEXT,label_text);
      ObjectSetString(chart_id,lable_name,OBJPROP_FONT,font_model);
      ObjectSetInteger(chart_id,lable_name,OBJPROP_FONTSIZE,WS(font_size));
      ObjectSetInteger(chart_id,lable_name,OBJPROP_COLOR,label_color);
      ObjectSetInteger(chart_id,lable_name,OBJPROP_CORNER,chart_corner);
      ObjectSetInteger(chart_id,lable_name,OBJPROP_ANCHOR,ancp);
      ObjectSetInteger(chart_id,lable_name,OBJPROP_XDISTANCE,WS(x_cor));
      ObjectSetInteger(chart_id,lable_name,OBJPROP_YDISTANCE,WS(y_cor));
      ObjectSetInteger(chart_id,lable_name,OBJPROP_HIDDEN,price_hidden);
      ObjectSetString(chart_id,lable_name,OBJPROP_TOOLTIP,tooltip);
      //-- successful execution
      return(true);
      //---
     } //-end CreateArrowLabel()
   //---
   //---
   void              CreateButtonTemplate(long chartid,
                                          string obj_name,
                                          int    x_size,
                                          int    y_size,
                                          int    style,
                                          int    width,
                                          int    border,
                                          color  bordcolor,
                                          color  bgcolor,
                                          color  objcolor,
                                          int    corner,
                                          int    x_dist,
                                          int    y_dist,
                                          bool   hidden)
     {
      //--
      ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
      ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size));
      ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,WS(y_size));
      ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
      ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,WS(width));
      ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,WS(border));
      ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
      ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor);
      ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
      ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner);
      ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
      ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,WS(y_dist));
      ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
      ChartRedraw(chartid);
      //--
      return;
      //---
     } //-end CreateButtonTemplate()
   //---
   //---
  }; //-end class MTF_Indi()
//---------//

MTF_Indi mi;

//---------//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   mi.VZZ_MTF_Config();
//--
   SetIndexBuffer(0,mi.PowerMove,INDICATOR_DATA);
   PlotIndexSetString(0,PLOT_LABEL,"ZZMTF_Move");
//--
   IndicatorSetString(INDICATOR_SHORTNAME,mi.indname);
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//---
   return(INIT_SUCCEEDED);
  }
//---------//
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
   Print(mi.getUninitReasonText(reason));
   //-- Release all handle indicators for all symbols
   for(int x=0; x<mi.tfxar; x++) 
     IndicatorRelease(mi.hZigZag[x]);
//--
   mi.DeletedZigZagObject();
//--
   ChartRedraw(mi.CI);
//---
   return;
//---
  } //-end OnDeinit()
//-------//
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   ResetLastError();
   //--
   int limit;
   limit=rates_total-prev_calculated;
   if(prev_calculated>0)
      limit++;
   if(limit>mi.ttlbars)
      limit=mi.ttlbars;
   if(limit-3<=1)
      limit=3;
   //--
   mi.ZigZagMovementCalculation(limit);
   //--
   if(alerts==Yes||UseEmailAlert==Yes||UseSendnotify==Yes)
     {
       mi.curmin=mi.ThisTime(mi.min);
       if(mi.curmin!=mi.prvmin && mi.curAlert==1 && mi.curAlert!=mi.prvAlert)
         {
           string AlertTxt="The strength of the ZigZag movement appears to be Rise.";
           mi.Do_Alerts(AlertTxt);
           mi.prvAlert=mi.curAlert;
           mi.prvmin=mi.curmin;
         }
       if(mi.curmin!=mi.prvmin && mi.curAlert==-1 && mi.curAlert!=mi.prvAlert)
         {
           string AlertTxt="The strength of the ZigZag movement appears to be Down.";
           mi.Do_Alerts(AlertTxt);
           mi.prvAlert=mi.curAlert;
           mi.prvmin=mi.curmin;
         }
     }
   //--
   if(mi.display)
     mi.DrawZigZagObject();
   //---
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//---------//
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
   ResetLastError();
//--
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- if "X" button is click
      if(sparam=="X")
        {
         mi.DeletedZigZagObject();
         //--- unpress the button
         ObjectSetInteger(mi.CI,"X",OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,"X",OBJPROP_ZORDER,0);
         //--
         mi.display=false;
         ObjectDelete(mi.CI,"X");
         mi.DisplayPanelButton();
        }
      //--- if "cstar" button is click
      if(sparam==mi.cstar)
        {
         mi.DeletedZigZagObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.cstar,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         if(mi.corpos==mi.posbot) ObjectDelete(mi.CI,mi.arbot);
         if(mi.corpos==mi.postop) ObjectDelete(mi.CI,mi.artop);
         mi.DrawZigZagObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "artop" button is click
      if(sparam==mi.artop)
        {
         mi.DeletedZigZagObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.artop,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.artop);
         mi.PanelPosChange(mi.postop);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("arbot");
         mi.DrawZigZagObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if "arbot" button is click
      if(sparam==mi.arbot)
        {
         mi.DeletedZigZagObject();
         mi.DisplayPanelButton();
         //--- unpress the button
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_STATE,false);
         ObjectSetInteger(mi.CI,mi.arbot,OBJPROP_ZORDER,0);
         if(!mi.display)
            mi.display=true;
         ObjectDelete(mi.CI,mi.arbot);
         mi.PanelPosChange(mi.posbot);
         //--
         ObjectDelete(mi.CI,"X");
         mi.DisplayButtonClick("artop");
         mi.DrawZigZagObject();
         //--
         ChartRedraw(mi.CI);
        }
      //--- if TF button is click
      //--
      if(sparam==mi.TFSc[0])
        {
         mi.ChangeChartSymbol(mi.TFSc[0],mi.TFId[0]);
        }
      //--
      if(sparam==mi.TFSc[1])
        {
         mi.ChangeChartSymbol(mi.TFSc[1],mi.TFId[1]);
        }
      //--
      if(sparam==mi.TFSc[2])
        {
         mi.ChangeChartSymbol(mi.TFSc[2],mi.TFId[2]);
        }
      //--
      if(sparam==mi.TFSc[3])
        {
         mi.ChangeChartSymbol(mi.TFSc[3],mi.TFId[3]);
        }
      //--
      if(sparam==mi.TFSc[4])
        {
         mi.ChangeChartSymbol(mi.TFSc[4],mi.TFId[4]);
        }
      //--
      if(sparam==mi.TFSc[5])
        {
         mi.ChangeChartSymbol(mi.TFSc[5],mi.TFId[5]);
        }
      //--
      if(sparam==mi.TFSc[6])
        {
         mi.ChangeChartSymbol(mi.TFSc[6],mi.TFId[6]);
        }
      //--
      if(sparam==mi.TFSc[7])
        {
         mi.ChangeChartSymbol(mi.TFSc[7],mi.TFId[7]);
        }
      //--
      if(sparam==mi.TFSc[8])
        {
         mi.ChangeChartSymbol(mi.TFSc[8],mi.TFId[8]);
        }
      //--
      if(sparam==mi.TFSc[9])
        {
         mi.ChangeChartSymbol(mi.TFSc[9],mi.TFId[9]);
        }
      //--
      if(sparam==mi.TFSc[10])
        {
         mi.ChangeChartSymbol(mi.TFSc[10],mi.TFId[10]);
        }
      //--
      if(sparam==mi.TFSc[11])
        {
         mi.ChangeChartSymbol(mi.TFSc[11],mi.TFId[11]);
        }
      //--
      if(sparam==mi.TFSc[12])
        {
         mi.ChangeChartSymbol(mi.TFSc[12],mi.TFId[12]);
        }
      //--
      if(sparam==mi.TFSc[13])
        {
         mi.ChangeChartSymbol(mi.TFSc[13],mi.TFId[13]);
        }
      //--
      if(sparam==mi.TFSc[14])
        {
         mi.ChangeChartSymbol(mi.TFSc[14],mi.TFId[14]);
        }
      //--
      if(sparam==mi.TFSc[15])
        {
         mi.ChangeChartSymbol(mi.TFSc[15],mi.TFId[15]);
        }
      //--
      if(sparam==mi.TFSc[16])
        {
         mi.ChangeChartSymbol(mi.TFSc[16],mi.TFId[16]);
        }
      //--
      if(sparam==mi.TFSc[17])
        {
         mi.ChangeChartSymbol(mi.TFSc[17],mi.TFId[17]);
        }
      //--
      if(sparam==mi.TFSc[18])
        {
         mi.ChangeChartSymbol(mi.TFSc[18],mi.TFId[18]);
        }
      //--
      if(sparam==mi.TFSc[19])
        {
         mi.ChangeChartSymbol(mi.TFSc[19],mi.TFId[19]);
        }
      //--
      if(sparam==mi.TFSc[20])
        {
         mi.ChangeChartSymbol(mi.TFSc[20],mi.TFId[20]);
        }
      //--
     }
//---
  } //-end OnChartEvent()
//---------//

Please download the ZigZag_MTF indicator: ZigZag_MTF


© 2026 ZigZag_MTF - Developed by Roberto Jacobs (3rjfx)

Saturday, January 31, 2026

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert

1. Introduction

In the world of technical analysis, the ZigZag indicator is legendary for its ability to filter market noise and highlight the true structure of the market—its peaks and troughs. However, every veteran trader knows its greatest weakness: it repaints. A confirmed low today can disappear tomorrow if the price continues to drop.

To solve this, I developed ZigZag Reverses, an indicator that doesn't just track price; it measures Momentum Energy based on the laws of physics.

NZDUSDH1_ZigZag_Reverses_Black Figure 1: ZigZag_Reverses indicator for MT5 display with 70% threshold line

2. The Newtonian Philosophy: Force and Inertia

My inspiration for this indicator comes from Sir Isaac Newton’s Laws of Motion. Imagine a ball being thrown against the floor. The initial force (the trend) creates a massive bounce. However, as gravity and friction take over, the energy dissipates.

In trading, when a price hits an extremum (High or Low), it possesses 100% of that trend's force. For a reversal to be mathematically and physically probable, that force must decay past a certain threshold. Through my observations, the 30% and 70% levels act as the Threshold of No Return.

NZDUSDM1_ZigZag_ReversesFigure 2: ZigZag Reverses indicator for MT5 display with 70% threshold line - Price Reverses Rice to Down

3. How ZigZag Reverses Works

Unlike standard ZigZag, this indicator calculates two dynamic confirmation lines based on the most recent price swing:

  • The 70% Fall Line (Highest to Fall): After a Peak is formed, we don't assume a reversal immediately. We wait for the price to drop below 70% of the previous swing's range. If the Close Price breaks this level, the bullish momentum is physically exhausted, confirming a Bearish Reversal.
  • NZDUSDD1_ZigZag_Reverses_Rise_to_Down Figure 3: Price breaking the 70% threshold, confirming a bearish momentum shift
  • The 30% Rise Line (Lowest to Rise): Conversely, after a Trough, we wait for the price to climb above the 30% mark. Breaking this level confirms that the selling pressure has faded and a Bullish Reversal is in play.
  • NZDUSDM10_ZigZag_Reverses_Down_to_Rise Figure 4: Price breaking the 30% threshold, confirming a bullish momentum shift

4. Why Close Price Matters

The indicator is programmed to be objective. It creates a TrendLine on the chart to visualize these thresholds. As per my testing, if a bar closes beyond these lines, the probability of the trend continuing in the new direction increases significantly. It is no longer a guess—it is a confirmation of shifting market force.

5. Input Parameters Properties

ZigZag_Reverses_Input_Properties Figure 5: ZigZag Reverses Indicator Input Parameters Properties

6. Technical Specifications:

  • Dynamic Thresholds: Customizable `updown` and `downup` percentages to suit different market volatilities.
  • Visual Confirmation: Automatic horizontal lines marking the breakout zones.
  • Clean Logic: Built with high-performance MQL5 code, ensuring zero lag in calculation.

7. Practical Strategy for Manual Traders

To maximize the effectiveness of the ZigZag Reverses indicator, manual traders can utilize a set-and-forget approach using Pending Orders. Once the ZigZag extremum is stabilized (no longer repainting), follow these steps:

  • Bullish Confirmation: When a stable Extremum Low is identified, traders can place a BUY_STOP order exactly at the 30% Line. This ensures an entry only when the upward momentum is physically confirmed by the price breaking the threshold.
  • Bearish Confirmation: When a stable Extremum High is identified, traders can place a SELL_STOP order exactly at the 70% Line. This ensures you are selling only when the price has officially "exhausted" its bullish force and crossed into the reversal zone.

⚠️ Important: Risk Disclaimer

Trading foreign exchange on margin carries a high level of risk and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to invest in foreign exchange, you should carefully consider your investment objectives, level of experience, and risk appetite. The Newtonian logic and indicators provided in this article are for educational purposes and do not guarantee profits. Past performance is not indicative of future results.

8. Conclusion

Trading shouldn't be about catching falling knives; it should be about measuring the weight of the market. By applying the principles of Newtonian mechanics to the ZigZag structure, we transform a repainting tool into a reliable momentum gauge.

9. Vital Records

If you think the ZigZag Reverses Indicator is worthy of being used for automated trading as an Expert Advisor, please leave a comment below this article.

If at least 25 people agree that this indicator is worthy of being used as an Expert Advisor, I will create an Expert Advisor based on its signals and share it on this blog.

Thanks for reading this article.

Risk Warning: Trading Forex and CFDs involves significant risk and may not be suitable for all investors. All content provided is for educational purposes only.


//+------------------------------------------------------------------+
//|                                              ZigZag Reverses.mq5 |
//|        Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-01-30 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-01-30"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property indicator_chart_window
//--
//---
#property indicator_buffers 3
#property indicator_plots   3
//---
#property indicator_type1   DRAW_NONE
#property indicator_type2   DRAW_NONE
#property indicator_type3   DRAW_NONE
//--
//--- input parameters
input int          ZDepth = 25;            // Input Zigzag Depth
input int      ZDeviation = 5;             // Input Zigzag Deviation
input int       ZBackstep = 3;             // Input Zigzag Backstep
input double       updown = 70.0;          // Highest to Fall (in pct)
input double       downup = 30.0;          // Lowest to Rise (in pct)
input color      contRise = clrWhite;      // Color Line Rise Continue
input color      contDown = clrWhite;      // Color Line Down Continue
input color      revsRise = clrRed;        // Color Line Rise Reverses
input color      revsDown = clrRed;        // Color Line Down Reverses
//--
//--- indicator buffers
double         ZZBuffer[];
double         ZRBuffer[];
double         ZDBuffer[];
//--
int hZ;
//--
string obnm="obzz_";
string iname="Examples\\ZigZag.ex5";
string indiname;
//--
#define RDown updown/100.0
#define DRise downup/100.0
#define DATA_LIMIT  369
//---------//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
    //--
    SetIndexBuffer(0,ZZBuffer,INDICATOR_DATA);
    SetIndexBuffer(1,ZRBuffer,INDICATOR_DATA);
    SetIndexBuffer(2,ZDBuffer,INDICATOR_DATA);
    //--
    hZ=iCustom(Symbol(),0,iname,ZDepth,ZDeviation,ZBackstep);   //-- Handle for the ZigZag indicator
    //--
    if(hZ==INVALID_HANDLE)
      {
        printf("Failed to create handle of the ZigZag indicator for ",Symbol());
        return(INIT_FAILED);
      }
    //--
    PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
    indiname=StringFormat("ZZR(%d,%d,%d)",ZDepth,ZDeviation,ZBackstep);
    IndicatorSetString(INDICATOR_SHORTNAME,indiname);
    PlotIndexSetString(0,PLOT_LABEL,indiname);
    PlotIndexSetString(1,PLOT_LABEL,"Level Rise");
    PlotIndexSetString(2,PLOT_LABEL,"Level Down");
    IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//---
   return(INIT_SUCCEEDED);
  }
//---------//
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
    Comment("");
    //--
    IndicatorRelease(hZ);
    ObjectsDeleteAll(0,obnm,-1,-1);
    //--
    Print(getUninitReasonText(reason));
    //--
    if(reason==REASON_REMOVE)
      {
       PrintFormat("An indicator %s deletes from the chart..!!",indiname,__FILE__);
      }
    //--
//----
   return;
  }  
//---------//
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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;
    int zh=0,zl=0;
    datetime tmi=0;
//---- insufficient data
    if(rates_total<DATA_LIMIT)
       return(0);
//--- last counted bar will be recounted
    limit=rates_total-prev_calculated;
    if(limit==0) limit=DATA_LIMIT;
    if(prev_calculated>0) limit++;
    //--
    int calculated=BarsCalculated(hZ);
    if(calculated<rates_total)
      {
       Print("Not all data of ZigZag Indicator is calculated (",calculated,"bars ). Error",GetLastError());
       return(0);
      }
    //--
    limit=DATA_LIMIT;
    //--
    ArrayResize(ZZBuffer,limit,limit);
    ArrayResize(ZRBuffer,limit,limit);
    ArrayResize(ZDBuffer,limit,limit);
    //--
    ArraySetAsSeries(ZZBuffer,true);
    ArraySetAsSeries(ZRBuffer,true);
    ArraySetAsSeries(ZDBuffer,true);
    ArraySetAsSeries(open,true);
    ArraySetAsSeries(high,true);
    ArraySetAsSeries(low,true);
    ArraySetAsSeries(close,true);
    ArraySetAsSeries(time,true);
    //--
    //--- we can copy not all data
    int to_copy;
    int values_to_copy; 
    if(prev_calculated>rates_total || prev_calculated<0) 
      {
        to_copy=values_to_copy=rates_total;
      }
    else
      {
       to_copy=values_to_copy=rates_total-prev_calculated;
        if(prev_calculated>0) to_copy++; values_to_copy++;
      }
    //--- get ZigZag buffers
    if(IsStopped()) return(0); //Checking for stop flag
    if(CopyBuffer(hZ,0,0,to_copy,ZZBuffer)<0)
      {
       Print("Getting ZigZag indicator buffers is failed! Error",GetLastError());
       return(0);
      }
    //--
    for(i=limit-1; i>=0; i--)
      {
        if(ZZBuffer[i]==high[i]) { zh=i; tmi=time[i+3]; }
        if(ZZBuffer[i]==low[i])  { zl=i; tmi=time[i+3]; }
        ZDBuffer[i]=0.0;
        ZRBuffer[i]=0.0;
        //--
        if(i==0)
          {
            if((zl<zh && zl>0) || (zl>zh && zh==0)) 
              { 
                ZRBuffer[zl]=NormalizeDouble(low[zl]+((high[zh]-low[zl])*DRise),Digits());
                CreateTrendLine(0,obnm+"Price Reverses from Down To Rise_"+DoubleToString(DRise,2)+"(%)",time[0],ZRBuffer[zl],tmi,ZRBuffer[zl],1,STYLE_SOLID,revsDown,false,true);
                for(int x=0; x<zl; x++)
                  {
                    ZRBuffer[x]=ZRBuffer[zl];
                    ZDBuffer[x]=0.0;
                  }
                CreateTrendLine(0,obnm+"ZigZag Bottom ~ Breakout continue to Down",time[0],ZZBuffer[zl],tmi,ZZBuffer[zl],1,STYLE_SOLID,contDown,false,true);
              }
            if((zh<zl && zh>0) || (zh>zl && zl==0)) 
              { 
                ZDBuffer[zh]=NormalizeDouble(low[zl]+((high[zh]-low[zl])*RDown),Digits());
                CreateTrendLine(0,obnm+"Price Reverses from Rise To Down_"+DoubleToString(RDown,2)+"(%)",time[0],ZDBuffer[zh],tmi,ZDBuffer[zh],1,STYLE_SOLID,revsRise,false,true);
                for(int x=0; x<zh; x++)
                  {
                    ZDBuffer[x]=ZDBuffer[zh];
                    ZRBuffer[x]=0.0;
                  }
                CreateTrendLine(0,obnm+"ZigZag Top ~ Breakout continue to Rise",time[0],ZZBuffer[zh],tmi,ZZBuffer[zh],1,STYLE_SOLID,contRise,false,true);
              }
          }
      }
    //--
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//---------//
//+------------------------------------------------------------------+

bool CreateTrendLine(long     chartid, 
                     string   line_name,
                     datetime line_time1,
                     double   line_price1,
                     datetime line_time2,
                     double   line_price2,
                     int      line_width,
                     int      line_style,
                     color    line_color,
                     bool     ray_right,
                     bool     line_hidden)
  {  
//---
   ObjectDelete(chartid,line_name);
   //--
   if(ObjectCreate(chartid,line_name,OBJ_TREND,0,line_time1,line_price1,line_time2,line_price2)) // create trend line
     {
       ObjectSetInteger(chartid,line_name,OBJPROP_WIDTH,line_width);
       ObjectSetInteger(chartid,line_name,OBJPROP_STYLE,line_style);
       ObjectSetInteger(chartid,line_name,OBJPROP_COLOR,line_color);
       ObjectSetInteger(chartid,line_name,OBJPROP_RAY,ray_right);
       ObjectSetInteger(chartid,line_name,OBJPROP_HIDDEN,line_hidden);
     } 
   else 
      {Print("Failed to create the object OBJ_TREND ",line_name,", Error code = ", GetLastError()); return(false);}
   //--
   return(true);
//---
  } //-end CreateTrendLine()   
//---------//

string getUninitReasonText(int reasonCode) 
  { 
//---
   string text=""; 
   //--- 
   switch(reasonCode) 
     { 
       case REASON_PROGRAM:
            text="The EA has stopped working calling by remove function."; break;
       case REASON_REMOVE: 
            text="Program "+__FILE__+" was removed from chart"; break;
       case REASON_RECOMPILE:
            text="Program recompiled."; break;    
       case REASON_CHARTCHANGE: 
            text="Symbol or timeframe was changed"; break;
       case REASON_CHARTCLOSE: 
            text="Chart was closed"; break; 
       case REASON_PARAMETERS: 
            text="Input-parameter was changed"; break;            
       case REASON_ACCOUNT: 
            text="Account was changed"; break; 
       case REASON_TEMPLATE: 
            text="New template was applied to chart"; break; 
       case REASON_INITFAILED:
            text="The OnInit() handler returned a non-zero value."; break;
       case REASON_CLOSE: 
            text="Terminal closed."; break;
       default: text="Another reason"; break;
     } 
   //--
   return text;
//---
  } //-end getUninitReasonText()
//---------//

Please download the ZigZag Reverses indicator: ZigZag Reverses


© 2026 ZigZag Reverses - Developed by Roberto Jacobs (3rjfx)

Wednesday, January 28, 2026

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert

In the fast-paced world of Forex trading, every second counts. Whether you are a professional scalper or a part-time trader, the ability to access tools quickly can be the difference between a winning trade and a missed opportunity.

Many traders struggle with manual calculations—from determining the correct pip value to calculating lot sizes based on risk management. Doing this manually on a website while your MT4/MT5 chart is moving can be distracting.

@Roberto3RJfxbot - TMA_3rjfx.png "Sneak peek of our @Roberto3RJfxbot interface—designed for fast and efficient trading analysis."

This is why we have integrated our advanced trading tools into a seamless **Telegram Mini App (TMA)**. Here is why you should switch:

  • Lightning Fast: No need to wait for heavy websites to load.
  • Mobile Optimized: Designed specifically for your smartphone screen.
  • Integrated with Telegram: You can check signals and calculate risk without leaving your favorite messaging app.
  • Zero Cost: All our premium tools inside the bot are free to use.

Need a faster way to access this tool?
Use our Telegram Mini App directly from your smartphone. No installation required! 🚀


© 2026 Telegram Trading Bot - Developed by Roberto Jacobs (3rjfx)

Featured Post

How to create a simple Multi-Currency Expert Advisor using MQL5 with Zigzag and RSI Indicators Signal

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert Introduction The Expert Advisor discussed in this article is a mult...

OPEN BOT