Doubts about the behavior of High, Low - Need help

 

I am trying to implement a function that looks back a number of candles and then finds the local minimum price and the moment in time they happen.

I am not sure if I understood correctly the behavior of iLow.  So my iteration may be wrong.

If I call this

min_local(PERIOD_H1, local_extreme, time_extreme, true, 200);

What is meant to happen is to look the last 200 candles, ignore the first minimum and return the two minimum values and the moment in time they happen inside the two arrays.

/**
   Finds the minimum values from a sequence of candles
   local_extreme - two postion array to store the local minimum
   time_extreme - two postion array to store the moment int time where the local minimum happens
   ignoreFirst - flag to discard the first local mimimum
   candlesBack - The number of candles back to observe
 */
void min_local(ENUM_TIMEFRAMES timeframe, double &local_extreme[],datetime &time_extreme[], bool ignoreFirst, int candlesBack) {
   ArrayResize(local_extreme,2);
   ArrayInitialize(local_extreme,10000);

   ArrayResize(time_extreme,2);
   ArrayInitialize(time_extreme,__DATETIME__);

   local_extreme[0] = 100000;
   int i = 0;
   double smallestA_value = 0;
   double smallestB_value = 0;
   double smallestC_value = 0;
   datetime timeA = __DATETIME__;
   datetime timeB = __DATETIME__;
   datetime timeC = __DATETIME__;
   for(i=0;i<candlesBack;i++) {
      int value_index = iLow(Symbol(),timeframe,i);
      if(Low[value_index] < smallestA_value){
         smallestB_value = smallestA_value;
         smallestA_value = Low[value_index];
         timeA = Time[value_index];
      } else if (Low[value_index] < smallestB_value) {
         smallestB_value = Low[value_index];
         timeB = Time[value_index];
      } else if (Low[value_index] < smallestC_value) {
         smallestC_value = Low[value_index];
         timeC = Time[value_index];
      }
   }
   if(ignoreFirst){
      local_extreme[0] = smallestB_value;
      local_extreme[1] = smallestC_value;
      time_extreme[0] = timeB;
      time_extreme[1] = timeC;   
   }else{
      local_extreme[0] = smallestA_value;
      local_extreme[1] = smallestB_value;
      time_extreme[0] = timeA;
      time_extreme[1] = timeB;   
   }
}
 
  1. int value_index = iLow(Symbol(),timeframe,i);
    Unless the chart is that specific pair/TF, you must handle 4066/4073 errors. See Download history in MQL4 EA - MQL4 and MetaTrader 4 - MQL4 programming forum
  2.    ArrayInitialize(local_extreme,10000);
       local_extreme[0] = 100000;
    Redundant assignment
  3.    ArrayInitialize(time_extreme,__DATETIME__);
    
    Why not just use zero?
  4.       int value_index = iLow(Symbol(),timeframe,i);
          if(Low[value_index] < smallestA_value){
    iLow returns the low price for that timeframe/index, not an Int, not an index. Then you look at the current chart's low. You are mixing apples and oranges.
 
whroeder1:
Unless the chart is that specific pair/TF, you must handle 4066/4073 errors. See Download history in MQL4 EA - MQL4 and MetaTrader 4 - MQL4 programming forum

To handle error is never a bad practice :)

Sorry if I failed to mention some initial premises.  Thanks you for alerting me.

1 - The indicator where this function is used is doing the calculations over the same pair of the char he is attached to.

2 - The indicator does the calculations of 4 time frames, H4, D1, WN and MN

The code corrected following your suggestions.  Yet it seems to have a problem with iLow usage, so I changed to iLowest and the implementation changed a bit.

#define SYMBOL string
#define THIS_SYMBOL ""
#define HR2400 PERIOD_D1 * 60    // 86400 = 24 * 3600

/**
   Finds the minimum values from a sequence of candles
   local_extreme - two postion array to store the local minimum
   time_extreme - two postion array to store the moment int time where the local minimum happens
   ignoreFirst - flag to discard the first local mimimum
   candlesBack - The number of candles back to observe
 */
void min_local(ENUM_TIMEFRAMES timeframe, double &local_extreme[],datetime &time_extreme[], bool ignoreFirst, int candlesBack)  /**<[in] Direction of the search. */{
   ArrayResize(local_extreme,2);
   ArrayInitialize(local_extreme,10000);

   ArrayResize(time_extreme,2);
   ArrayInitialize(time_extreme,__DATETIME__);

   local_extreme[0] = 100000;
   int i = 0;
   int error_code = 0;
   
   double smallestA_value = 0;
   double smallestB_value = 0;
   double smallestC_value = 0;
   datetime timeA = __DATETIME__;
   datetime timeB = __DATETIME__;
   datetime timeC = __DATETIME__;
   
   int value_index_A = iLowest(NULL,timeframe,MODE_LOW,candlesBack,0); 
   if(0 == value_index_A) error_code = GetLastError();
   if(error_code == 0) download_history(Symbol(),timeframe);
   
   error_code = 0;
   int value_index_B = iLowest(NULL,timeframe,MODE_LOW,Bars - value_index_A,0);
   if(0 == value_index_B) error_code = GetLastError();
   if(error_code == 0) download_history(Symbol(),timeframe);

   error_code = 0;
   int value_index_C = iLowest(NULL,timeframe,MODE_LOW,Bars - value_index_B,0);
   if(0 == value_index_C) error_code = GetLastError();
   if(error_code == 0) download_history(Symbol(),timeframe);
   
   if(ignoreFirst){
      local_extreme[0] = Low[value_index_B];
      local_extreme[1] = Low[value_index_C];
      time_extreme[0] = Time[value_index_B];
      time_extreme[1] = Time[value_index_C];
   }else{
      local_extreme[0] = Low[value_index_A];
      local_extreme[1] = Low[value_index_B];
      time_extreme[0] = Time[value_index_A];
      time_extreme[1] = Time[value_index_B];
   }
}

bool  download_history(
      SYMBOL            symbol=THIS_SYMBOL,     ///< The symbol required.
      ENUM_TIMEFRAMES   period=PERIOD_CURRENT   /**< The standard timeframe.*/){
   if(symbol == THIS_SYMBOL)     symbol = _Symbol;
   if(period == PERIOD_CURRENT)  period = _Period;
   datetime today = DateOfDay();
   ResetLastError();
   datetime other = iTime(symbol, period, 0);
   if(_LastError == 0  && today == DateOfDay(other)) return true;   
   if(_LastError != ERR_HISTORY_WILL_UPDATED && _LastError != ERR_NO_HISTORY_DATA) Print(StringFormat("iTime(%s,%i) Failed: %i", symbol, period,_LastError));
   return false;
}

datetime DateOfDay(datetime when=0){
   if(when == 0) when = TimeCurrent();
   return(when - TimeOfDay(when));
}
                                          
int TimeOfDay(datetime when=0){
   if(when == 0)  when = TimeCurrent();
   return( when % HR2400 );
}