//+------------------------------------------------------------------+ //| highs_lows.mq5 | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "AHMAD KAZBAR" #property link "https://ahmedkzbar.web.app/" #property version "1.6" #property indicator_chart_window #property indicator_buffers 6 #property indicator_plots 1 #property indicator_label1 "zigzag" #include #include #include #include input int Depth = 5 ; // Period input int AtrPeriod= 200 ; // ATR Period input double AtrFactor = 1.5 ; // Calculation between level On basis of ATR input int lookback_htf = 12; // Calculate % of candles chart input int history = 50; // History (Number of levels) input bool candle_HeikenAshi = true; // Candle Type input group "******* Style *******" input bool show_break_lines = true ; // Show break lines input group "******* High & Resitance Color *******" input ColorList High_color = RedColor; // High Color input ColorList Resitance_color = LightPinkColor; // Resitance Color input group "******* Low & Support Color *******" input ColorList Low_color = LightBlueColor; // Low Color input ColorList Support_color = LightGreenColor; // Support Color double ExtTRBuffer[],ExtATRBuffer[]; double ExtZigzag[]; double ExtTRBuffer_htf[],ExtATRBuffer_htf[]; double ExtRSI[]; double ExtRSIBuffer[]; double ExtPosBuffer[]; double ExtNegBuffer[]; color PH,PL,SC,RC; CArrayObj prevResitance; CArrayObj prevSupport; CArrayObj lows; CArrayObj highs; string prefix; datetime previousTimeCurrent = 0; string btn1 ="btn1",btn2 = "btn2",btn3 ="btn3",btn4="btn4",btn5="btn5",btn6="btn6",btn7="btn7"; bool show_Resitance = false,show_Support = false,show_prevSupport =true,show_prevResitance = true,show_Break_levels = false; bool show_Resitance_htf = true,show_Support_htf = true,show_prevSupport_htf = true,show_prevResitance_htf = true,show_htf_levels = false,show_levels = true; datetime lastBarTime = 0; datetime lastBarTimeDraw = 0; int start_index; double last_high,last_low,last_high_poi,last_low_poi; int last_high_pos,last_low_pos; datetime last_high_time,last_low_time; CGmmaPanel gammaPanel; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CLevel : public CObject { public: double c; double o; double h; double l; datetime t; int i; bool is_peak ; string type; int rsiValue; CLevel(double _c,double _o,double _h,double _l,datetime _t,int _i,string _type,bool _peak,int _rsiValue = 0) { c = _c; o = _o; h = _h; l = _l; t= _t; i = _i; type = _type; is_peak = _peak; rsiValue = _rsiValue; } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { gammaPanel.ChartEvent(id,lparam,dparam,sparam); if(id == CHARTEVENT_OBJECT_CLICK) // Check if an object (button) was clicked { if(sparam == btn1) // Check if it's our button { if(show_Resitance) { ObjectSetString(0, btn1, OBJPROP_TEXT, "Show Pivot High"); ObjectsDeleteAll(0,prefix+"Resitance"); } else { ObjectSetString(0,btn1, OBJPROP_TEXT, "Hide Pivot High"); drawHighPivot(); } show_Resitance = !show_Resitance; } if(sparam == btn2) // Check if it's our button { if(show_Support) { ObjectSetString(0, btn2, OBJPROP_TEXT, "Show Pivot Low"); ObjectsDeleteAll(0,prefix+"Support"); } else { ObjectSetString(0,btn2, OBJPROP_TEXT, "Hide Pivot Low"); drawLowPivot(); } show_Support = !show_Support; } /// END BTN2 if(sparam == btn3) { Print(prevSupport.Total()); if(show_prevSupport) { ObjectSetString(0, btn3, OBJPROP_TEXT, "Show Support Levels"); ObjectsDeleteAll(0,prefix+"prevSupport"); } else { ObjectSetString(0, btn3, OBJPROP_TEXT, "Hide Support Levels"); drawSupport(); } show_prevSupport = !show_prevSupport; } if(sparam == btn4) { Print(prevResitance.Total()); if(show_prevResitance) { ObjectSetString(0, btn4, OBJPROP_TEXT, "Show Resitance Levels"); ObjectsDeleteAll(0,prefix+"prevResitance"); } else { ObjectSetString(0, btn4, OBJPROP_TEXT, "Hide Resitance Levels"); drawResitance(); } show_prevResitance = !show_prevResitance; } } ChartRedraw(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0,ExtZigzag,INDICATOR_DATA); SetIndexBuffer(1,ExtATRBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,ExtTRBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(3,ExtRSIBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(4,ExtPosBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(5,ExtNegBuffer,INDICATOR_CALCULATIONS); PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); StringConcatenate(prefix,"SRChannel","\n"); previousTimeCurrent = iTime(_Symbol, PERIOD_CURRENT, 1); start_index=0; if(lookback_htf > 90) { Alert("Calculate % of candles chart number must be less than 90."); return(INIT_FAILED); } PH = GetColor(High_color); PL = GetColor(Low_color); SC = GetColor(Support_color); RC = GetColor(Resitance_color); btn1 = "PANEL\n"+btn1; btn2 = "PANEL\n"+btn2; btn3 = "PANEL\n"+btn3; btn4 = "PANEL\n"+btn4; btn5 = "PANEL\n"+btn5; gammaPanel.Oninit(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reson) { ObjectsDeleteAll(0,"SRChannel"); ObjectsDeleteAll(0,"PANEL"); ClearChart(); gammaPanel.Destroy(reson); } //+------------------------------------------------------------------+ //| 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[]) { if(prev_calculated==0) { if(start_index == 0) start_index= rates_total - (rates_total * 95 / 100) - Depth*2; } else { start_index=prev_calculated-1; } datetime currentBarTime = time[rates_total - 1]; static bool chart_is_load = false; ATR(rates_total,AtrPeriod+1,prev_calculated,high,low,close,open); RSI(rates_total,prev_calculated,close); for(int i = start_index; i < rates_total-1 ; i++) { //----START FIND HIGH AND LOW---// FindHigh_Low(i,time,open,high,low,close,chart_is_load); //----END FIND HIGH AND LOW---// CheckMarketStructure(i,time,close,open,low,high,chart_is_load); } if(currentBarTime != lastBarTime) { lastBarTime = currentBarTime; chart_is_load = true; } if(currentBarTime > lastBarTimeDraw) { drawLTFLevels(); lastBarTimeDraw = currentBarTime+11*PeriodSeconds(); } return(rates_total); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ClearChart() { clearList(prevResitance); clearList(prevSupport); clearList(highs); clearList(lows); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void clearList(CArrayObj &list) { for(int i = 0 ; i < list.Total()-1;i++) { CLevel* level = list.At(i); ObjectDelete(0,level.type); delete level; } list.Clear(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void FindHigh_Low(int i,const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[],bool chart_is_load) { int idx = i - Depth; if(isHigh(i,high,Depth)) { if(IsValueFarEnough(high[idx],highs,ExtATRBuffer[idx])) { int pivot_id = idx; CLevel* level = new CLevel(close[pivot_id],open[pivot_id],high[pivot_id],low[pivot_id],time[pivot_id],pivot_id,prefix+"Resitance"+"\n"+DoubleToString(close[pivot_id],_Digits),true,(int)ExtRSIBuffer[pivot_id]); AddToLimitedArray(highs,level,chart_is_load); last_high = high[idx]; last_high_pos = idx; if(chart_is_load && show_Resitance) DrawRect(level.type,level.h,level.o,level.t,lastBarTime+12*PeriodSeconds(),PH,STYLE_DASHDOT,true,2,1); } } if(isLow(i,low,Depth)) { if(IsValueFarEnough(low[idx],lows,ExtATRBuffer[idx])) { int pivot_id = idx; CLevel* level = new CLevel(close[pivot_id],open[pivot_id],high[pivot_id],low[pivot_id],time[pivot_id],pivot_id,prefix+"Support"+"\n"+DoubleToString(close[pivot_id],_Digits),false,(int)ExtRSIBuffer[pivot_id]); AddToLimitedArray(lows,level,chart_is_load); last_low = low[idx]; last_low_pos = idx; if(chart_is_load && show_Support) DrawRect(level.type,level.l,level.o,level.t,lastBarTime+12*PeriodSeconds(),PL,STYLE_DASHDOT,true,2,1); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CheckMarketStructure(int i,const datetime &time[],const double &close[],const double &open[],const double &low[],const double &high[],bool drawsIsLoaded) { for(int j = highs.Total()-1 ; j >= 0 ; j--) { CLevel* level = highs.At(j); double break_price = close[i] ; double to_break_price = level.h; if(break_price > to_break_price && time[i] > level.t) { if(drawsIsLoaded) ObjectDelete(0,level.type); string name = prefix+"break_high"+"\n"+DoubleToString(level.l,_Digits)+IntegerToString(level.i); //DrawHorizontalLine(name,to_break_price,to_break_price,level.t,time[i],clrDarkRed,STYLE_SOLID,1); CLevel* level2 = new CLevel(close[i],open[i],high[i],low[i],level.t,i,prefix+"prevSupport"+"\n"+DoubleToString(i,_Digits),false,level.rsiValue); prevSupport.Insert(level2,0); double ots = (level2.h + level2.l) / 2.0; color myColor = RGBToColor(255 * (100 - level.rsiValue / 70.0),255,255 * (100 -level.rsiValue / 70.0)); if(drawsIsLoaded && show_prevSupport) { DrawRect(level2.type,low[i],high[i],level2.t,lastBarTime+12*PeriodSeconds(),SC,STYLE_DASHDOT,true,2,1); } last_high_poi = ots;; highs.Delete(j); last_high = 0.0; } } for(int j = lows.Total()-1 ; j >= 0 ; j--) { CLevel* level = lows.At(j); double break_price = close[i] ; double to_break_price= level.l; if(break_price < to_break_price && time[i] > level.t) { if(drawsIsLoaded) ObjectDelete(0,level.type); string name = prefix+"break_low"+"\n"+DoubleToString(level.l,_Digits)+IntegerToString(level.i); //DrawHorizontalLine(name,to_break_price,to_break_price,level.t,time[i],clrDarkRed,STYLE_SOLID,1); double new_poi = (level.h + level.l) / 2; CLevel* level2 = new CLevel(close[i],open[i],high[i],low[i],i,prefix+"prevResitance"+"\n"+IntegerToString(i),true,level.rsiValue); prevResitance.Insert(level2,0); double ots = (level2.h + level2.l) / 2.0; color myColor = RGBToColor(255,255 * (level.rsiValue / 70.0),255 * (level.rsiValue / 70.0)); if(drawsIsLoaded && show_prevResitance) { DrawRect(level2.type,high[i],low[i],level2.t,lastBarTime+12*PeriodSeconds(),RC,STYLE_DASHDOT,true,2,1); } last_low_poi = (level2.h + level2.l) / 2; lows.Delete(j); last_low = 0.0; } } for(int j = prevResitance.Total()-1 ; j >=0 ; j--) { CLevel* level = prevResitance.At(j); if(close[i] > level.h && time[i] > level.t) { if(drawsIsLoaded) { ObjectDelete(0,level.type); } prevResitance.Delete(j); } } for(int j = prevSupport.Total()-1 ; j >= 0 ; j--) { CLevel* level = prevSupport.At(j); if(close[i] < level.l && time[i] > level.t) { if(drawsIsLoaded) { ObjectDelete(0,level.type); } prevSupport.Delete(j); } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void drawLTFLevels() { if(show_Resitance) { drawHighPivot(); } if(show_Support) { drawLowPivot(); } if(show_prevResitance) { drawResitance(); } if(show_prevSupport) { drawSupport(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void ATR(int rates_total,int ExtPeriodATR,int prev_calculated,const double &_H[],const double &_L[],const double &_C[],const double &_O[]) { if(rates_total<=ExtPeriodATR) return; int i,start; //--- preliminary calculations if(prev_calculated==0) { ExtTRBuffer[0]=0.0; ExtATRBuffer[0]=0.0; //--- filling out the array of True Range values for each period for(i=1; i0?diff:0); sum_neg+=(diff<0?-diff:0); } //--- calculate first visible value ExtPosBuffer[14]=sum_pos/14; ExtNegBuffer[14]=sum_neg/14; if(ExtNegBuffer[14]!=0.0) ExtRSIBuffer[14]=100.0-(100.0/(1.0+ExtPosBuffer[14]/ExtNegBuffer[14])); else { if(ExtPosBuffer[14]!=0.0) ExtRSIBuffer[14]=100.0; else ExtRSIBuffer[14]=50.0; } //--- prepare the position value for main calculation pos=14+1; } //--- the main loop of calculations for(int i=pos; i0.0?diff:0.0))/14; ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(14-1)+(diff<0.0?-diff:0.0))/14; if(ExtNegBuffer[i]!=0.0) ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]); else { if(ExtPosBuffer[i]!=0.0) ExtRSIBuffer[i]=100.0; else ExtRSIBuffer[i]=50.0; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool IsValueFarEnough(double NeWvalue,CArrayObj &list,double A) { if(list.Total()==0) return true; for(int i=list.Total()-1;i>=0;i--) { CLevel* level = list.At(i); double val = level.is_peak ? level.h : level.l; double dis = MathAbs(NeWvalue - val); if(dis <= (A)) { return false; break; } } return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ void drawSupport() { for(int i = 0 ; i <= prevSupport.Total()-1 ; i++) { CLevel* level = prevSupport.At(i); color myColor = RGBToColor((level.rsiValue * 255.0) /30,255,(level.rsiValue * 255.0)/30); DrawRect(level.type,level.h,level.l,level.t,lastBarTime+12*PeriodSeconds(),myColor,STYLE_DASHDOT,true,2,1); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void drawResitance() { for(int i = 0 ; i <= prevResitance.Total()-1 ; i ++) { CLevel* level = prevResitance.At(i); color myColor = RGBToColor(255,255 * (level.rsiValue / 30.0),255 * (level.rsiValue / 30.0)); DrawRect(level.type,level.h,level.l,level.t,lastBarTime+12*PeriodSeconds(),myColor,STYLE_DASHDOT,true,2,1); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void drawHighPivot() { for(int i = highs.Total()-1 ; i >= 0 ; i --) { CLevel* level = highs.At(i); DrawRect(level.type,level.h,level.l,level.t,lastBarTime+12*PeriodSeconds(),PH,STYLE_DASHDOT,true,2,1); //DrawHorizontalLine(level.type+"C",level.c,level.c,level.t,iTime(_Symbol,PERIOD_CURRENT,0)+1*PeriodSeconds(),clrGreen,STYLE_SOLID,2); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void drawLowPivot() { for(int i = lows.Total()-1 ; i >=0 ; i --) { CLevel* level = lows.At(i); DrawRect(level.type,level.h,level.l,level.t,lastBarTime+12*PeriodSeconds(),PL,STYLE_DASHDOT,true,2,1); //DrawHorizontalLine(level.type+"C",level.c,level.c,level.t,iTime(_Symbol,PERIOD_CURRENT,0)+1*PeriodSeconds(),clrGreen,STYLE_SOLID,2); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void AddToLimitedArray(CArrayObj &list,CObject *newElement,bool chart_is_load) { list.Add(newElement); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ color RGBToColor(double aR,double aG,double aB) { int int_r=(int)MathRound(aR); int int_g=(int)MathRound(aG); int int_b=(int)MathRound(aB); int Color=0; Color=int_b; Color<<=8; Color|=int_g; Color<<=8; Color|=int_r; return((color)Color); } //+------------------------------------------------------------------+ // Get R component double GetR(color aColor) { return(aColor&0xff); } // Get G component double GetG(color aColor) { return((aColor>>8)&0xff); } // Get B component double GetB(color aColor) { return((aColor>>16)&0xff); } //+------------------------------------------------------------------+