Finding the High and Low for a cluster of candles

 

Hi All,

I am trying working on an MA cross EA where the stoploss is right above the high of cluster of candles greater than the MA if i'm in a sell and right below the the low of the cluster of candles less than the MA if im in a buy but i'm having a problem figuring out the code. Here is what I have so far:

   {
   double currMA=iMA(_Symbol,Period(),MAPeriod,MAShift,MaMethod,PRICE_CLOSE,0);
   datetime timeforcandle1;
   datetime timeforlastcandle;

   
   if(Open[0]<currMA && Close[0]>currMA)
   {
    timeforcandle1=Time[0];
    int high_anchor= iBarShift(_Symbol,Period(),timeforcandle1,false);
   }
   if(Open[0]>currMA && Close[0]<currMA)
   {
    timeforlastcandle=Time[0];
    int low_anchor=iBarShift(_Symbol,Period(),timeforlastcandle,false);
   }

   int HighestCandleNO=iHighest(_Symbol,Period(),MODE_HIGH,high_anchor,low_anchor);
   double HighestCandlePrice=High[HighestCandleNO];
   

   int LowestCandleNo=iLowest(_Symbol,Period(),MODE_LOW,low_anchor,high_anchor);
   double LowestCandlePrice=Low[LowestCandleNo];
  }

i think i'm using the iBarShift func correctly but I could be wrong. If there is any guidance anyone could provide in this matter, it will be greatly appreciated.

 
Nita Forex:


where the stoploss is right above the high of cluster of candles greater than the MA if i'm in a sell and right below the the low of the cluster of candles less than the MA if im in a buy

Maybe it will help if you provide an image of what you're trying to accomplish because, the way you described it, you can't use iHighest/iLowest because they require a set amount of bars to count but, in your situation, I don't think there's a way to know the count value beforehand. You would have to use a while loop to determine the amount that it should count, then you can pass that value in the count parameter of iHighest/iLowest, and it will return the index of the bar with the highest / lowest of the type you specified (i.e., MODE_HIGH, MODE_LOW).

 
Nita Forex: i think i'm using the iBarShift func correctly but I could be wrong.
   timeforcandle1=Time[0];
    int high_anchor= iBarShift(_Symbol,Period(),timeforcandle1,false);

The shift of Time[x] is always x.

 
Alexander Martinez #:

Maybe it will help if you provide an image of what you're trying to accomplish because, the way you described it, you can't use iHighest/iLowest because they require a set amount of bars to count but, in your situation, I don't think there's a way to know the count value beforehand. You would have to use a while loop to determine the amount that it should count, then you can pass that value in the count parameter of iHighest/iLowest, and it will return the index of the bar with the highest / lowest of the type you specified (i.e., MODE_HIGH, MODE_LOW).

i apologize for not being clearer but hopefully this pic accurately explains what i'm trying to do 

Files:
 
Nita Forex #:

i apologize for not being clearer but hopefully this pic accurately explains what i'm trying to do 

No worries!

So, yeah, you need a while loop to figure out the count parameter of iHighest/iLowest.

It's pretty simple if all you care about is the last crossover.

If you want to do it for all the price history on the chart, it gets more complicated. You'll have to keep track of when price crosses over the MA and then find the difference between that crossover and the previous crossover, then call iHighest/iLowest.

Here's an example of determining the proper count parameter for iHighest/iLowest for the last crossover.



And here's the accompanying code, I figured that it's easier to code it than to bother explaining it and all the caveats. For what it's worth, there's probably better ways to go about this.

if (prev_calculated == 0) {
  const int period  = 14;
  const int limit   = Bars - 1 - period;
  
  //--- Init SimpleMA Buffer
  SimpleMAOnBuffer(rates_total, prev_calculated, 1, period, close, ExtMA);
  
  //--- Find last crossover
  int count                = 0;      //--- count param for iHighest/iLowest
  bool found               = false;  //--- Exit for-loop when found == true
  bool isCloseHigherThanMA = false;  //--- Helps to determine whether to use iHighest or iLowest
  
  for (int i = 1; i < Bars && !found;) {
    while (close[i] > ExtMA[i]) {
      count++;
      i++;
      found               = true;
      isCloseHigherThanMA = true;
    }
    
    //--- Since we only care about the last crossover, we break from the for-loop if found == true
    if (found) {
      break;
    }
    
    while (close[i] < ExtMA[i]) {
      count++;
      i++;
      found = true;
    }
  }
  
  //--- now we have the proper value for the count parameter of iHighest/iLowest
  //--- and can use that to get the index of the highest high / lowest low, along with the High[] / Low[] of that index

  double stoploss = 0.0;
  int index       = 1;
  
  if (isCloseHigherThanMA) {
    index     = iLowest(NULL, 0, MODE_LOW, count, 1);
    stoploss  = Low[index];
  } else {
    index     = iHighest(NULL, 0, MODE_HIGH, count, 1);
    stoploss  = High[index];
  }
  
  Comment("Count: ", count,
            "\nIndex: ", index,
            "\nStoploss: ", DoubleToString(stoploss, Digits));
}
 
