If in 200 visible bars of history, there are 10 bullish engulf pattern, and in these 10 patterns, 5 are those patterns where low of bullish engulf is broken by close of a bear candle
so how can I write a loop to show only those patterns where low is not broken by close of candlestick in the visible bars.
you mean after bar2 at any point or within a range ?
Lets say there are high and lows on visible chart, I am looking to check from left to right how many engulf in visible chart are those where low of those engulf is not broken by body. If engulf low broken by close of candle then it should not show arrow on it, it should only show arrow which engulf are not broken by candle close of price from engulf to last recent bar.
here is my code attempt
//+------------------------------------------------------------------+ //| test.mq5 | //| Rodger Sen, Copyright 2023 | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Rodger Sen, Copyright 2023" #property link "https://www.mql5.com/" #property version "1.00" #property indicator_chart_window #property indicator_plots 0 double engulf=0,engulf2=0; int engulf_index = 0,engulf_index2=0; int lvb,_fvb,_clb,fvb=-1,clb=-1,hix,lix; string prefix = "fs_"; color clrBull = C'8,153,129'; color clrBear = C'242,54,69'; color clrNull = clrSnow; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping //--- 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[]) { //--- //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- if (id==CHARTEVENT_CHART_CHANGE) { FindHighLow(); FindEngulf(); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void FindEngulf() { FindBullishEngulf(hix); ObjectsDeleteAll(0,-1,OBJ_ARROW); int r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0; double s1=0,s2=0,s3=0,s4=0,s5=0,s6=0,s7=0,s8=0,s9=0,s10=0; for(int i=engulf_index; i>lix; i--) { if(iClose(NULL,0,i)<engulf) { FindBullishEngulf(i); s1 = iClose(NULL,0,i); r1=i; break; } } r1--; for(int i=r1; i>lix; i--) { if(iClose(NULL,0,i)<s1) { // ObjectDelete(0,"SnR"); FindBullishEngulf(i); s2 = iClose(NULL,0,i); r2=i; break; } } r2--; for(int i=r2; i>lix; i--) { if(iClose(NULL,0,i)<s2) { // ObjectDelete(0,"SnR"); FindBullishEngulf(i); s3 = iClose(NULL,0,i); r3=i; break; } } r3--; for(int i=r3; i>lix; i--) { if(iClose(NULL,0,i)<s3) { // ObjectDelete(0,"SnR"); FindBullishEngulf(i); s4 = iClose(NULL,0,i); r4=i; break; } } r4--; for(int i=r4; i>lix; i--) { if(iClose(NULL,0,i)<s3) { // ObjectDelete(0,"SnR"); FindBullishEngulf(i); s5 = iClose(NULL,0,i); r5=i; break; } } r5--; ChartRedraw(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void FindBullishEngulf(int ii) { for(int i=ii; i>1; i--) { // Find Bullish SNR if(iOpen(NULL,0,i)>iClose(NULL,0,i) && iOpen(NULL,0,i-1)<iClose(NULL,0,i-1) && iClose(NULL,0,i-1)>iOpen(NULL,0,i)) { //if(iClose(NULL,0,i)<=rates[i].close) { ArrowCreate(0,"Bullish_Engulf",0,iTime(NULL,0,i-1),iLow(NULL,0,i-1),234,ANCHOR_TOP,clrDeepPink); // } else ObjectsDeleteAll(0,-1,OBJ_ARROW); engulf = iClose(NULL,0,i); engulf_index=i; break; } } } //+------------------------------------------------------------------+ //| Find HighLow on Visible Chart Window | //+------------------------------------------------------------------+ void FindHighLow() { _fvb=(int)ChartGetInteger(ChartID(),CHART_FIRST_VISIBLE_BAR,0); _clb=(int)ChartGetInteger(ChartID(),CHART_WIDTH_IN_BARS,0); if (_fvb>0 &&(_fvb!=fvb||_clb!=clb)) { lvb=_fvb-(_clb-1); if (lvb<0) { lvb=0; } hix= iHighest(NULL,0,MODE_HIGH,(_fvb-lvb),lvb); // Highest Index of High lix= iLowest(NULL,0,MODE_LOW,(_fvb-lvb),lvb); // Highest Index of Low //Highest Lowest Bodies ArrowCreate(0,prefix+"H",0,iTime(NULL,0,hix),iHigh(NULL,0,hix),234,ANCHOR_BOTTOM,clrBear); ArrowCreate(0,prefix+"L",0,iTime(NULL,0,lix),iLow(NULL,0,lix),233,ANCHOR_TOP,clrBull); ChartRedraw(ChartID()); fvb=_fvb; clb=_clb; } } //+------------------------------------------------------------------+ //| Create the arrow | //+------------------------------------------------------------------+ bool ArrowCreate(const long chart_ID=0, // chart's ID const string name="Arrow", // arrow name const int sub_window=0, // subwindow index datetime time=0, // anchor point time double price=0, // anchor point price const uchar arrow_code=252, // arrow code const ENUM_ARROW_ANCHOR anchor=ANCHOR_BOTTOM, // anchor point position const color clr=clrRed, // arrow color const ENUM_LINE_STYLE style=STYLE_SOLID, // border line style const int width=1, // arrow size 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 ResetLastError(); if(!ObjectCreate(chart_ID,name,OBJ_ARROW,sub_window,time,price)) { Print(__FUNCTION__, ": failed to create an arrow! Error code = ",GetLastError()); return(false); } ObjectSetInteger(chart_ID,name,OBJPROP_ARROWCODE,arrow_code); ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,width); ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); //if(!ArrowCreate(0,InpName,0,date[d],price[p],32,InpAnchor,InpColor, // InpStyle,InpWidth,InpBack,InpSelection,InpHidden,InpZOrder)) { // return; //} return(true); } //+------------------------------------------------------------------+
try this
#property copyright "Discussion" #property link "https://www.mql5.com/en/forum/450830" #property version "1.00" #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 //--- plot Buy #property indicator_label1 "Buy" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrDeepSkyBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- plot Sell #property indicator_label2 "Sell" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrGold #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- indicator buffers double BuyBuffer[]; double SellBuffer[]; //we create a structure for the engulf class anEngulf{ //discovery time datetime discoveryTime; datetime bar1Time,bar2Time; double top,bottom; bool active; char direction;//-1 bearish 1 bullish 0 nothing public: anEngulf(void){reset();} ~anEngulf(void){reset();} void reset(){ discoveryTime=0; bar1Time=0; bar2Time=0; top=0.0; bottom=0.0; direction=0; active=false; } void setup_bullish(datetime _now, datetime _bar1, datetime _bar2, double _top, double _bottom){ direction=1; top=_top; bottom=_bottom; bar1Time=_bar1; bar2Time=_bar2; discoveryTime=_now; active=true; } void setup_bearish(datetime _now, datetime _bar1, datetime _bar2, double _top, double _bottom){ direction=-1; top=_top; bottom=_bottom; bar1Time=_bar1; bar2Time=_bar2; discoveryTime=_now; active=true; } bool is_active(){return(active);} char maintain(double _close,datetime _now){ if(_now>=discoveryTime){ //bullish if(direction==1){ if(_close>top){active=false;return(1);} if(_close<bottom){active=false;return(0);} } //bearish else if(direction==-1){ if(_close<bottom){active=false;return(-1);} if(_close>top){active=false;return(0);} } } return(0); } }; //and a rack of engulfs , or a shelf :P struct engulfShelf{ anEngulf engulfs[];//this is our collection engulfShelf(void){reset();} ~engulfShelf(void){reset();} void reset(){ ArrayFree(engulfs); } char read_bars(double b1Open, double b1Close, datetime b1Time, double b2Open, double b2Close, datetime b2Time, double b3Close, datetime b3Time_now){ //bullish if(b2Close>b2Open){ if(b1Close<b1Open){ if(b2Close>b1Open){ if(b2Open<b1Close){ //add engulfing int ix=add_engulf(); engulfs[ix].setup_bullish(b3Time_now,b1Time,b2Time,b2Close,b2Open); } } } } //bearish if(b2Close<b2Open){ if(b1Close>b1Open){ if(b2Close<b1Open){ if(b2Open>b1Close){ //add engulfing int ix=add_engulf(); engulfs[ix].setup_bearish(b3Time_now,b1Time,b2Time,b2Open,b2Close); } } } } //0 no signal //1 only buy //-1 only sell //2 both char signal=0; for(int i=0;i<ArraySize(engulfs);i++){ char local_signal=engulfs[i].maintain(b3Close,b3Time_now); if(local_signal!=0){ if(signal==0){signal=local_signal;} else if(signal==1){ if(local_signal==-1){signal=2;} } else if(signal==-1){ if(local_signal==1){signal=2;} } } } int from=ArraySize(engulfs)-1; for(int i=from;i>=0;i--){ if(!engulfs[i].is_active()){ remove(i); } } return(signal); } int add_engulf(){ int ns=ArraySize(engulfs)+1; ArrayResize(engulfs,ns,0); return(ns-1); } int remove(int ix){ int ns=ArraySize(engulfs)-1; engulfs[ix]=engulfs[ns]; ArrayResize(engulfs,ns,0); return(ns); } }; engulfShelf E; int OnInit() { E.reset(); //--- indicator buffers mapping SetIndexBuffer(0,BuyBuffer,INDICATOR_DATA); SetIndexBuffer(1,SellBuffer,INDICATOR_DATA); //--- setting a code from the Wingdings charset as the property of PLOT_ARROW PlotIndexSetInteger(0,PLOT_ARROW,233); PlotIndexSetInteger(1,PLOT_ARROW,234); //--- 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 from=prev_calculated; int to=rates_total-2; if(from==0){from=3;} for(int i=from;i<=to;i++){ char signal=E.read_bars(open[i-2],close[i-2],time[i-2],open[i-1],close[i-1],time[i-1],close[i],time[i]); if(signal==1){ BuyBuffer[i]=close[i]; } else if(signal==-1){ SellBuffer[i]=close[i]; } else if(signal==2){ BuyBuffer[i]=close[i]; SellBuffer[i]=close[i]; } } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+
No problem .
Be careful as sometimes the arrow you see comes from an engulfing pattern that is not neccesserrilly immediately preceding the signal bar.
This is where you do ninja stuff and add information popups on hovering , shapes colors etc ,instead of using iClose and iOpen you can use the "open" and "close" buffers which are in the OnCalculate function signature
You can make a function that passes in the index (if you make a for loop inside OnCalculate)
EDIT- I see that is what Lorentzos has done


- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
If in 200 visible bars of history, there are 10 bullish engulf pattern, and in these 10 patterns, 5 are those patterns where low of bullish engulf is broken by close of a bear candle
so how can I write a loop to show only those patterns where low is not broken by close of candlestick in the visible bars.