Multi_Time_Frame_Overview

Author: Copyright 2018, MetaQuotes Software Corp.
Price Data Components
Series array that contains open time of each barSeries array that contains tick volumes of each bar Series array that contains close prices for each bar
Indicators Used
Moving average indicator
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
Multi_Time_Frame_Overview
ÿþ//+------------------------------------------------------------------+

//|                                    Multi_Time_Frame_Overview.mq5 |

//|                        Copyright 2018, MetaQuotes Software Corp. |

//|                                                 https://mql5.com |

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

#property copyright "Copyright 2018, MetaQuotes Software Corp."

#property link      "https://mql5.com"

#property version   "1.00"

#property description "Multi Time Frame Price/MA Overview Panel with alerts"

//--- includes

#include <Canvas\Canvas.mqh>

#include <Arrays\ArrayObj.mqh>

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

//| ;0AA->:=>                                                       |

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

enum ENUM_MOUSE_STATE

  {

   MOUSE_STATE_NOT_PRESSED,

   MOUSE_STATE_PRESSED_OUTSIDE_WINDOW,

   MOUSE_STATE_PRESSED_INSIDE_WINDOW,

   MOUSE_STATE_PRESSED_INSIDE_HEADER,

   MOUSE_STATE_OUTSIDE_WINDOW,

   MOUSE_STATE_INSIDE_WINDOW,

   MOUSE_STATE_INSIDE_HEADER

  };

class CWnd

  {

protected:

   CCanvas           m_canvas;

   CCanvas           m_field;

   long              m_chart_id;

   int               m_chart_w;

   int               m_chart_h;

   int               m_sub_wnd;

   string            m_name;

   string            m_caption;

   string            m_caption_font;

   string            m_name_gv_x;

   string            m_name_gv_y;

   color             m_color_bg;

   color             m_color_border;

   color             m_color_bg_header;

   color             m_color_caption;

   color             m_color_texts;

   uchar             m_alpha_bg;

   uchar             m_alpha_head;

   int               m_x;

   int               m_y;

   int               m_w;

   int               m_h;

   int               m_y_act;

   int               m_caption_font_size;

   uint              m_caption_alignment;

   uint              m_x_caption;

   bool              m_is_visible;

   bool              m_header_on;

   bool              m_movable;

   ENUM_PROGRAM_TYPE m_program_type;  

   ENUM_MOUSE_STATE  m_mouse_state;

   ENUM_MOUSE_STATE  MouseButtonState(const int x,const int y,bool pressed);

   void              Move(int x,int y);

   bool              CreateCanvas(CCanvas &canvas,const int wnd_id,const int x,const int y,const int w,const int h);

   void              DrawHeaderArea(const string caption);

   void              RedrawHeaderArea(const color clr_area,const color clr_caption);

   string            TimeframeToString(const ENUM_TIMEFRAMES timeframe);

   int               CoordX1(void)                             const { return this.m_x;               }

   int               CoordX2(void)                             const { return this.m_x+this.m_w;      }

   int               CoordY1(void)                             const { return this.m_y;               }

   int               CoordY2(void)                             const { return this.m_y+this.m_h;      }

   int               CoordYAct(void)                           const { return this.m_y+this.m_y_act;  }

   color             RGBToColor(const double r,const double g,const double b);

   void              ColorToRGB(const color clr,double &r,double &g,double &b);

   double            GetR(const color clr)                           { return clr&0xff ;              }

   double            GetG(const color clr)                           { return(clr>>8)&0xff;           }

   double            GetB(const color clr)                           { return(clr>>16)&0xff;          }

   int               ChartWidth(void)                          const { return this.m_chart_w;         }

   int               ChartHeight(void)                         const { return this.m_chart_h;         }

public:

   bool              CreateWindow(const string caption_text,const int x,const int y,const int w,const int h,const bool header,bool movable);

   void              Resize(const int w,const int h);

   void              SetColors(const color clr_bg,const color clr_bd,const color clr_hd,const color clr_capt,const color clr_text,uchar alpha_bg=128,uchar alpha_hd=200);

   CCanvas*          GetFieldCanvas(void)                            { return &this.m_field;          }

   void              DrawSeparateVLine(const int x,const int y1,const int y2,const color clr1,const color clr2,const uchar w=1);

   void              DrawSeparateHLine(const int x,const int y1,const int y2,const color clr1,const color clr2,const uchar w=1);

   color             NewColor(color base_color, int shift_red, int shift_green, int shift_blue);

   string            Caption(void)                             const { return this.m_caption;         }

   string            NameCaptionFont(void)                     const { return this.m_caption_font;    }

   color             ColorCaption(void)                        const { return this.m_color_caption;   }

   color             ColorBackground(void)                     const { return this.m_color_bg;        }

   color             ColorHeaderBackground(void)               const { return this.m_color_bg_header; }

   color             ColorTexts(void)                          const { return this.m_color_texts;     }

   void              OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam);

                     CWnd(void);

                    ~CWnd(void);

  };

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

//| CWnd :>=AB@C:B>@                                                 |

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

CWnd::CWnd(void) : m_chart_id(::ChartID()),

                   m_program_type((ENUM_PROGRAM_TYPE)::MQLInfoInteger(MQL_PROGRAM_TYPE)),

                   m_name(::MQLInfoString(MQL_PROGRAM_NAME)),

                   m_name_gv_x(m_name+"_GVX"),

                   m_name_gv_y(m_name+"_GVY"),

                   m_sub_wnd(m_program_type==PROGRAM_EXPERT || m_program_type==PROGRAM_SCRIPT ? 0 : ::ChartWindowFind()),

                   m_chart_w((int)::ChartGetInteger(m_chart_id,CHART_WIDTH_IN_PIXELS,m_sub_wnd)),

                   m_chart_h((int)::ChartGetInteger(m_chart_id,CHART_HEIGHT_IN_PIXELS,m_sub_wnd)),

                   m_caption(""),

                   m_caption_font("Calibri"),

                   m_caption_font_size(-100),

                   m_alpha_bg(128),

                   m_alpha_head(200),

                   m_color_bg(C'200,200,200'),

                   m_color_bg_header(clrDarkGray),

                   m_color_border(clrDarkGray),

                   m_color_caption(clrYellow),

                   m_color_texts(clrSlateGray),

                   m_h(100),

                   m_w(160),

                   m_x(6),

                   m_y(6),

                   m_y_act(10),

                   m_is_visible(false),

                   m_movable(true),

                   m_header_on(true),

                   m_x_caption(4),

                   m_caption_alignment(TA_LEFT|TA_VCENTER),

                   m_mouse_state(MOUSE_STATE_NOT_PRESSED)

  {

   ::ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);

   if(!::GlobalVariableCheck(this.m_name_gv_x))

      ::GlobalVariableSet(this.m_name_gv_x,this.m_x);

   else

      this.m_x=(int)::GlobalVariableGet(this.m_name_gv_x);

   if(!::GlobalVariableCheck(this.m_name_gv_y))

      ::GlobalVariableSet(this.m_name_gv_y,this.m_y);

   else

      this.m_y=(int)::GlobalVariableGet(this.m_name_gv_y);

  }

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

//| CWnd 45AB@C:B>@                                                  |

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

CWnd::~CWnd(void)

  {

   ::ObjectsDeleteAll(this.m_chart_id,m_name);

   ::GlobalVariableSet(this.m_name_gv_x,this.m_x);

   ::GlobalVariableSet(this.m_name_gv_y,this.m_y);

  }

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

//| CWnd Chart event function                                        |

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

