Help for new programmer coding first program

 

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.

 
Bailey John Wickens:

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.

https://docs.mql4.com/series/ihighest


And the same for the Low 
 
Bailey John Wickens:

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 :) :) :) 

 
Bailey John Wickens #:

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 .


Reason: