Trying to clean up fractals

 

Im trying fracts buffor arrows to show only limited to 5 backwards and 5 frontwards of OBJ_'TEXT highest and lowest point

currently it shows fractal on every bar

Any help is highly appreciated

Here is code

Thanks 

#property copyright "Copyright 2022"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2


//--- plot Fractal_Up
#property indicator_label1  "Fractal Up"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrDeepSkyBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Fractal_Down
#property indicator_label2  "Fractal Down"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrDeepSkyBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1


//--- input parameters
input group             "Fibo"
input color             InpColorUp     = clrBlue;              // Fibo color UP
input color             InpColorDOWN   = clrRed;               // Fibo color DOWN
input ENUM_LINE_STYLE   InpStyles      = STYLE_SOLID;          // Style of Fibo
input int               InpWidth       = 3;                    // Fibo line width
input group             "Levels"
input color             InpLevelsColor = clrGold;              // Color of level lines
input ENUM_LINE_STYLE   InpLevelsStyles= STYLE_DOT;            // Style of level lines
input int               InpLevelsWidth = 3;                    // Fibo line width


//+------------------------------------------------------------------+
//|  Enumeration for Windows fonts indices storage                   |
//+------------------------------------------------------------------+
enum type_font // font type
  {
   Font0, //Arial
   Font1, //Arial Black
   Font2, //Arial Bold
   Font3, //Arial Bold Italic
   Font4, //Arial Italic
   Font5, //Comic Sans MS Bold
   Font6, //Courier
   Font7, //Courier New
   Font8, //Courier New Bold
   Font9, //Courier New Bold Italic
   Font10, //Courier New Italic
   Font11, //Estrangelo Edessa
   Font12, //Franklin Gothic Medium
   Font13, //Gautami
   Font14, //Georgia
   Font15, //Georgia Bold
   Font16, //Georgia Bold Italic
   Font17, //Georgia Italic
   Font18, //Georgia Italic Impact
   Font19, //Latha
   Font20, //Lucida Console
   Font21, //Lucida Sans Unicode
   Font22, //Modern MS Sans Serif
   Font23, //MS Sans Serif
   Font24, //Mv Boli
   Font25, //Palatino Linotype
   Font26, //Palatino Linotype Bold
   Font27, //Palatino Linotype Italic
   Font28, //Roman
   Font29, //Script
   Font30, //Small Fonts
   Font31, //Symbol
   Font32, //Tahoma
   Font33, //Tahoma Bold
   Font34, //Times New Roman
   Font35, //Times New Roman Bold
   Font36, //Times New Roman Bold Italic
   Font37, //Times New Roman Italic
   Font38, //Trebuchet MS
   Font39, //Trebuchet MS Bold
   Font40, //Trebuchet MS Bold Italic
   Font41, //Trebuchet MS Italic
   Font42, //Tunga
   Font43, //Verdana
   Font44, //Verdana Bold
   Font45, //Verdana Bold Italic
   Font46, //Verdana Italic
   Font47, //Webdings
   Font48, //Westminster
   Font49, //Wingdings
   Font50, //WST_Czech
   Font51, //WST_Engl
   Font52, //WST_Fren
   Font53, //WST_Germ
   Font54, //WST_Ital
   Font55, //WST_Span
   Font56  //WST_Swed
  };
//+------------------------------------------------------------------+
//|  Font name obtaining class                                       |
//+------------------------------------------------------------------+
class CFontName
  {
public:
   string              GetFontName(type_font FontNumber)
     {
      string FontTypes[]=
        {
         "Arial",
         "Arial Black",
         "Arial Bold",
         "Arial Bold Italic",
         "Arial Italic",
         "Comic Sans MS Bold",
         "Courier",
         "Courier New",
         "Courier New Bold",
         "Courier New Bold Italic",
         "Courier New Italic",
         "Estrangelo Edessa",
         "Franklin Gothic Medium",
         "Gautami",
         "Georgia",
         "Georgia Bold",
         "Georgia Bold Italic",
         "Georgia Italic",
         "Georgia Italic Impact",
         "Latha",
         "Lucida Console",
         "Lucida Sans Unicode",
         "Modern MS Sans Serif",
         "MS Sans Serif",
         "Mv Boli",
         "Palatino Linotype",
         "Palatino Linotype Bold",
         "Palatino Linotype Italic",
         "Roman",
         "Script",
         "Small Fonts",
         "Symbol",
         "Tahoma",
         "Tahoma Bold",
         "Times New Roman",
         "Times New Roman Bold",
         "Times New Roman Bold Italic",
         "Times New Roman Italic",
         "Trebuchet MS",
         "Trebuchet MS Bold",
         "Trebuchet MS Bold Italic",
         "Trebuchet MS Italic",
         "Tunga",
         "Verdana",
         "Verdana Bold",
         "Verdana Bold Italic",
         "Verdana Italic",
         "Webdings",
         "Westminster",
         "Wingdings",
         "WST_Czech",
         "WST_Engl",
         "WST_Fren",
         "WST_Germ",
         "WST_Ital",
         "WST_Span",
         "WST_Swed"
        };

      return(FontTypes[int(FontNumber)]);
     };
  }; 