void CWnd::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)

  {

   if(id==CHARTEVENT_CHART_CHANGE)

     {

      int w=(int)::ChartGetInteger(this.m_chart_id,CHART_WIDTH_IN_PIXELS,this.m_sub_wnd);

      int h=(int)::ChartGetInteger(this.m_chart_id,CHART_HEIGHT_IN_PIXELS,this.m_sub_wnd);

      if(this.m_chart_h!=h)

        {

         this.m_chart_h=h;

         int y=this.CoordY1();

         if(this.CoordY1()+this.m_h>h-1) y=h-this.m_h-1;

         if(y<1) y=1;

         this.Move(this.CoordX1(),y);

        }

      if(this.m_chart_w!=w)

        {

         this.m_chart_w=w;

         int x=this.CoordX1();

         if(this.CoordX1()+this.m_w>w-1) x=w-this.m_w-1;

         if(x<1) x=1;

         this.Move(x,this.CoordY1());

        }

     }

   if(!this.m_movable)

      return;

   static int diff_x=0;

   static int diff_y=0;

   bool pressed=(sparam=="1" || sparam=="" ? true : false);

   int  mouse_x=(int)lparam;

   int  mouse_y=(int)dparam-(int)::ChartGetInteger(this.m_chart_id,CHART_WINDOW_YDISTANCE,this.m_sub_wnd);

   ENUM_MOUSE_STATE state=this.MouseButtonState(mouse_x,mouse_y,pressed);

   if(id==CHARTEVENT_MOUSE_MOVE)

     {

      if(state==MOUSE_STATE_PRESSED_INSIDE_WINDOW)

        {

         ::ChartSetInteger(0,CHART_MOUSE_SCROLL,false);

         ::ChartRedraw(this.m_chart_id);

         return;

        }

      else if(state==MOUSE_STATE_PRESSED_INSIDE_HEADER)

        {

         ::ChartSetInteger(0,CHART_MOUSE_SCROLL,false);

         this.Move(mouse_x-diff_x,mouse_y-diff_y);

         return;

        }

      else

        {

         ::ChartSetInteger(0,CHART_MOUSE_SCROLL,true);

         diff_x=mouse_x-this.CoordX1();

         diff_y=mouse_y-this.CoordY1();

        }

     }

  }

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

//| >72@0I05B A>AB>O=85 :=>?:8 <KH8                                 |

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

ENUM_MOUSE_STATE CWnd::MouseButtonState(const int x,const int y,bool pressed)

  {

   //--- A;8 :=>?:0 =060B0

   if(pressed)

     {

      //--- A;8 C65 70D8:A8@>20=> A>AB>O=85 - 2KE>4

      if(this.m_mouse_state!=MOUSE_STATE_NOT_PRESSED)

         return this.m_mouse_state;

      //--- A;8 =060B0 :=>?:0 2=CB@8 >:=0

      if(x>this.CoordX1() && x<this.CoordX2() && y>this.CoordY1() && y<this.CoordY2())

        {

         //--- A;8 =060B0 :=>?:0 2=CB@8 703>;>2:0

         if(y>this.CoordY1() && y<this.CoordYAct())

           {

            this.RedrawHeaderArea(this.NewColor(this.m_color_bg_header,30,30,30),this.m_color_caption);

            this.m_mouse_state=MOUSE_STATE_PRESSED_INSIDE_HEADER;

            return this.m_mouse_state;

           }

         //--- A;8 =060B0 :=>?:0 2=CB@8 >:=0

         else if(y>this.CoordY1() && y<this.CoordY2())

           {

            this.m_mouse_state=(this.m_header_on ? MOUSE_STATE_PRESSED_INSIDE_WINDOW : MOUSE_STATE_PRESSED_INSIDE_HEADER);

            return this.m_mouse_state;

           }

        }

      //--- =>?:0 =060B0 2=5 ?@545;>2 >:=0

      else

        {

         this.m_mouse_state=MOUSE_STATE_PRESSED_OUTSIDE_WINDOW;

         return this.m_mouse_state;

        }

     }

   //--- =>?:0 =5 =060B0

   else

     {

      this.m_mouse_state=MOUSE_STATE_NOT_PRESSED;

      //--- C@A>@ 2=CB@8 >:=0

      if(x>this.CoordX1() && x<this.CoordX2() && y>this.CoordY1() && y<this.CoordY2())

        {

         //--- C@A>@ 2=CB@8 703>;>2:0

         if(y>this.CoordY1() && y<this.CoordYAct())

           {

            this.RedrawHeaderArea(this.NewColor(this.m_color_bg_header,20,20,20),this.m_color_caption);

            return MOUSE_STATE_INSIDE_HEADER;

           }

         //--- C@A>@ 2=CB@8 >:=0

         else

           {

            this.RedrawHeaderArea(this.m_color_bg_header,this.m_color_caption);

            return MOUSE_STATE_INSIDE_WINDOW;

           }

        }

     }

   this.RedrawHeaderArea(this.m_color_bg_header,this.m_color_caption);

   return MOUSE_STATE_NOT_PRESSED;

  }

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

//| CWnd ?5@5<5I5=85 >:=0                                            |

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

void CWnd::Move(int x,int y)

  {

   if(x+this.m_w>this.m_chart_w-1) x=this.m_chart_w-this.m_w-1;

   if(x<1) x=1;

   if(y+this.m_h>this.m_chart_h-1) y=this.m_chart_h-this.m_h-1;

   if(y<1) y=1;

   this.m_x=x;

   this.m_y=y;

   ::ObjectSetInteger(this.m_chart_id,this.m_name+"0",OBJPROP_XDISTANCE,this.m_x);

   ::ObjectSetInteger(this.m_chart_id,this.m_name+"0",OBJPROP_YDISTANCE,this.m_y);

   ::ObjectSetInteger(this.m_chart_id,this.m_name+"1",OBJPROP_XDISTANCE,this.m_x+1);

   ::ObjectSetInteger(this.m_chart_id,this.m_name+"1",OBJPROP_YDISTANCE,this.m_y+this.m_y_act+1);

   this.m_canvas.Update(true);

  }

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

//| CWnd !>740QB E>;AB                                               |

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

bool CWnd::CreateCanvas(CCanvas &canvas,const int wnd_id,const int x,const int y,const int w,const int h)

  {

   if(!canvas.CreateBitmapLabel(this.m_chart_id,this.m_sub_wnd,this.m_name+(string)wnd_id,x,y,w,h,COLOR_FORMAT_ARGB_NORMALIZE))

      return false;

   if(wnd_id==0)

     {

      this.m_x=x;

      this.m_y=y;

      this.m_w=w;

      this.m_h=h;

     }

   ::ObjectSetInteger(this.m_chart_id,this.m_name+(string)wnd_id,OBJPROP_SELECTABLE,false);

   ::ObjectSetInteger(this.m_chart_id,this.m_name+(string)wnd_id,OBJPROP_SELECTED,false);

   ::ObjectSetInteger(this.m_chart_id,this.m_name+(string)wnd_id,OBJPROP_HIDDEN,true);

   return true;

  }

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

//| CWnd !>740QB >:=>                                                |

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

bool CWnd::CreateWindow(const string caption_text,const int x,const int y,const int w,const int h,const bool header,bool movable)

  {

   if(!this.CreateCanvas(this.m_canvas,0,x,y,w,h))

      return false;

   this.m_header_on=header;

   if(!header)

      this.m_y_act=0;

   this.m_movable=movable;

   this.m_caption=caption_text;

   this.m_canvas.Erase(::ColorToARGB(this.m_color_bg,this.m_alpha_bg));

   this.m_canvas.Rectangle(0,0,this.m_w-1,this.m_h-1,::ColorToARGB(this.m_color_border));

   this.DrawHeaderArea(this.m_caption);

   this.m_canvas.Update(true);

   

   if(!this.CreateCanvas(this.m_field,1,this.m_x+1,this.m_y+this.m_y_act+1,this.m_w-2,this.m_h-this.m_y_act-2))

      return false;

   return true;

  }

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

//| 7<5=O5B @07<5@K >:=0                                            |

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

