Author: Copyright 2018, MetaQuotes Software Corp.
6 Views
0 Downloads
0 Favorites
HLBands
ÿþ//+------------------------------------------------------------------+

//|                                                      HLBands.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 indicator_chart_window

#property indicator_buffers 3

#property indicator_plots   3

//--- plot Band Upper

#property indicator_label1  "Upper"

#property indicator_type1   DRAW_LINE

#property indicator_color1  clrCrimson

#property indicator_style1  STYLE_SOLID

#property indicator_width1  1

//--- plot Band Lower

#property indicator_label2  "Lower"

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrMediumSlateBlue

#property indicator_style2  STYLE_SOLID

#property indicator_width2  1

//--- plot Label day Upper

#property indicator_label3  "Open"

#property indicator_type3   DRAW_LINE

#property indicator_color3  clrLightSteelBlue

#property indicator_style3  STYLE_DOT

#property indicator_width3  1

//--- enums

enum ENUM_CALC_METHOD

  {

   PRICE_HL,            // High/Low

   PRICE_OC             // Open/Close

  };

enum ENUM_MODE_UPDATE

  {

   MODE_UPDATE_OPEN,    // at the opening of the bar

   MODE_UPDATE_ALWAYS   // always

  };

//--- input parameters

input ENUM_TIMEFRAMES   InpTimeframe      =  PERIOD_D1;        // Bands period

input ENUM_MODE_UPDATE  InpBandUpdate     =  MODE_UPDATE_OPEN; // Bands Update

input ENUM_CALC_METHOD  InpBandCalcMethod =  PRICE_HL;         // Bands Applied price

//--- indicator buffers

double         BufferH[];

double         BufferL[];

double         BufferOpen[];

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- indicator buffers mapping

   SetIndexBuffer(0,BufferH,INDICATOR_DATA);

   SetIndexBuffer(1,BufferL,INDICATOR_DATA);

   SetIndexBuffer(2,BufferOpen,INDICATOR_DATA);

//--- setting a code from the Wingdings charset as the property of PLOT_ARROW

   PlotIndexSetInteger(2,PLOT_ARROW,220);

   PlotIndexSetInteger(2,PLOT_SHOW_DATA,true);

//--- settings indicators parameters

   string tfn=StringSubstr(EnumToString(InpTimeframe),7);

   IndicatorSetString(INDICATOR_SHORTNAME,"High/Low Bands("+tfn+")");

   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

//--- setting buffer arrays as timeseries

   ArraySetAsSeries(BufferH,true);

   ArraySetAsSeries(BufferL,true);

   ArraySetAsSeries(BufferOpen,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[])

  {

//--- @>25@:0 =0 <8=8<0;L=>5 :>;85AB2> 10@>2 4;O @0AGQB0

   if(rates_total<3) return 0;

//--- #AB0=>2:0 <0AA82>2 1CD5@>2 :0: B09<A5@89

   ArraySetAsSeries(open,true);

   ArraySetAsSeries(high,true);

   ArraySetAsSeries(low,true);

   ArraySetAsSeries(close,true);

   ArraySetAsSeries(time,true);

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

   static int index_curr=WRONG_VALUE;

   static int index_prev=WRONG_VALUE;

   static datetime tm=0;

   int limit=rates_total-prev_calculated;

   if(limit>1)

     {

      limit=rates_total-2;

      index_curr=(InpTimeframe<PERIOD_MN1 ? BarShift(Symbol(),InpTimeframe,time[limit]) : BarShift(Symbol(),InpTimeframe,BeginOfYear(time[limit])));

      if(index_curr==WRONG_VALUE) return 0;

      ArrayInitialize(BufferH,EMPTY_VALUE);

      ArrayInitialize(BufferL,EMPTY_VALUE);

      ArrayInitialize(BufferOpen,EMPTY_VALUE);

      BufferH[limit]=(InpBandCalcMethod==PRICE_HL ? high[limit] : fmax(open[limit],close[limit]));

      BufferL[limit]=(InpBandCalcMethod==PRICE_HL ? low[limit]  : fmin(open[limit],close[limit]));

     }

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

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

     {

      index_curr=(InpTimeframe<PERIOD_MN1 ? BarShift(Symbol(),InpTimeframe,time[i]) : BarShift(Symbol(),InpTimeframe,BeginOfYear(time[i])));

      if(index_curr==WRONG_VALUE) return 0;

      static datetime time_bar=0;

      double H=UpperPrice(InpTimeframe,index_curr);

      double L=LowerPrice(InpTimeframe,index_curr);

      //---

      if(index_curr!=index_prev)

        {

         if(index_prev>index_curr)

           {

            time_bar=time[i];

            BufferH[i]=(InpBandUpdate==MODE_UPDATE_OPEN ? (InpBandCalcMethod==PRICE_HL ? high[i] : fmax(open[i],close[i])) : H);

            BufferL[i]=(InpBandUpdate==MODE_UPDATE_OPEN ? (InpBandCalcMethod==PRICE_HL ? low[i]  : fmin(open[i],close[i])) : L);

            BufferOpen[i]=open[i];

           }

         index_prev=index_curr;

        }

      //---

      int bar=BarShift(Symbol(),PERIOD_CURRENT,time_bar);

      if(bar==WRONG_VALUE) continue;

      if(bar==0)

        {

         BufferH[i]=(InpBandCalcMethod==PRICE_HL ? high[i] : fmax(open[i],close[i]));

         BufferL[i]=(InpBandCalcMethod==PRICE_HL ? low[i]  : fmin(open[i],close[i]));

         BufferOpen[i]=open[i];

        }

      else

        {

         BufferH[i]=BufferH[bar];

         BufferL[i]=BufferL[bar];

         BufferOpen[i]=BufferOpen[bar];

         if(InpBandUpdate==MODE_UPDATE_ALWAYS)

           {

            double highest=(InpBandCalcMethod==PRICE_HL ? H : HighestPrice(i,bar,open,close));

            double lowhest=(InpBandCalcMethod==PRICE_HL ? L : LowestPrice(i,bar,open,close));

            SetPrice(highest,i,bar,BufferH);

            SetPrice(lowhest,i,bar,BufferL);

           }

        }

     }

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

   return(rates_total);

  }

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

