any help on what methods I can use to write this - im stuck on how to find the highs after 'x' consecutive lower bars and the lows after 'x' consecutive higher bars
any help very much appreciated.
Does anyone have any idea or tips to help me with my first ea - ive done everything I need to do in the EA to make it work and run well - however im having a little trouble with my findHigh and findLow functions
Im wanting to place an order on a high after having 'x' amount of candles that are lower - for example we have a high and then after 5 consecutive lower candles, the EA places a buy stop at the high until the next high has had 5 consecutive lower candles - when this happens the previous order gets deleted and replaced with this newer order.
and the same for a sell...
any help on what methods I can use to write this - im stuck on how to find the highs after 'x' consecutive lower bars and the lows after 'x' consecutive higher bars
any help very much appreciated.
Hello . Consult the following code . It is for MT5 , can be ported to MT4 as well .
Most of the lines are comments that describe the process , it is not as complex as it appears .
Cheers
mql5 find recent high and low
#property copyright "Read The Discussion" #property link "https://www.mql5.com/en/forum/439895" #property version "1.00" input int consecutiveBarsRight=5;//bars to the right to be "wider" than input int consecutiveBarsLeft=5;//bars to the left to be "wider" than //these are explained where they are used enum search_mode{ search_recent=0,//recent search_with_max_bars=1//with max bars }; input search_mode searchMode=search_recent;//Search mode from the live bar input int searchMaxBars=250;//Max bars (or -1 for unlimited recent mode) //we setup a system tag to manage our objects string system_tag="TEST_"; //we declare a bar timestamp to detect new bars //when a new bar forms we will be running the search again datetime barStamp=0; int OnInit() { ObjectsDeleteAll(ChartID(),system_tag);//delete our test objects //reset the barstamp barStamp=0; return(INIT_SUCCEEDED); } void OnTick() { //get the latest time datetime now=iTime(_Symbol,_Period,0); //if this time is bigger than the barStamp , access the search if(now>barStamp){ //delete our objects ObjectsDeleteAll(ChartID(),system_tag); //update our barStamp barStamp=now; //find a high int highIndex=findHighLow(0,consecutiveBarsLeft,consecutiveBarsRight,searchMode,1,searchMaxBars); //if we found a high if(highIndex!=-1){ //create it double price=iHigh(_Symbol,_Period,highIndex); datetime time=iTime(_Symbol,_Period,highIndex); ObjectCreate(ChartID(),system_tag+"_HIGH",OBJ_TREND,0,time,price,TimeCurrent(),price); ObjectSetInteger(ChartID(),system_tag+"_HIGH",OBJPROP_RAY_LEFT,false); ObjectSetInteger(ChartID(),system_tag+"_HIGH",OBJPROP_RAY_RIGHT,true); } //find a low int lowIndex=findHighLow(0,consecutiveBarsLeft,consecutiveBarsRight,searchMode,-1,searchMaxBars); //if we found a low if(lowIndex!=-1){ //create it double price=iLow(_Symbol,_Period,lowIndex); datetime time=iTime(_Symbol,_Period,lowIndex); ObjectCreate(ChartID(),system_tag+"_LOW",OBJ_TREND,0,time,price,TimeCurrent(),price); ObjectSetInteger(ChartID(),system_tag+"_LOW",OBJPROP_RAY_LEFT,false); ObjectSetInteger(ChartID(),system_tag+"_LOW",OBJPROP_RAY_RIGHT,true); } ChartRedraw(); } } void OnDeinit(const int reason) { ObjectsDeleteAll(ChartID(),system_tag);//delete our test objects } int findHighLow(int live_bar_or_simulation_of,//this is the live bar index with righmost bar being [0] as this uses iHighest / iLowest int leftBars,//bars to the left of our candidate high that must be lower than it int rightBars,//bars to the right of our candidate high that must be lower than it search_mode _mode,//the search mode char search_for,//-1 for low +1 for high int max_bars=-1){//max bars if max search is used /* one "trick" to find our high/low is to check consecutive bars to the left + consecutive bars to the right + 1 from our point of interest and backwards , but we can also pull another card out and define a maximum distance within which our "extreme" point can be . So right of the bat we recognize 2 modes 1.most recent , no max limit 2.highest in the range of 0 to max bars from the live bar That means we need to prevent the user from any errors so if they provide a max bars value that is smaller than the leftBars+1+rightBars we don't let them unless they are in most recent mode and max bars is -1 So check one : */ bool valid_max_bars=(max_bars>=(leftBars+1+rightBars)); if(valid_max_bars||(_mode==search_recent&&max_bars==-1)){ /* second check : since this function can be used in the past we need to make sure there are -simulation bar index + left bars + right bars + 1 bars at least available if on mode 1 -max bars from our simulation bar index at least available if on mode 2 so , total bars are : */ int total_bars=Bars(_Symbol,_Period); //and we are using iHigh iLow iHighest iLowest which map fro [total_bars-1](oldest) to [0](newest) //so our check is mode 1? mode 1 result mode 2 result bool enough_bars=_mode==search_recent?((live_bar_or_simulation_of+1+leftBars+rightBars)<total_bars):((live_bar_or_simulation_of+max_bars)<total_bars); if(enough_bars){ /* let's start from the easy mode , the maximum one */ //MODE MAX :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if(_mode==search_with_max_bars){ /* what we'll do here is find the extreme level over the max # of bars and if its location indicates it has room to the left (at least leftBars ) and room to the right (at least rightBars) it is what we are looking for otherwise we look to its right from where it was found + rightBars So , we need a switch and a while loop */ bool found=false; int bars_range=max_bars;//the size of our search , initially //remember we will be searching from the live bar or a simulation point of a live bar in the past //our starting point does not change but it has a big name so let's reduce it to i int i=live_bar_or_simulation_of+1; /* why did we +1 it ? because iLowest and iHighest include the starting bar of the search in their calculations we are firing this off only on new bars so we would be at the open of bar i (the live_or_simulation_of) which means for a live call we would send [0] and start the search from [1] and in the past we would send wherever we pretend we are in time (the open of a bar since its a known time in the past) We want to maintain symmetry between the past tests and live behavior */ /* so what is our criteria here : -if we haven't found what we are looking for -and we have more than left+1+right bars in the range left keep searching */ while(!found&&bars_range>=(leftBars+1+rightBars)){ /* now what ? now we define a candidate index which takes the value of the highest or the lowest -these return index # not values of price- depending on what we are looking for Pretty simple call , give me the lowest or the highest starting from i within that range */ int candidate=-1; if(search_for==1){ candidate=iHighest(_Symbol,_Period,MODE_HIGH,bars_range,i); //meaning : give us the index of the highest high bar starting from i until i+bars_range } else{//we assume the user wont send -69 here for what to look for candidate=iLowest(_Symbol,_Period,MODE_LOW,bars_range,i); //meaning : give us the index of the lowest low bar starting from i until i+bars_range } //so , is there a candidate ? if(candidate>=0){ /* if our range is i(recent) to i+bars_range(past) does that candidate have room to the left and right to meet our criteria of leftBars and rightBars ? */ bool room_to_the_left=((((i-1)+bars_range)-candidate)>=leftBars);//-1 because we adjusted i with +1 earlier bool room_to_the_right=((candidate-(i-1))>=rightBars); //we need both if(room_to_the_left&&room_to_the_right){ found=true;//redundant //this is our candidate so we just return it and we finish for this mode of search return(candidate); } //or we narrow the search if this is not our candidate else{ //to narrow the search there must be room to the right but our while condition takes care of that //so let's just calculate the new bars range bars_range=candidate+rightBars-(i-1);//-1 because we adjusted i with +1 earlier //and that is it for this mode } }else{ break; } } }//MODE MAX ENDS HERE ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: /* now the recent mode What is the difference of this to the previous one ? this mode will have a search "window" which will be moved toward the past gradually so as to find the most recent high or low that satisfies or condition regardless of where it stands in a bigger "range" of bars , so this may find a high or low that is not the highest or lowest if you look at the chart but it fits our criteria. so we brew coffee and code it */ else if(_mode==search_recent){//MODE RECENT :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //an else would have worked but it helps if we see the enumeration /* let's pause and consider some things. What could happen if we request the highest or lowest in a window of size leftBars+1+rightBars (a mini equivalent of bars_range in the previous mode) a.we find a high or low smack dab in the middle in which case it satisfies our criteria so we win b.we find a high or low that leans toward the right which means it has the leftBars we need but not the rightBars in this case we move the search window to where it was found so as i would be the "live bar" so its not part of the check c.we find a high or low that leans toward the left which means it has the rightBars we need but not the leftBars in this case we move the search window so as where it was found to be in the middle of the window Simpler than expected , and notice how on mode max we adjust the window of search while here we adjust the starting point So lets setup the window */ int window=leftBars+1+rightBars;//could this be called bars_range like before ? Yes //and our starting point int i=live_bar_or_simulation_of+1; //and let's also find the last point of search available //this will be total bars minus left_bars minus right_bars minus 3 (1 for literal , 1 for the bar in the middle , 1 for the starting point) int last_i=total_bars-3-leftBars-rightBars; //but ! the user may have sneaked a max bars value in with this mode in which case //our last possible search i becomes if(max_bars!=-1){//it is valid because we passed that filter last_i=((i-1)+max_bars)-3-leftBars-rightBars;//-1 because we adjusted i with +1 earlier //what happened ? we projected the last bar in general , then calculated the last bar we can have as a starting point ! } //and we are ready to start , the i moves here , it grows as we move in the past so while(i<=last_i){ //again we use the candidate int candidate=-1; if(search_for==1){candidate=iHighest(_Symbol,_Period,MODE_HIGH,window,i);} else{candidate=iLowest(_Symbol,_Period,MODE_LOW,window,i);} if(candidate>=0){ //and we check against our cases //case a :we find a high or low smack dab in the middle if(candidate==((i-1)+rightBars+1)){//-1 because we adjusted i with +1 earlier return(candidate);//we send it up } //case b :we find a high or low that leans toward the right else if(candidate<((i-1)+rightBars+1)){//-1 because we adjusted i with +1 earlier i=candidate+1;//why +1 ? because iHighest/iLowest will include i in the search and we dont want to be stuck in that high or low } //case c :we find a high or low that leans toward the left else if(candidate>((i-1)+rightBars+1)){ //now we want the candidate to be at the middle of the window so //the search will start from : candidate-rightBars i=candidate-rightBars; } //and we are done }else{ break; } } }//MODE RECENT ENDS HERE ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: }else{Print("Not enough bars in history");} }else{Print("Max Bars are less than the sum of LB+1+RB");} return(-1); }
thanks all for your feedback i will get looking though this today - very much appreciated :) :) :)
thanks all for your feedback i will get looking though this today - very much appreciated :) :) :)
anytime
Also , read the docs provided by @Daniel Cioca first as i forgot to place links to the documentation .
![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Does anyone have any idea or tips to help me with my first ea - ive done everything I need to do in the EA to make it work and run well - however im having a little trouble with my findHigh and findLow functions
Im wanting to place an order on a high after having 'x' amount of candles that are lower - for example we have a high and then after 5 consecutive lower candles, the EA places a buy stop at the high until the next high has had 5 consecutive lower candles - when this happens the previous order gets deleted and replaced with this newer order.
and the same for a sell...
any help on what methods I can use to write this - im stuck on how to find the highs after 'x' consecutive lower bars and the lows after 'x' consecutive higher bars
any help very much appreciated.