void CWnd::Resize(const int w,const int h)

  {

   this.m_w=w;

   this.m_h=h;

   this.m_canvas.Resize(this.m_w,this.m_h);

   this.m_field.Resize(this.m_w-2,this.m_h-this.m_y_act-2);

   this.m_canvas.Erase(::ColorToARGB(this.m_color_bg,this.m_alpha_bg));

   this.m_canvas.Rectangle(0,0,this.m_w-1,this.m_h-1,::ColorToARGB(this.m_color_border));

   this.DrawHeaderArea(this.m_caption);

   this.m_canvas.Update(false);

   this.m_field.Update(true);

  }

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

//| CWnd  8AC5B 703>;>2>:                                            |

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

void CWnd::DrawHeaderArea(const string caption)

  {

   if(!this.m_header_on) return;

   this.m_canvas.FillRectangle(0,0,this.m_w,this.m_y_act,::ColorToARGB(this.m_color_bg_header,this.m_alpha_head));

   this.m_canvas.FontSet(this.m_caption_font,this.m_caption_font_size,FW_NORMAL);

   this.m_canvas.TextOut(this.m_x_caption,this.m_y_act/2,caption,::ColorToARGB(this.m_color_caption),this.m_caption_alignment);

  }

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

//| CWnd 5@5@8A>2K205B 703>;>2>:                                    |

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

void CWnd::RedrawHeaderArea(const color clr_area,const color clr_caption)

  {

   if(!this.m_header_on) return;

   this.m_canvas.FillRectangle(0,0,this.m_w,this.m_y_act,::ColorToARGB(clr_area,this.m_alpha_head));

   this.m_canvas.FontSet(this.m_caption_font,this.m_caption_font_size,FW_NORMAL);

   this.m_canvas.TextOut(this.m_x_caption,this.m_y_act/2,this.m_caption,::ColorToARGB(clr_caption),this.m_caption_alignment);

   this.m_canvas.Update();

  }

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

//|  8AC5B 25@B8:0;L=CN @0745;8B5;L=CN ;8=8N                         |

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

void CWnd::DrawSeparateVLine(const int x,const int y1,const int y2,const color clr1,const color clr2,const uchar w=1)

  {

   this.m_field.LineVertical(x,y1,y2,::ColorToARGB(clr1,this.m_alpha_bg));

   this.m_field.LineVertical(x+w,y1,y2,::ColorToARGB(clr2,this.m_alpha_bg));

  }

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

//|  8AC5B 3>@87>=B0;L=CN @0745;8B5;L=CN ;8=8N                       |

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

void CWnd::DrawSeparateHLine(const int x1,const int x2,const int y,const color clr1,const color clr2,const uchar w=1)

  {

   this.m_field.LineHorizontal(x1,x2,y,::ColorToARGB(clr1,this.m_alpha_bg));

   this.m_field.LineHorizontal(x1,x2,y+w,::ColorToARGB(clr2,this.m_alpha_bg));

  }

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

//| >72@0I05B F25B A =>2>9 F25B>2>9 A>AB02;ONI59                    |

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

color CWnd::NewColor(color base_color, int shift_red, int shift_green, int shift_blue)

  {

   double clR=0, clG=0, clB=0;

   this.ColorToRGB(base_color,clR,clG,clB);

   double clRn=(clR+shift_red  < 0 ? 0 : clR+shift_red  > 255 ? 255 : clR+shift_red);

   double clGn=(clG+shift_green< 0 ? 0 : clG+shift_green> 255 ? 255 : clG+shift_green);

   double clBn=(clB+shift_blue < 0 ? 0 : clB+shift_blue > 255 ? 255 : clB+shift_blue);

   return this.RGBToColor(clRn,clGn,clBn);

  }

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

//| @5>1@07>20=85 RGB 2 const color                                 |

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

color CWnd::RGBToColor(const double r,const double g,const double b)

  {

   int int_r=(int)::round(r);

   int int_g=(int)::round(g);

   int int_b=(int)::round(b);

   int clr=0;

//---

   clr=int_b;

   clr<<=8;

   clr|=int_g;

   clr<<=8;

   clr|=int_r;

//---

   return (color)clr;

  }

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

//| >;CG5=85 7=0G5=89 :><?>=5=B>2 RGB                               |

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

void CWnd::ColorToRGB(const color clr,double &r,double &g,double &b)

  {

   r=GetR(clr);

   g=GetG(clr);

   b=GetB(clr);

  }

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

//| >72@0I05B =08<5=>20=85 B09<D@59<0                               |

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

string CWnd::TimeframeToString(const ENUM_TIMEFRAMES timeframe)

  {

   return ::StringSubstr(::EnumToString(timeframe==PERIOD_CURRENT ? Period() : timeframe),7);

  }

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

//| #AB0=02;8205B F25B0 ?0=5;8                                       |

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

void CWnd::SetColors(const color clr_bg,const color clr_bd,const color clr_hd,const color clr_capt,const color clr_text,uchar alpha_bg=128,uchar alpha_hd=200)

  {

   this.m_color_bg=clr_bg;

   this.m_color_border=clr_bd;

   this.m_color_bg_header=clr_hd;

   this.m_color_caption=clr_capt;

   this.m_color_texts=clr_text;

   this.m_alpha_bg=alpha_bg;

   this.m_alpha_head=alpha_hd;

  }

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





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

//| =48:0B>@                                                        |

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

#property indicator_chart_window

#property indicator_buffers 16

#property indicator_plots   4

//--- plot MA1

#property indicator_label1  "MA1"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrRed

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- plot MA2

#property indicator_label2  "MA2"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrGreen

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- plot MA3

#property indicator_label3  "MA3"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrBlue

#property indicator_style3  STYLE_SOLID

#property indicator_width3  1

//--- plot MA4

#property indicator_label4  "MA4"

#property indicator_type4   DRAW_LINE

#property indicator_color4  clrGray

#property indicator_style4  STYLE_SOLID

#property indicator_width4  1

//--- enums

enum ENUM_DATA_DIRECTIONS

  {

   DIRECT_UP,

   DIRECT_DOWN,

   DIRECT_NEUTRAL

  };

//---

enum ENUM_MA_METHOD_EXT

  {

   METHOD_SMA,          // Simple

   METHOD_EMA,          // Exponential

   METHOD_SMMA,         // Smoothed

   METHOD_LWMA,         // Linear-Weighted

   METHOD_WILDER_EMA,   // Wilder Exponential

   METHOD_SINE_WMA,     // Sine-Weighted

   METHOD_TRI_MA,       // Triangular

   METHOD_LSMA,         // Least Square

   METHOD_HMA,          // Hull MA by Alan Hull

   METHOD_ZL_EMA,       // Zero-Lag Exponential

   METHOD_ITREND_MA,    // Instantaneous Trendline by J.Ehlers

   METHOD_MOVING_MEDIAN,// Moving Median

   METHOD_GEO_MEAN,     // Geometric Mean

   METHOD_REMA,         // Regularized EMA by Chris Satchwell

   METHOD_ILRS,         // Integral of Linear Regression Slope

   METHOD_IE_2,         // Combination of LSMA and ILRS

   METHOD_TRI_MA_GEN,   // Triangular MA generalized by J.Ehlers

   METHOD_VWMA          // Volume-Weighted

  };

//---

enum ENUM_DRAW_MODE

  {

   DRAW_MODE_STEPS,  // Steps

   DRAW_MODE_SLOPE   // Slope

  };

//---

enum ENUM_INPUT_YES_NO

  {

   INPUT_YES   =  1,    // Yes

   INPUT_NO    =  0     // No

  };

//--- structures

struct SDataInd

  {

   ENUM_TIMEFRAMES      timeframe;

   double               price_close0;

   double               price_close1;

   double               price_ma_0;

   double               price_ma_1;

   ENUM_DATA_DIRECTIONS ma_direction;

   ENUM_DATA_DIRECTIONS price_direction;

   ENUM_DATA_DIRECTIONS price_ma_direction;

  };

//--- input parameters

input ENUM_TIMEFRAMES      InpTimeframe1     =  PERIOD_M15;       // First MA timeframe

input uint                 InpPeriodMA1      =  50;               // First MA period