Alexander Martinez #:

No worries!

So, yeah, you need a while loop to figure out the count parameter of iHighest/iLowest.

It's pretty simple if all you care about is the last crossover.

If you want to do it for all the price history on the chart, it gets more complicated. You'll have to keep track of when price crosses over the MA and then find the difference between that crossover and the previous crossover, then call iHighest/iLowest.

Here's an example of determining the proper count parameter for iHighest/iLowest for the last crossover.



And here's the accompanying code, I figured that it's easier to code it than to bother explaining it and all the caveats. For what it's worth, there's probably better ways to go about this.

thank you... it's said that there is more than one way to skin a cat... not literally of course... but as long as it gets the job done there's room for improvement later... ill give it a try tho.. again thanks

 
Nita Forex #:

thank you... it's said that there is more than one way to skin a cat... not literally of course... but as long as it gets the job done there's room for improvement later... ill give it a try tho.. again thanks

No problem! If you need help, just come back and share your attempt. Take care!

 
Alexander Martinez #:

No problem! If you need help, just come back and share your attempt. Take care!

if you don't mind explaining the code that would be great... i want to take this as a learning opportunity just in case i have to use some of these func again

 
Alexander Martinez #:

No worries!

So, yeah, you need a while loop to figure out the count parameter of iHighest/iLowest.

It's pretty simple if all you care about is the last crossover.

If you want to do it for all the price history on the chart, it gets more complicated. You'll have to keep track of when price crosses over the MA and then find the difference between that crossover and the previous crossover, then call iHighest/iLowest.

Here's an example of determining the proper count parameter for iHighest/iLowest for the last crossover.



And here's the accompanying code, I figured that it's easier to code it than to bother explaining it and all the caveats. For what it's worth, there's probably better ways to go about this.

is this code for MT4 or MT5?

 
Nita Forex #:

is this code for MT4 or MT5?

MT4. It was only partial code as it was just meant to exemplify the concept. Here's the full code if you want it.

#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot ExtMA
#property indicator_label1  "My MA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//---
#include <MovingAverages.mqh>
//--- indicator buffers
double         ExtMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,ExtMA);

   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[]) {
  if (prev_calculated == 0) {
    const int period  = 14;
    
    //--- Init SimpleMA Buffer
    SimpleMAOnBuffer(rates_total, prev_calculated, 1, period, close, ExtMA);
    
    //--- Find last crossover
    int count                = 0;      //--- count param for iHighest/iLowest
    bool found               = false;  //--- Exit for-loop when found == true
    bool isCloseHigherThanMA = false;  //--- Helps to determine whether to use iHighest or iLowest
    
    for (int i = 1; i < Bars && !found;) {
      while (close[i] > ExtMA[i]) {
        count++;
        i++;
        found               = true;
        isCloseHigherThanMA = true;
      }
      
      //--- Since we only care about the last crossover, we break from the for loop if found == true
      if (found) {
        break;
      }
      
      while (close[i] < ExtMA[i]) {
        count++;
        i++;
        found = true;
      }
    }
    
    double stoploss = 0.0;
    int index       = 1;
    
    if (isCloseHigherThanMA) {
      index     = iLowest(NULL, 0, MODE_LOW, count, 1);
      stoploss  = Low[index];
    } else {
      index     = iHighest(NULL, 0, MODE_HIGH, count, 1);
      stoploss  = High[index];
    }
    
    Comment("Count: ", count,
              "\nIndex: ", index,
              "\nStoploss: ", DoubleToString(stoploss, Digits));
  }

  return rates_total;
}