//| >72@0I05B =081>;LHCN F5=C F5?>G:8 10@>2                         |

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

double HighestPrice(const int start,const int end,const double &open[],const double &close[])

  {

   double array[];

   ArraySetAsSeries(array,true);

   int total=(end-start)+1;

   ArrayResize(array,total,20);

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

      array[i]=fmax(open[start+i],close[start+i]);

   return array[ArrayMaximum(array)];

  }

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

//| >72@0I05B =08<5=LHCN F5=C F5?>G:8 10@>2                         |

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

double LowestPrice(const int start,const int end,const double &open[],const double &close[])

  {

   double array[];

   ArraySetAsSeries(array,true);

   int total=(end-start)+1;

   ArrayResize(array,total,20);

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

      array[i]=fmin(open[start+i],close[start+i]);

   return array[ArrayMinimum(array)];

  }

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

//| #AB0=02;8205B F5=C F5?>G:5 10@>2                                 |

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

void SetPrice(const double price,const int start,const int end,double &buffer[])

  {

   for(int i=start; i<=end; i++)

      buffer[i]=price;

  }

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

//| >72@0I05B 25@E=NN F5=C 10@0                                     |

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

double UpperPrice(ENUM_TIMEFRAMES timeframe,const int index)

  {

   return

   (

    InpBandCalcMethod==PRICE_HL ? High(timeframe,index) :

    (Open(timeframe,index)==0 || Close(timeframe,index)==0 ? 0 : fmax(Open(timeframe,index),Close(timeframe,index)))

    );

  }

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

//| >72@0I05B =86=NN F5=C 10@0                                      |

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

double LowerPrice(ENUM_TIMEFRAMES timeframe,const int index)

  {

   return

   (

    InpBandCalcMethod==PRICE_HL ? Low(timeframe,index) :

    (Open(timeframe,index)==0 || Close(timeframe,index)==0 ? 0 : fmin(Open(timeframe,index),Close(timeframe,index)))

    );

  }

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

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

//| https://www.mql5.com/ru/code/1864                                |

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

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

  {

   datetime last_bar;

   if(!SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar))

     {

      datetime array[1];

      if(CopyTime(symbol_name,timeframe,0,1,array)==1)

         last_bar=array[0];

      else

         return WRONG_VALUE;

     }

   if(time>last_bar)

      return(0);

   int shift=Bars(symbol_name,timeframe,time,last_bar);

   datetime array[1];

   if(CopyTime(symbol_name,timeframe,time,1,array)==1)

      return(array[0]==time ? shift-1 : exact && time>array[0]+PeriodSeconds(timeframe) ? WRONG_VALUE : shift);

   return WRONG_VALUE;

  }

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

//| >72@0I05B 2@5<O C:070==>3> 10@0                                 |

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

datetime Time(const ENUM_TIMEFRAMES timeframe,const int index)

  {

   datetime array[];

   ArraySetAsSeries(array,true);

   if(CopyTime(Symbol(),timeframe,index,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B Open C:070==>3> 10@0                                  |

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

double Open(const ENUM_TIMEFRAMES timeframe,const int index)

  {

   double array[];

   ArraySetAsSeries(array,true);

   if(CopyOpen(Symbol(),timeframe,index,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B High C:070==>3> 10@0                                  |

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

double High(const ENUM_TIMEFRAMES timeframe,const int index)

  {

   double array[];

   ArraySetAsSeries(array,true);

   if(CopyHigh(Symbol(),timeframe,index,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B Low C:070==>3> 10@0                                   |

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

double Low(const ENUM_TIMEFRAMES timeframe,const int index)

  {

   double array[];

   ArraySetAsSeries(array,true);

   if(CopyLow(Symbol(),timeframe,index,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B Close C:070==>3> 10@0                                 |

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

double Close(const ENUM_TIMEFRAMES timeframe,const int index)

  {

   double array[];

   ArraySetAsSeries(array,true);

   if(CopyClose(Symbol(),timeframe,index,1,array)==1) return array[0];

   return 0;

  }

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

//| >72@0I05B =><5@ 4=O <5AOF0                                      |

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

int TimeDay(const datetime time)

  {

   MqlDateTime tm;

   int day_number=WRONG_VALUE;

   if(TimeToStruct(time,tm))

      day_number=tm.day;

   return day_number;

  }

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

//| >72@0I05B 40BC =0G0;0 3>40 C:070==>9 40BK                       |

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

datetime BeginOfYear(const datetime time)

  {

   MqlDateTime tm;

   if(!TimeToStruct(time,tm)) return WRONG_VALUE;

   tm.mon=1;

   tm.day=1;

   return StructToTime(tm);

  }

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

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

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

string NameTimeframe(const ENUM_TIMEFRAMES timeframe)

  {

   return StringSubstr(EnumToString(timeframe),7);

  }

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

Comments