input ENUM_MA_METHOD_EXT   InpMethod1        =  METHOD_EMA;       // First MA method

input ENUM_APPLIED_PRICE   InpAppliedPrice1  =  PRICE_CLOSE;      // First MA applied price

input ENUM_TIMEFRAMES      InpTimeframe2     =  PERIOD_H1;        // Second MA timeframe

input uint                 InpPeriodMA2      =  50;               // Second MA period

input ENUM_MA_METHOD_EXT   InpMethod2        =  METHOD_EMA;       // Second MA method

input ENUM_APPLIED_PRICE   InpAppliedPrice2  =  PRICE_CLOSE;      // Second MA applied price

input ENUM_TIMEFRAMES      InpTimeframe3     =  PERIOD_H4;        // Third MA timeframe

input uint                 InpPeriodMA3      =  50;               // Third MA period

input ENUM_MA_METHOD_EXT   InpMethod3        =  METHOD_EMA;       // Third MA method

input ENUM_APPLIED_PRICE   InpAppliedPrice3  =  PRICE_CLOSE;      // Third MA applied price

input ENUM_TIMEFRAMES      InpTimeframe4     =  PERIOD_D1;        // Fourth MA timeframe

input uint                 InpPeriodMA4      =  50;               // Fourth MA period

input ENUM_MA_METHOD_EXT   InpMethod4        =  METHOD_EMA;       // Fourth MA method

input ENUM_APPLIED_PRICE   InpAppliedPrice4  =  PRICE_CLOSE;      // Fourth MA applied price

input uint                 InpCoordX         =  10;               // Panel: X-coordinate

input uint                 InpCoordY         =  10;               // Panel: Y-coordinate

input color                InpColorPanel     =  C'200,200,200';   // Panel: Background color

input color                InpColorHeader    =  clrDarkGray;      // Panel: Header color

input color                InpColorCaption   =  clrBeige;         // Panel: Caption color

input color                InpColorLabels    =  clrSlateGray;     // Panel: Texts color

input color                InpColorSlopeUP   =  clrLimeGreen;     // Panel: Slope up-direction color

input color                InpColorSlopeDN   =  clrDarkOrange;    // Panel: Slope down-direction color

input color                InpColorAllSyncUP =  clrGreen;         // Panel: all sync up-direction color

input color                InpColorAllSyncDN =  clrRed;           // Panel: all sync down-direction color

input uchar                InpAlphaBackgrnd  =  128;              // Panel: Background opacity

input uchar                InpAlphaHeader    =  200;              // Panel: Header opacity

input ENUM_DRAW_MODE       InpDrawMode       =  DRAW_MODE_SLOPE;  // Drawing mode

input ENUM_INPUT_YES_NO    InpUseAlert       =  INPUT_YES;        // Use alerts

input uchar                InpAlertInterval  =  5;                // Alert interval (min)

//--- indicator buffers

double            BufferMA1[];

double            BufferMA2[];

double            BufferMA3[];

double            BufferMA4[];

double            BufferMA1tmp[];

double            BufferMA2tmp[];

double            BufferMA3tmp[];

double            BufferMA4tmp[];

double            BufferPrice1[];

double            BufferPrice2[];

double            BufferPrice3[];

double            BufferPrice4[];

double            BufferVol1[];

double            BufferVol2[];

double            BufferVol3[];

double            BufferVol4[];

//--- global variables

CWnd              panel;

SDataInd          data_indicator[4];

ENUM_TIMEFRAMES   timeframe1;

ENUM_TIMEFRAMES   timeframe2;

ENUM_TIMEFRAMES   timeframe3;

ENUM_TIMEFRAMES   timeframe4;

int               period_ma1;

int               period_ma2;

int               period_ma3;

int               period_ma4;

int               period_max;

int               interval;

int               handle_ma1;

int               handle_ma2;

int               handle_ma3;

int               handle_ma4;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- timer

   EventSetTimer(90);

