Problem Description
Solution
To find the highest and lowest prices within a specific range of bars in MQL4, you use the iHighest() and iLowest() functions. These functions return the index (shift) of the bar where the extreme value occurred. You then use that index to retrieve the actual price from the High[] and Low[] series arrays.
Here is a complete, runnable script that calculates and prints the highest and lowest prices for the last 50 closed bars.
MQL4 Code Example
//+------------------------------------------------------------------+
//| FindHighLow_Last50.mq4|
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#property script_show_inputs
//--- Input parameters
input int InpBarsToScan = 50; // Number of bars to check
input int InpStartBar = 1; // Start index (1 = last closed bar, 0 = current forming bar)
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
// 1. Find the index (shift) of the highest High
// iHighest(Symbol, Timeframe, Type, Count, StartIndex)
int highestIndex = iHighest(Symbol(), Period(), MODE_HIGH, InpBarsToScan, InpStartBar);
// 2. Find the index (shift) of the lowest Low
// iLowest(Symbol, Timeframe, Type, Count, StartIndex)
int lowestIndex = iLowest(Symbol(), Period(), MODE_LOW, InpBarsToScan, InpStartBar);
// 3. Error checking
if(highestIndex == -1 || lowestIndex == -1)
{
Print("Error finding High/Low. Error code: ", GetLastError());
return;
}
// 4. Retrieve the actual price values using the found indices
double highestPrice = High[highestIndex];
double lowestPrice = Low[lowestIndex];
// 5. Output the results to the Experts log
string output = StringFormat("Range: Bars %d to %d on %s %d",
InpStartBar,
InpStartBar + InpBarsToScan - 1,
Symbol(),
Period());
Print("--------------------------------------------------");
Print(output);
Print("Highest Price: ", DoubleToString(highestPrice, Digits), " (Bar Index: ", highestIndex, ")");
Print("Lowest Price: ", DoubleToString(lowestPrice, Digits), " (Bar Index: ", lowestIndex, ")");
Print("--------------------------------------------------");
}
//+------------------------------------------------------------------+
Explanation of Functions
-
iHighest(...):Symbol(): The current chart symbol.Period(): The current chart timeframe.MODE_HIGH: Specifies that we are looking for the highest value among the High prices.InpBarsToScan: The number of bars to search (50).InpStartBar: The starting point. We usually use1to check the last 50 closed bars. If you use0, it includes the current forming bar, which changes with every tick.
-
iLowest(...):- Works exactly like
iHighest, but usesMODE_LOWto search the Low prices.
- Works exactly like
-
High[]andLow[]:- These are predefined timeseries arrays.
High[highestIndex]returns the actual price value at the specific bar index found by the function.
- These are predefined timeseries arrays.
Q&A
Q: Why do we use start = 1 instead of 0?
A: In trading strategies, it is standard practice to analyze "closed" bars (indices 1 and greater). Bar 0 is the current forming bar; its High and Low can change until the candle closes. Using index 1 ensures the data is fixed and will not "repaint."
Q: Can I use this for Open or Close prices?
A: Yes. To find the highest Close price, change MODE_HIGH to MODE_CLOSE inside iHighest, and retrieve the value using Close[highestIndex].
Q: What happens if the chart doesn't have 50 bars of history?
A: The function will search whatever is available up to the maximum history. However, it is good practice to check Bars (a predefined variable holding the total number of bars) to ensure Bars > 50 before running the logic to avoid array out-of-range errors.