input       type_font FontType=Font24;
string      sFontType;
input uint  TextSize=10;
string      _model;
string lines_tag="viewport_lines_";
int fvb=-1,clb=-1;
//--- indicator buffers
double   FractalUpBuffer[];
double   FractalDownBuffer[];
//--- 10 pixels upper from high price
int      m_arrow_shift=-10;
//---
int      handle_iFractals;                   // variable for storing the handle of the iFractals indicator
int      bars_calculated=0;                  // we will keep the number of values in the Fractals indicator
datetime m_prev_bars                = 0;     // "0" -> D'1970.01.01 00:00';

//--- input parameters of the script
input string            InpFont="Arial";         // Font
input int               InpFontSize=10;          // Font size
input color             InpColor=clrDeepPink;         // Color
input double            InpAngle=0.0;           // Slope angle in degrees
input ENUM_ANCHOR_POINT InpAnchor=ANCHOR_CENTER;   // Anchor type
input bool              InpBack=false;           // Background object
input bool              InpSelection=false;      // Highlight to move
input bool              InpHidden=true;          // Hidden in the object list
input long              InpZOrder=0;             // Priority for mouse click
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
//--- indicator buffers mapping
   ObjectsDeleteAll(ChartID(),lines_tag);
    CFontName FONT;
   _model=FONT.GetFontName(FontType);
   
//--- indicator buffers mapping
   SetIndexBuffer(0,FractalUpBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,FractalDownBuffer,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_ARROW,217);
   PlotIndexSetInteger(1,PLOT_ARROW,218);
//--- arrow shifts when drawing
   PlotIndexSetInteger(0,PLOT_ARROW_SHIFT,m_arrow_shift);
   PlotIndexSetInteger(1,PLOT_ARROW_SHIFT,-m_arrow_shift);
//--- sets drawing line empty value--
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//--- create handle of the indicator iFractals
   handle_iFractals=iFractals(Symbol(),Period());
//--- if the handle is not created
   if(handle_iFractals==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iFractals indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      return(INIT_FAILED);
     }
//---
   ArrayFree(SFractals);
   ArrayResize(SFractals,3);
   ArraySetAsSeries(SFractals,true);
//---
//---
   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[]) {
//---
  int values_to_copy;
//--- determine the number of values calculated in the indicator
   int calculated=BarsCalculated(handle_iFractals);
   if(calculated<=0)
     {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- if it is the first start of calculation of the indicator or if the number of values in the iFractals indicator changed
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history)
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- if the FractalUpBuffer array is greater than the number of values in the iFractals indicator for symbol/period, then we don't copy everything
      //--- otherwise, we copy less than the size of indicator buffers
      if(calculated>rates_total)
         values_to_copy=rates_total;
      else
         values_to_copy=calculated;
     }
   else
     {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
      //--- for calculation not more than one bar is added
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- fill the FractalUpBuffer and FractalDownBuffer arrays with values from the Fractals indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArraysFromBuffers(FractalUpBuffer,FractalDownBuffer,handle_iFractals,values_to_copy))
      return(0);
//--- memorize the number of values in the Fractals indicator
   bars_calculated=calculated;
//--- main loop
   int limit=prev_calculated-4;
   if(prev_calculated==0)
      limit=3;