//--- set global variables

   period_ma1=int(InpPeriodMA1<2 ? 2 : InpPeriodMA1);

   period_ma2=int(InpPeriodMA2<2 ? 2 : InpPeriodMA2);

   period_ma3=int(InpPeriodMA3<2 ? 2 : InpPeriodMA3);

   period_ma4=int(InpPeriodMA4<2 ? 2 : InpPeriodMA4);

   period_max=fmax(period_ma1,fmax(period_ma2,fmax(period_ma3,period_ma4)));

   interval=int(InpAlertInterval<1 ? 1 : InpAlertInterval);

   timeframe1=(InpTimeframe1>Period() ? InpTimeframe1 : Period());

   timeframe2=(InpTimeframe2>Period() ? InpTimeframe2 : Period());

   timeframe3=(InpTimeframe3>Period() ? InpTimeframe3 : Period());

   timeframe4=(InpTimeframe4>Period() ? InpTimeframe4 : Period());

   data_indicator[0].timeframe=timeframe1;

   data_indicator[1].timeframe=timeframe2;

   data_indicator[2].timeframe=timeframe3;

   data_indicator[3].timeframe=timeframe4;

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferMA1,INDICATOR_DATA);

   SetIndexBuffer(1,BufferMA2,INDICATOR_DATA);

   SetIndexBuffer(2,BufferMA3,INDICATOR_DATA);

   SetIndexBuffer(3,BufferMA4,INDICATOR_DATA);

   SetIndexBuffer(4,BufferMA1tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(5,BufferMA2tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(6,BufferMA3tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(7,BufferMA4tmp,INDICATOR_CALCULATIONS);

   SetIndexBuffer(8,BufferPrice1,INDICATOR_CALCULATIONS);

   SetIndexBuffer(9,BufferPrice2,INDICATOR_CALCULATIONS);

   SetIndexBuffer(10,BufferPrice3,INDICATOR_CALCULATIONS);

   SetIndexBuffer(11,BufferPrice4,INDICATOR_CALCULATIONS);

   SetIndexBuffer(12,BufferVol1,INDICATOR_CALCULATIONS);

   SetIndexBuffer(13,BufferVol2,INDICATOR_CALCULATIONS);

   SetIndexBuffer(14,BufferVol3,INDICATOR_CALCULATIONS);

   SetIndexBuffer(15,BufferVol4,INDICATOR_CALCULATIONS);

//--- setting indicator parameters

   string label=TimeframeToString(timeframe1)+","+TimeframeToString(timeframe2)+","+TimeframeToString(timeframe3)+","+TimeframeToString(timeframe4)+" Timeframes MA Overview("+(string)period_ma1+","+(string)period_ma2+","+(string)period_ma3+","+(string)period_ma4+")";

   IndicatorSetString(INDICATOR_SHORTNAME,label);

   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

   IndicatorSetInteger(INDICATOR_LEVELS,2);

//--- setting plot buffer parameters

   PlotIndexSetString(0,PLOT_LABEL,TimeframeToString(timeframe1)+" "+MethodToString(InpMethod1)+"("+(string)period_ma1+")");

   PlotIndexSetString(1,PLOT_LABEL,TimeframeToString(timeframe2)+" "+MethodToString(InpMethod2)+"("+(string)period_ma2+")");

   PlotIndexSetString(2,PLOT_LABEL,TimeframeToString(timeframe3)+" "+MethodToString(InpMethod3)+"("+(string)period_ma3+")");

   PlotIndexSetString(3,PLOT_LABEL,TimeframeToString(timeframe4)+" "+MethodToString(InpMethod4)+"("+(string)period_ma4+")");

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferMA1,true);

   ArraySetAsSeries(BufferMA2,true);

   ArraySetAsSeries(BufferMA3,true);

   ArraySetAsSeries(BufferMA4,true);

   ArraySetAsSeries(BufferMA1tmp,true);

   ArraySetAsSeries(BufferMA2tmp,true);

   ArraySetAsSeries(BufferMA3tmp,true);

   ArraySetAsSeries(BufferMA4tmp,true);

   ArraySetAsSeries(BufferPrice1,true);

   ArraySetAsSeries(BufferPrice2,true);

   ArraySetAsSeries(BufferPrice3,true);

   ArraySetAsSeries(BufferPrice4,true);

   ArraySetAsSeries(BufferVol1,true);

   ArraySetAsSeries(BufferVol2,true);

   ArraySetAsSeries(BufferVol3,true);

   ArraySetAsSeries(BufferVol4,true);

   ResetLastError();

   handle_ma1=iMA(NULL,timeframe1,1,0,MODE_SMA,InpAppliedPrice1);

   if(handle_ma1==INVALID_HANDLE)

     {

      Print("The ",TimeframeToString(timeframe1)," iMA(1) object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

   handle_ma2=iMA(NULL,timeframe2,1,0,MODE_SMA,InpAppliedPrice2);

   if(handle_ma2==INVALID_HANDLE)

     {

      Print("The ",TimeframeToString(timeframe2)," iMA(1) object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

   handle_ma3=iMA(NULL,timeframe3,1,0,MODE_SMA,InpAppliedPrice3);

   if(handle_ma3==INVALID_HANDLE)

     {

      Print("The ",TimeframeToString(timeframe3)," iMA(1) object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

   handle_ma4=iMA(NULL,timeframe4,1,0,MODE_SMA,InpAppliedPrice4);

   if(handle_ma4==INVALID_HANDLE)

     {

      Print("The ",TimeframeToString(timeframe4)," iMA(1) object was not created: Error ",GetLastError());

      return INIT_FAILED;

     }

//--- get timeframe

   Time(NULL,timeframe1,1);

   Time(NULL,timeframe2,1);

   Time(NULL,timeframe3,1);

   Time(NULL,timeframe4,1);

//---

   int w=180,h=74;

   int x=int(!GlobalVariableCheck("Multi_Time_Frame_Overview_GVX") ? int(ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-w-InpCoordX) : GlobalVariableGet("Multi_Time_Frame_Overview_GVX"));

   int y=int(!GlobalVariableCheck("Multi_Time_Frame_Overview_GVY") ? (int)InpCoordY : GlobalVariableGet("Multi_Time_Frame_Overview_GVY"));

   panel.SetColors(InpColorPanel,clrSilver,InpColorHeader,InpColorCaption,InpColorLabels,InpAlphaBackgrnd,InpAlphaHeader);

   if(!panel.CreateWindow("MTF MA overview",x,y,w,h,true,true))

     {

      Print("Failed to create panel. Please restart the indicator");

      return INIT_FAILED;

     }

   RedrawField(data_indicator,ArraySize(data_indicator),0);

//---

   return(INIT_SUCCEEDED);

  }

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

//| 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[])

  {

//--- @>25@:0 :>;8G5AB20 4>ABC?=KE 10@>2

   if(rates_total<fmax(period_max,4)) return 0;

//--- @>25@:0 8 @0AGQB :>;8G5AB20 ?@>AG8BK205<KE 10@>2

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-3;

      ArrayInitialize(BufferMA1,EMPTY_VALUE);

      ArrayInitialize(BufferMA2,EMPTY_VALUE);

      ArrayInitialize(BufferMA3,EMPTY_VALUE);

      ArrayInitialize(BufferMA4,EMPTY_VALUE);

      ArrayInitialize(BufferMA1tmp,0);

      ArrayInitialize(BufferMA2tmp,0);

      ArrayInitialize(BufferMA3tmp,0);

      ArrayInitialize(BufferMA4tmp,0);

      ArrayInitialize(BufferPrice1,0);

      ArrayInitialize(BufferPrice2,0);

      ArrayInitialize(BufferPrice3,0);

      ArrayInitialize(BufferPrice4,0);

      ArrayInitialize(BufferVol1,0);

      ArrayInitialize(BufferVol2,0);

      ArrayInitialize(BufferVol3,0);

      ArrayInitialize(BufferVol4,0);

     }

//--- >43>B>2:0 40==KE

   if(Time(NULL,timeframe1,1)==0 || Time(NULL,timeframe2,1)==0 || Time(NULL,timeframe3,1)==0 || Time(NULL,timeframe4,1)==0)

      return 0;

   

   int bars1=(timeframe1==Period() ? rates_total : Bars(NULL,timeframe1));

   int bars2=(timeframe2==Period() ? rates_total : Bars(NULL,timeframe2));

   int bars3=(timeframe3==Period() ? rates_total : Bars(NULL,timeframe3));

   int bars4=(timeframe4==Period() ? rates_total : Bars(NULL,timeframe4));

   

   int count1=(limit>1 ? fmin(bars1,rates_total) : 1);

   int copied1=CopyBuffer(handle_ma1,0,0,count1,BufferPrice1);

   if(copied1!=count1) return 0;

   

   int count2=(limit>1 ? fmin(bars2,rates_total) : 1);

   int copied2=CopyBuffer(handle_ma2,0,0,count2,BufferPrice2);

   if(copied2!=count2) return 0;

   

   int count3=(limit>1 ? fmin(bars3,rates_total) : 1);

   int copied3=CopyBuffer(handle_ma3,0,0,count3,BufferPrice3);

   if(copied3!=count3) return 0;

   

   int count4=(limit>1 ? fmin(bars4,rates_total) : 1);

   int copied4=CopyBuffer(handle_ma4,0,0,count4,BufferPrice4);

   if(copied4!=count4) return 0;

   

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      BufferVol1[i]=(double)Volume(NULL,timeframe1,i);

      BufferVol2[i]=(double)Volume(NULL,timeframe2,i);

      BufferVol3[i]=(double)Volume(NULL,timeframe3,i);

      BufferVol4[i]=(double)Volume(NULL,timeframe4,i);

   //---  0AGQB MA1,MA2,MA3,MA4

      Calculate(rates_total,period_ma1,i,InpMethod1,BufferPrice1,BufferVol1,BufferMA1tmp);

      Calculate(rates_total,period_ma2,i,InpMethod2,BufferPrice2,BufferVol2,BufferMA2tmp);

      Calculate(rates_total,period_ma3,i,InpMethod3,BufferPrice3,BufferVol3,BufferMA3tmp);

      Calculate(rates_total,period_ma4,i,InpMethod4,BufferPrice4,BufferVol4,BufferMA4tmp);

     }

     

//---  0AGQB 8=48:0B>@0

   for(int i=limit; i>=0 && !IsStopped(); i--)

     {

      DataConversion(rates_total,NULL,timeframe1,i,BufferMA1tmp,BufferMA1,InpDrawMode);

      DataConversion(rates_total,NULL,timeframe2,i,BufferMA2tmp,BufferMA2,InpDrawMode);

      DataConversion(rates_total,NULL,timeframe3,i,BufferMA3tmp,BufferMA3,InpDrawMode);

      DataConversion(rates_total,NULL,timeframe4,i,BufferMA4tmp,BufferMA4,InpDrawMode);

     }

     

//--- 0=5;L

   int total=ArraySize(data_indicator);

   GetDataInd();

   ENUM_DATA_DIRECTIONS sync=AllSyncDirection(total,data_indicator);

   RedrawField(data_indicator,total,sync);

   

//--- ;5@B

   static datetime last_time=0;

   bool alert=false;

   if(InpUseAlert && sync!=DIRECT_NEUTRAL && (TimeCurrent()-last_time)>(interval*60))

     {

      string txt=(sync==DIRECT_UP ? "Up - Price Above MA and both MA and Price Positive" : "Down - Price Below MA and both MA and Price Negative");

      Alert(Symbol()+": ",TimeframeToString(data_indicator[0].timeframe),",",TimeframeToString(data_indicator[1].timeframe),",",TimeframeToString(data_indicator[2].timeframe),",",TimeframeToString(data_indicator[3].timeframe)," in Sync for the "+txt);

      alert=true;

     }

   if(alert)

      last_time=TimeCurrent();



//--- return value of prev_calculated for next call

   return(rates_total);

  }

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

//| Custom indicator timer function                                  |

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

void OnTimer()

  {

   Time(NULL,timeframe1,1);

   Time(NULL,timeframe2,1);

   Time(NULL,timeframe3,1);

   Time(NULL,timeframe4,1);

  }  

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

//| Cart event function                                              |

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

void OnChartEvent(const int id,

                  const long &lparam,

                  const double &dparam,

                  const string &sparam)

  {

   panel.OnChartEvent(id,lparam,dparam,sparam);

  }

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

//| 1=>2;O5B 40==K5 ?0=5;8                                          |

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

void RedrawField(SDataInd &data_ind[],const int total,const ENUM_DATA_DIRECTIONS sync)

  {

   #define ROW       (3)

   CCanvas* canvas=panel.GetFieldCanvas();

   if(canvas==NULL)

     {

      Print(__FUNCTION__,": Error: Canvas not available.");

      return;

     }

   canvas.Erase(ColorToARGB(panel.ColorBackground(),0));

   panel.DrawSeparateHLine(1,canvas.Width()-2,13,panel.NewColor(panel.ColorBackground(),-5,-5,-5),panel.NewColor(panel.ColorBackground(),45,45,45));

   panel.DrawSeparateVLine(50,14,canvas.Height()-2,panel.NewColor(panel.ColorBackground(),-5,-5,-5),panel.NewColor(panel.ColorBackground(),45,45,45));

   //---

   int shiftV=14,shiftH=30;

   for(int col=0;col<total;col++)

     {

      for(int row=0;row<ROW;row++)

        {

         if(row==0)

           {

            string tf=TimeframeToString(data_ind[col].timeframe);

            canvas.FontSet(panel.NameCaptionFont(),-80,FW_BLACK);

            canvas.TextOut(70+col*shiftH,0,tf,ColorToARGB(panel.ColorTexts()),TA_CENTER);

            if(col==0)

               canvas.TextOut(4,0,Symbol(),ColorToARGB(panel.ColorTexts()),TA_LEFT|TA_TOP);

           }

         if(col==0)

           {

            canvas.FontSet(panel.NameCaptionFont(),-80,FW_NORMAL);

            string txt=(row==0 ? "MA" : row==1 ? "Price" : "Price/MA");

            canvas.TextOut(4,16+row*shiftV,txt,ColorToARGB(panel.ColorTexts()));

           }

         double close0=data_ind[col].price_close0;

         double close1=data_ind[col].price_close1;

         double ma0=data_ind[col].price_ma_0;

         double ma1=data_ind[col].price_ma_1;

         canvas.FontSet(panel.NameCaptionFont(),-80,FW_NORMAL);

         string txt="";

         char shift_v=0,shift_h=0;

         color clr=InpColorLabels;

         if(row==0) txt=GetDrawingChar(ma0,ma1,shift_h,shift_v,clr,sync);

         if(row==1) txt=GetDrawingChar(close0,close1,shift_h,shift_v,clr,sync);

         if(row==2) txt=GetDrawingChar(close0,ma0,shift_h,shift_v,clr,sync);

         canvas.FontSet("Wingdings",-80,FW_BOLD);

         canvas.TextOut(70+col*shiftH+shift_h,16+row*shiftV+shift_v,txt,ColorToARGB(clr),TA_CENTER);

        }

     }

   canvas.Update(true);

  }

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

//| >72@0I05B 7=0G5=8O 40==KE 4;O 2K2>40 =0 ?0=5;L                  |

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

string GetDrawingChar(const double value0,const double value1,char &shift_h,char &shift_v,color &clr,ENUM_DATA_DIRECTIONS sync)

  {

   uchar code=32;

   shift_h=shift_v=0;

   clr=InpColorLabels;

   if(value0==0 || value1==0)

      return CharToString(code);

   if(value0>value1)

     {

      shift_v=0;

      shift_h=0;

      code=225;

      clr=(sync==DIRECT_UP ? InpColorAllSyncUP : InpColorSlopeUP);

     }

   else if(value0<value1)

     {

      shift_v=2;

      shift_h=-1;

      code=226;

      clr=(sync==DIRECT_DOWN ? InpColorAllSyncDN : InpColorSlopeDN);

     }

   else

     {

      shift_v=0;

      shift_h=0;

      code=224;

      clr=InpColorLabels;

     }

   return CharToString(code);

  }

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

//| >72@0I05B D;03 A8=E@>=870F88 2A5E =0?@02;5=89                   |

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

ENUM_DATA_DIRECTIONS AllSyncDirection(const int total,SDataInd &data_ind[])

  {

   ENUM_DATA_DIRECTIONS sync0=

     (

      (data_ind[0].ma_direction==DIRECT_UP && data_ind[0].price_direction==DIRECT_UP && data_ind[0].price_ma_direction==DIRECT_UP) ? DIRECT_UP :

      (data_ind[0].ma_direction==DIRECT_DOWN && data_ind[0].price_direction==DIRECT_DOWN && data_ind[0].price_ma_direction==DIRECT_DOWN) ? DIRECT_DOWN : DIRECT_NEUTRAL

     );

   ENUM_DATA_DIRECTIONS sync1=

     (

      (data_ind[1].ma_direction==DIRECT_UP && data_ind[1].price_direction==DIRECT_UP && data_ind[1].price_ma_direction==DIRECT_UP) ? DIRECT_UP :

      (data_ind[1].ma_direction==DIRECT_DOWN && data_ind[1].price_direction==DIRECT_DOWN && data_ind[1].price_ma_direction==DIRECT_DOWN) ? DIRECT_DOWN : DIRECT_NEUTRAL

     );

   ENUM_DATA_DIRECTIONS sync2=

     (

      (data_ind[2].ma_direction==DIRECT_UP && data_ind[2].price_direction==DIRECT_UP && data_ind[2].price_ma_direction==DIRECT_UP) ? DIRECT_UP :

      (data_ind[2].ma_direction==DIRECT_DOWN && data_ind[2].price_direction==DIRECT_DOWN && data_ind[2].price_ma_direction==DIRECT_DOWN) ? DIRECT_DOWN : DIRECT_NEUTRAL

     );

   ENUM_DATA_DIRECTIONS sync3=

     (

      (data_ind[3].ma_direction==DIRECT_UP && data_ind[3].price_direction==DIRECT_UP && data_ind[3].price_ma_direction==DIRECT_UP) ? DIRECT_UP :

      (data_ind[3].ma_direction==DIRECT_DOWN && data_ind[3].price_direction==DIRECT_DOWN && data_ind[3].price_ma_direction==DIRECT_DOWN) ? DIRECT_DOWN : DIRECT_NEUTRAL

     );

   return

     (

      ((sync0==DIRECT_UP) &&

       (sync1==DIRECT_UP) &&

       (sync2==DIRECT_UP) &&

       (sync3==DIRECT_UP)) ? DIRECT_UP :

      

      ((sync0==DIRECT_DOWN) &&

       (sync1==DIRECT_DOWN) &&

       (sync2==DIRECT_DOWN) &&

       (sync3==DIRECT_DOWN)) ? DIRECT_DOWN : DIRECT_NEUTRAL

     );

  }

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

//| Transfering data from the source timeframe to current timeframe  |

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

void DataConversion(const int rates_total,

                    const string symbol_name,

                    const ENUM_TIMEFRAMES timeframe_src,

                    const int shift,

                    const double &buffer_src[],

                    double &buffer_dest[],

                    ENUM_DRAW_MODE mode=DRAW_MODE_STEPS

                   )

  {

   if(timeframe_src==Period())

     {

      buffer_dest[shift]=buffer_src[shift];

      return;

     }

   int bar_curr=BarToCurrent(symbol_name,timeframe_src,shift);

   if(bar_curr>rates_total-1)

      return;

   int bar_prev=BarToCurrent(symbol_name,timeframe_src,shift+1);

   int bar_next=(shift>0 ? BarToCurrent(symbol_name,timeframe_src,shift-1) : 0);

   if(bar_prev==WRONG_VALUE || bar_curr==WRONG_VALUE || bar_next==WRONG_VALUE)

      return;

   buffer_dest[bar_curr]=buffer_src[shift];

   if(mode==DRAW_MODE_STEPS)

      for(int j=bar_curr; j>=bar_next; j--)

         buffer_dest[j]=buffer_dest[bar_curr];

   else

     {

      if(bar_prev>rates_total-1) return;

      for(int j=bar_prev; j>=bar_curr; j--)

         buffer_dest[j]=EquationDirect(bar_prev,buffer_dest[bar_prev],bar_curr,buffer_dest[bar_curr],j);

      if(shift==0)

         for(int j=bar_curr; j>=0; j--)

            buffer_dest[j]=buffer_dest[bar_curr];

     }

  }

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

//| >;CG5=85 40==KE 8=48:0B>@0                                      |

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

void GetDataInd(void)

  {

   int total=ArraySize(data_indicator);

   for(int i=0;i<total;i++)

     {

      ENUM_TIMEFRAMES tf=PERIOD_CURRENT;

      double ma0=0,ma1=0,pr0=0,pr1=0;

      switch(i)

        {

         case 0 : tf=timeframe1; ma0=BufferMA1tmp[0]; ma1=BufferMA1tmp[1]; break;

         case 1 : tf=timeframe2; ma0=BufferMA2tmp[0]; ma1=BufferMA2tmp[1]; break;

         case 2 : tf=timeframe3; ma0=BufferMA3tmp[0]; ma1=BufferMA3tmp[1]; break;

         default: tf=timeframe4; ma0=BufferMA4tmp[0]; ma1=BufferMA4tmp[1]; break;

        }

      pr0=Close(NULL,tf,0);

      pr1=Close(NULL,tf,1);

      data_indicator[i].timeframe=tf;

      data_indicator[i].price_close0=pr0;

      data_indicator[i].price_close1=pr1;

      data_indicator[i].price_ma_0=ma0;

      data_indicator[i].price_ma_1=ma1;

      data_indicator[i].ma_direction=(ma0>ma1 ? DIRECT_UP : ma0<ma1 ? DIRECT_DOWN : DIRECT_NEUTRAL);

      data_indicator[i].price_direction=(pr0>pr1 ? DIRECT_UP : pr0<pr1 ? DIRECT_DOWN : DIRECT_NEUTRAL);

      data_indicator[i].price_ma_direction=(pr0>ma0 ? DIRECT_UP : pr0<ma0 ? DIRECT_DOWN : DIRECT_NEUTRAL);

     }

  }

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

//| >72@0I05B 10@ 7040==>3> B09<D@59<0 :0: 10@ B5:CI53> B09<D@59<0  |

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

int BarToCurrent(const string symbol_name,const ENUM_TIMEFRAMES timeframe_src,const int shift,bool exact=false)

  {

   datetime time=Time(symbol_name,timeframe_src,shift);

   return(time!=0 ? BarShift(symbol_name,Period(),time,exact) : WRONG_VALUE);

  }  

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

//| >72@0I05B A<5I5=85 10@0 ?> 2@5<5=8                              |

//| https://www.mql5.com/ru/forum/743/page11#comment_7010041         |

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

int BarShift(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const datetime time,bool exact=false)

  {

   int res=Bars(symbol_name,timeframe,time+1,UINT_MAX);

   if(exact) if((timeframe!=PERIOD_MN1 || time>TimeCurrent()) && res==Bars(symbol_name,timeframe,time-PeriodSeconds(timeframe)+1,UINT_MAX)) return(WRONG_VALUE);

   return res;

  }

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

//| >72@0I05B Time                                                  |

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

datetime Time(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift)

  {

   datetime array[];

   ArraySetAsSeries(array,true);

   return(CopyTime(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0);

  }

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

//| >72@0I05B Volume                                                |

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

long Volume(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift)

  {

   long array[];

   ArraySetAsSeries(array,true);

   return(CopyTickVolume(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0);

  }

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

//| >72@0I05B Close                                                 |

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

double Close(const string symbol_name,const ENUM_TIMEFRAMES timeframe,const int shift)

  {

   double array[];

   ArraySetAsSeries(array,true);

   return(CopyClose(symbol_name,timeframe,shift,1,array)==1 ? array[0] : 0);

  }

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

//| #@02=5=85 ?@O<>9                                                 |

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

double EquationDirect(const int left_bar,const double left_price,const int right_bar,const double right_price,const int bar_to_search) 

  {

   return(right_bar==left_bar ? left_price : (right_price-left_price)/(right_bar-left_bar)*(bar_to_search-left_bar)+left_price);

  }

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

//| Timeframe to string                                              |

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

string TimeframeToString(const ENUM_TIMEFRAMES timeframe)

  {

   return StringSubstr(EnumToString(timeframe==PERIOD_CURRENT ? Period() : timeframe),7);

  }

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

//| Simple Moving Average                                            |

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

double SMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return array_src[shift];

   double sum=0;

   for(int i=0; i<period; i++)

      sum+=array_src[shift+i];

   return(sum/period);

  }

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

//| Exponential Moving Average                                       |

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

double EMA(const int rates_total,const double price,const double prev,const int period,const int shift)

  {

   return(shift>=rates_total-2 || period<1 ? price : prev+2.0/(1+period)*(price-prev));

  }

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

//| Wilder Exponential Moving Average                                |

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

double Wilder(const int rates_total,const double price,const double prev,const int period,const int shift)

  {

   return(shift>=rates_total-2 || period<1 ? price : prev+(price-prev)/period);

  }

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

//| Linear Weighted Moving Average                                   |

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

double LWMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sum=0;

   double weight=0;

   for(int i=0; i<period; i++)

     {

      weight+=(period-i);

      sum+=array_src[shift+i]*(period-i);

     }

   return(weight>0 ? sum/weight : 0);

  }

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

//| Sine Weighted Moving Average                                     |

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

double SineWMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sum=0;

   double weight=0;

   for(int i=0; i<period; i++)

     {

      weight+=sin(M_PI*(i+1)/(period+1));

      sum+=array_src[shift+i]*sin(M_PI*(i+1)/(period+1));

     }

   return(weight>0 ? sum/weight : 0);

  }

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

//| Triangular Moving Average                                        |

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

double TriMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sma;

   int len=(int)ceil((period+1)*0.5);

   double sum=0;

   for(int i=0; i<len; i++)

     {

      sma=SMA(rates_total,array_src,len,shift+i);

      sum+=sma;

     }

   double trima=sum/len;

   return(trima);

  }

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

//| Least Square Moving Average                                      |

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

double LSMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sum=0;

   for(int i=period; i>=1; i--)

      sum+=(i-(period+1)/3.0)*array_src[shift+period-i];

   double lsma=sum*6.0/(period*(period+1));

   return(lsma);

  }

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

//| Smoothed Moving Average                                          |

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

double SMMA(const int rates_total,const double &array_src[],const double prev,const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double smma=0;

   if(shift==rates_total-period-1)

      smma=SMA(rates_total,array_src,period,shift);

   else if(shift<rates_total-period-1)

     {

      double sum=0;

      for(int i = 0; i<period; i++)

         sum+=array_src[shift+i+1];

      smma=(sum-prev+array_src[shift])/period;

     }

   return smma;

  }

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

//| Hull Moving Average by Alan Hull                                 |

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

double HMA(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double tmp1[];

   double hma=0;

   int len=(int)sqrt(period);

   ArrayResize(tmp1,len);

   if(shift==rates_total-period-1)

      hma=array_src[shift];

   else if(shift<rates_total-period-1)

     {

      for(int i=0; i<len; i++)

         tmp1[i]=2.0*LWMA(rates_total,array_src,period/2,shift+i)-LWMA(rates_total,array_src,period,shift+i);

      hma=LWMA(rates_total,tmp1,len,0);

     }

   return hma;

  }

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

//| Zero-Lag Exponential Moving Average                              |

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

double ZeroLagEMA(const int rates_total,const double &array_src[],const double prev,const int period,const int shift)

  {

   double alfa=2.0/(1+period);

   int lag=int(0.5*(period-1));

   return(shift>=rates_total-lag ? array_src[shift] : alfa*(2.0*array_src[shift]-array_src[shift+lag])+(1-alfa)*prev);

  }

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

//| Instantaneous Trendline by J.Ehlers                              |

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

double ITrend(const int rates_total,const double &array_src[],const double &array[],const int period,const int shift)

  {

   double alfa=2.0/(period+1);

   return

     (

      shift<rates_total-7 ?

      (alfa-0.25*alfa*alfa)*array_src[shift]+0.5*alfa*alfa*array_src[shift+1]-(alfa-0.75*alfa*alfa)*array_src[shift+2]+2*(1-alfa)*array[shift+1]-(1-alfa)*(1-alfa)*array[shift+2]:

      (array_src[shift]+2*array_src[shift+1]+array_src[shift+2])/4.0

     );

  }

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

//| Moving Median                                                    |

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

double Median(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<2 || shift>rates_total-period-1)

      return 0;

   double array[];

   ArrayResize(array,period);

   for(int i=0; i<period; i++)

      array[i]=array_src[shift+i];

   ArraySort(array);

   int num=(int)round((period-1)/2);

   return(fmod(period,2)>0 ? array_src[num] : 0.5*(array_src[num]+array[num+1]));

  }

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

//| Geometric Mean                                                   |

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

double GeoMean(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   double gmean=0;

   if(shift<rates_total-period)

     {

      gmean=pow(array_src[shift],1.0/period);

      for(int i=1; i<period; i++)

         gmean*=pow(array_src[shift+i],1.0/period);

     }

   return(gmean);

  }

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

//| Regularized EMA by Chris Satchwell                               |

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

double REMA(const int rates_total,const double price,const double &array[],const int period,const double lambda,const int shift)

  {

   double alpha=2.0/(period+1);

   return(shift>=rates_total-3 ? price : (array[shift+1]*(1+2*lambda)+alpha*(price-array[shift+1])-lambda*array[shift+2])/(1+lambda));

  }

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

//| Integral of Linear Regression Slope                              |

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

double ILRS(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sum=period*(period-1)*0.5;

   double sum2=(period-1)*period*(2*period-1)/6.0;

   double sum1=0;

   double sumy=0;

   for(int i=0; i<period; i++)

     {

      sum1+=i*array_src[shift+i];

      sumy+=array_src[shift+i];

     }

   double num1=period*sum1-sum*sumy;

   double num2=sum*sum-period*sum2;

   double slope=(num2!=0 ? num1/num2 : 0);

   return(slope+SMA(rates_total,array_src,period,shift));

  }

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

//| Combination of LSMA and ILRS                                     |

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

double IE2(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   return(0.5*(ILRS(rates_total,array_src,period,shift)+LSMA(rates_total,array_src,period,shift)));

  }

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

//| Triangular Moving Average generalized by J.Ehlers                |

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

double TriMA_gen(const int rates_total,const double &array_src[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   int len1=(int)floor((period+1)*0.5);

   int len2=(int)ceil((period+1)*0.5);

   double sum=0;

   for(int i=0; i<len2; i++)

      sum+=SMA(rates_total,array_src,len1,shift+i);

   return(sum/len2);

  }

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

//| Volume-Weighted Moving Average                                   |

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

template<typename T>

double VWMA(const int rates_total,const double &array_src[],const T &volume[],const int period,const int shift)

  {

   if(period<1 || shift>rates_total-period-1)

      return 0;

   double sum=0;

   double weight=0;

   for(int i=0; i<period; i++)

     {

      weight+=(double)volume[shift+i];

      sum+=array_src[shift+i]*volume[shift+i];

     }

   return(weight>0 ? sum/weight : 0);

  }

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

//| >72@0I05B =08<5=>20=85 <5B>40                                 |

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

string MethodToString(ENUM_MA_METHOD_EXT method)

  {

   switch(method)

     {

      case METHOD_EMA            :  return "EMA";

      case METHOD_SMMA           :  return "SMMA";

      case METHOD_LWMA           :  return "LWMA";

      case METHOD_WILDER_EMA     :  return "WMA";

      case METHOD_SINE_WMA       :  return "SinMA";

      case METHOD_TRI_MA         :  return "TriMA";

      case METHOD_LSMA           :  return "LSMA";

      case METHOD_HMA            :  return "HMA";

      case METHOD_ZL_EMA         :  return "ZLMA";

      case METHOD_ITREND_MA      :  return "ITrendMA";

      case METHOD_MOVING_MEDIAN  :  return "Median";

      case METHOD_GEO_MEAN       :  return "GeoMean";

      case METHOD_REMA           :  return "REMA";

      case METHOD_ILRS           :  return "ILRS";

      case METHOD_IE_2           :  return "IE2";

      case METHOD_TRI_MA_GEN     :  return "TriMAgen";

      case METHOD_VWMA           :  return "VWMA";

      default                    :  return "SMA";

     }

  }

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

//| >72@0I05B =08<5=>20=85 F5=K                                     |

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

string PriceToString(ENUM_APPLIED_PRICE price)

  { 

   return StringSubstr(EnumToString(price),6); 

  }

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

//|  0AGQB                                                         |

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

void Calculate(const int rates_total,const int period,const int shift,const ENUM_MA_METHOD_EXT method,const double &price[],const double &volume[],double &buffer_ma[])

  {

   switch(method)

     {

      case METHOD_EMA            : buffer_ma[shift] = EMA(rates_total,price[shift],buffer_ma[shift+1],period,shift);    break;

      case METHOD_SMMA           : buffer_ma[shift] = SMMA(rates_total,price,buffer_ma[shift+1],period,shift);          break;

      case METHOD_LWMA           : buffer_ma[shift] = LWMA(rates_total,price,period,shift);                             break;

      case METHOD_WILDER_EMA     : buffer_ma[shift] = Wilder(rates_total,price[shift],buffer_ma[shift+1],period,shift); break;

      case METHOD_SINE_WMA       : buffer_ma[shift] = SineWMA(rates_total,price,period,shift);                          break;

      case METHOD_TRI_MA         : buffer_ma[shift] = TriMA(rates_total,price,period,shift);                            break;

      case METHOD_LSMA           : buffer_ma[shift] = LSMA(rates_total,price,period,shift);                             break;

      case METHOD_HMA            : buffer_ma[shift] = HMA(rates_total,price,period,shift);                              break;

      case METHOD_ZL_EMA         : buffer_ma[shift] = ZeroLagEMA(rates_total,price,buffer_ma[shift+1],period,shift);    break;

      case METHOD_ITREND_MA      : buffer_ma[shift] = ITrend(rates_total,price,buffer_ma,period,shift);                 break;

      case METHOD_MOVING_MEDIAN  : buffer_ma[shift] = Median(rates_total,price,period,shift);                           break;

      case METHOD_GEO_MEAN       : buffer_ma[shift] = GeoMean(rates_total,price,period,shift);                          break;

      case METHOD_REMA           : buffer_ma[shift] = REMA(rates_total,price[shift],buffer_ma,period,0.5,shift);        break;

      case METHOD_ILRS           : buffer_ma[shift] = ILRS(rates_total,price,period,shift);                             break;

      case METHOD_IE_2           : buffer_ma[shift] = IE2(rates_total,price,period,shift);                              break;

      case METHOD_TRI_MA_GEN     : buffer_ma[shift] = TriMA_gen(rates_total,price,period,shift);                        break;

      case METHOD_VWMA           : buffer_ma[shift] = VWMA(rates_total,price,volume,period,shift);                      break;

      default /*METHOD_SMA*/     : buffer_ma[shift] = SMA(rates_total,price,period,shift);                              break;

     }

  }

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

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---