//---
   for(int i=limit; i<rates_total-3; i++)
     {
      //--- we work only at the time of the birth of new bar
      datetime time_0=time[i];
      if(time_0==m_prev_bars)
         return(rates_total);
      m_prev_bars=time_0;
      //---
      if((FractalUpBuffer[i]!=0.0 && FractalUpBuffer[i]!=EMPTY_VALUE) || (FractalDownBuffer[i]!=0.0 && FractalDownBuffer[i]!=EMPTY_VALUE))
        {
         STRUCT_FRACTALS SFractals_temp[];
         //---
         ArrayResize(SFractals_temp,3);
         ArraySetAsSeries(SFractals_temp,true);
         ArrayCopy(SFractals_temp,SFractals,1,0,2);
         //---
         if(FractalUpBuffer[i]!=0.0 && FractalUpBuffer[i]!=EMPTY_VALUE)
           {
            if(SFractals_temp[1].fractal_type==1)
               continue;
            SFractals_temp[0].fractal_type=1;
            SFractals_temp[0].fractal_price=FractalUpBuffer[i];
           }
         else
           {
            if(FractalDownBuffer[i]!=0.0 && FractalDownBuffer[i]!=EMPTY_VALUE)
              {
               /*arr_temp_fractals[0]=FractalDownBuffer[i];*/
               if(SFractals_temp[1].fractal_type==-1)
                  continue;
               SFractals_temp[0].fractal_type=-1;
               SFractals_temp[0].fractal_price=FractalDownBuffer[i];
              }
           }
         SFractals_temp[0].fractal_time=time[i];
         ArrayCopy(SFractals,SFractals_temp,0,0,WHOLE_ARRAY);
         //---
         if(SFractals[1].fractal_price!=0.0 && SFractals[0].fractal_price!=0.0)
           {
            datetime time1=0;    // first point time
            double   price1=0;   // first point price
            datetime time2=0;    // second point time
            double   price2=0;   // second point price
            color    clr=clrRed; // object color
            //---
            time1=SFractals_temp[0].fractal_time;
            price1=SFractals_temp[0].fractal_price;
            time2=SFractals_temp[1].fractal_time;
            price2=SFractals_temp[1].fractal_price;
            if(SFractals[1].fractal_price<SFractals[0].fractal_price)
              {
               clr=InpColorUp;
              }
            else
              {
               clr=InpColorDOWN;
              }
         
           }
         //---
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   ObjectsDeleteAll(ChartID(),lines_tag,-1,OBJ_TEXT);
   if(handle_iFractals!=INVALID_HANDLE)
      IndicatorRelease(handle_iFractals);

}
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void  OnChartEvent(const int id,
                   const long &lparam,
                   const double &dparam,
                   const string &sparam) {
//---
   if (id==CHARTEVENT_CHART_CHANGE) {
      int _fvb=(int)ChartGetInteger(ChartID(),CHART_FIRST_VISIBLE_BAR,0);
      int _clb=(int)ChartGetInteger(ChartID(),CHART_WIDTH_IN_BARS,0);
      if (_fvb>0 &&(_fvb!=fvb||_clb!=clb)) {
         ObjectsDeleteAll(ChartID(),lines_tag,-1,OBJ_TEXT);
         /*
         The first visible bar returns a number that represents the distance of the leftmost visible bar from the live bar of the chart which is 0
         So if the first visible bar is 9 bars to the left of 0 the fvb will return 9
         We use the width in bars to project where the last visible bar is
         */
         int lvb=_fvb-(_clb-1);
         //but if the last visible bar is below zero that is impossible so we check it
         if (lvb<0) {
            lvb=0;
         }
         /*
         Then we utilize the iHighest function to get the highest in the range .
         In mt5 the series arrays resemble a salad where they are as series in some cases and not as series in others
         iHighest and iSeries are as series which means they operate with zero to the rightmost bar
         In the documentation for Highest it says the starting point is a deviation from the current bar
         So what we should send it there is the last visible bar
         But then we need to know how many bars that distance is so
         we subtract the last visible bar from the first visible bar
         */
         int hix= iHighest(_Symbol,_Period,MODE_HIGH,(_fvb-lvb),lvb);
         int lix= iLowest(_Symbol,_Period,MODE_LOW,(_fvb-lvb),lvb);
         //ObjectCreate(ChartID(),lines_tag+"_H",OBJ_TEXT,0,iTime(_Symbol,_Period,hix),iHigh(_Symbol,_Period,hix));
         // ObjectCreate(ChartID(),lines_tag+"_L",OBJ_TEXT,0,iTime(_Symbol,_Period,lix),iLow(_Symbol,_Period,lix));
         if(!TextCreate(0,lines_tag+"_H",0,iTime(_Symbol,_Period,hix),iHigh(_Symbol,_Period,hix),DoubleToString(iHigh(_Symbol,_Period,hix),_Digits),_model,InpFontSize,
                        clrDeepPink,InpAngle,InpAnchor,InpBack,InpSelection,InpHidden,InpZOrder)) {
            return;
         }
         if(!TextCreate(0,lines_tag+"_L",0,iTime(_Symbol,_Period,lix),iLow(_Symbol,_Period,lix),DoubleToString(iLow(_Symbol,_Period,lix),_Digits),_model,InpFontSize,
                        clrLimeGreen,InpAngle,InpAnchor,InpBack,InpSelection,InpHidden,InpZOrder)) {
            return;
         }
         ChartRedraw();
         //then we store the following to track changes
         fvb=_fvb;
         clb=_clb;
      }
   }
}
//+------------------------------------------------------------------+
//| Creating Text object                                             |
//+------------------------------------------------------------------+
bool TextCreate(const long              chart_ID=0,               // chart's ID
                const string            name="Text",              // object name
                const int               sub_window=0,             // subwindow index
                datetime                time=0,                   // anchor point time
                double                  price=0,                  // anchor point price
                const string            text="Text",              // the text itself
                const string            font="Arial",             // font
                const int               font_size=10,             // font size
                const color             clr=clrRed,               // color
                const double            angle=0.0,                // text slope
                const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type
                const bool              back=false,               // in the background
                const bool              selection=false,          // highlight to move
                const bool              hidden=true,              // hidden in the object list
                const long              z_order=0) {              // priority for mouse click
//--- set anchor point coordinates if they are not set
//ChangeTextEmptyPoint(time,price);
//--- reset the error value
   ResetLastError();
//--- create Text object
   if(!ObjectCreate(chart_ID,name,OBJ_TEXT,sub_window,time,price)) {
      Print(__FUNCTION__,
            ": failed to create \"Text\" object! Error code = ",GetLastError());
      return(false);
   }
//--- set the text
   ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
//--- set text font
   ObjectSetString(chart_ID,name,OBJPROP_FONT,font);
//--- set font size
   ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,font_size);
//--- set the slope angle of the text
   ObjectSetDouble(chart_ID,name,OBJPROP_ANGLE,angle);
//--- set anchor type
   ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set color
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the object by mouse
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
   return(true);
}
//+------------------------------------------------------------------+
//| Filling indicator buffers from the iFractals indicator           |
//+------------------------------------------------------------------+
bool FillArraysFromBuffers(double &up_arrows[],        // indicator buffer for up arrows
                           double &down_arrows[],      // indicator buffer for down arrows
                           int ind_handle,             // handle of the iFractals indicator
                           int amount                  // number of copied values
                          )
  {
//--- reset error code
   ResetLastError();
//--- fill a part of the FractalUpBuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,0,amount,up_arrows)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iFractals indicator to the FractalUpBuffer array, error code %d",
                  GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- fill a part of the FractalDownBuffer array with values from the indicator buffer that has index 1
   if(CopyBuffer(ind_handle,1,0,amount,down_arrows)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iFractals indicator to the FractalDownBuffer array, error code %d",
                  GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- everything is fine
   return(true);
  }
//+------------------------------------------------------------------+
//| Structurt Fractals                                               |
//+------------------------------------------------------------------+
struct STRUCT_FRACTALS
  {
   int               fractal_type;           // fractal type ('-1' -> down, '1' -> up)
   double            fractal_price;          // fractal price
   datetime          fractal_time;           // fractal time
   //--- Constructor
                     STRUCT_FRACTALS()
     {
      fractal_type               = 0;
      fractal_price              = 0.0;
      fractal_time               = 0;        // "0" -> D'1970.01.01 00:00';
     }
  };
STRUCT_FRACTALS SFractals[];
//+------------------------------------------------------------------+
Fractals - Bill Williams' Indicators - Technical Indicators - Price Charts, Technical and Fundamental Analysis - MetaTrader 5 Help
  • www.metatrader5.com
All markets are characterized by the fact that on the most part the prices do not change too much, and only short periods of time (15–30 percent)...
Files:
HL.1.mq5  20 kb
 

First set the empty value (PLOT_EMPTY_VALUE) with PlotIndexSetDouble().

Then set in the arrow buffer all values older than ... on PLOT_EMPTY_VALUE.

Documentation on MQL5: Custom Indicators / PlotIndexSetDouble
Documentation on MQL5: Custom Indicators / PlotIndexSetDouble
  • www.mql5.com
PlotIndexSetDouble - Custom Indicators - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5