Back to MetaTrader 5 MQL5 for CFD Traders
Part 2

Loops: Scanning Bars Efficiently

for and while, plus the two guards that keep a loop from hanging the terminal.

Beginner8 min readBeginner → AdvancedLesson 07 / 17
Try it in MetaEditor
Scan recent bars for the range and the streak

Save as MQL5/Scripts/Lesson7Loops.mq5. It copies recent bars, finds the highest high and lowest low, then counts a streak with a while loop.

//+------------------------------------------------------------------+
//| Lesson 7 - Loops: range scan and streak count                    |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version   "1.00"

void OnStart()
{
   int lookback = 20;

   MqlRates rates[];
   ArraySetAsSeries(rates, true);          // index 0 = newest bar

   int copied = CopyRates(_Symbol, _Period, 0, lookback + 1, rates);
   if(copied < lookback + 1)
   {
      Print("CopyRates returned ", copied, " bars - expected ", lookback + 1,
            ". Error: ", GetLastError());
      return;
   }

   // Start at 1: bar 0 is still forming, so it is not a completed range.
   double highest = rates[1].high;
   double lowest  = rates[1].low;
   int    highBar = 1;
   int    lowBar  = 1;

   for(int i = 2; i <= lookback && !IsStopped(); i++)
   {
      if(rates[i].high > highest) { highest = rates[i].high; highBar = i; }
      if(rates[i].low  < lowest)  { lowest  = rates[i].low;  lowBar  = i; }
   }

   Print("Range over last ", lookback, " completed bars on ", _Symbol);
   Print("Highest high: ", DoubleToString(highest, _Digits), "  (", highBar, " bars ago)");
   Print("Lowest low:   ", DoubleToString(lowest, _Digits), "  (", lowBar, " bars ago)");
   Print("Range size:   ", DoubleToString((highest - lowest) / _Point, 1), " points");

   // while loop: how many consecutive completed closes sit above the midpoint?
   double mid    = (highest + lowest) / 2.0;
   int    streak = 0;
   int    i      = 1;

   while(i <= lookback && rates[i].close > mid)
   {
      streak++;
      i++;
   }

   Print("Consecutive closes above midpoint: ", streak, " of ", lookback);
}
To run it
  1. 1. Open MetaEditor from MT5 (press F4), and pick the folder this program belongs in — Experts, Indicators, or Scripts.
  2. 2. Create a new file, paste this over it, then press F7 to compile. Fix anything the Errors tab reports.
  3. 3. Back in MT5, drag it onto a chart — or open the Strategy Tester if it is an Expert Advisor.

for is your default

When you know how many times to iterate — scan the last 20 bars, walk 50 symbols — use for. The pattern is always the same: initialise a counter, test it, increment.

while when the count is unknown

Use while when you loop until a condition changes: walk back until price closes below a level, retry an operation until it succeeds or you hit a cap. Always guarantee the condition can become false, or you have written an infinite loop that freezes the chart.

Two guards you should never skip

  • !IsStopped() — lets the terminal abort your loop when the user removes the program or shuts down. Without it, a long loop can make MT5 unresponsive.
  • A bounds check — never index past rates_total or the size of the array you copied into. Return early if the copy returned fewer bars than you asked for.

Series versus oldest-first, again

When you call CopyRates into your own array you choose the order with ArraySetAsSeries(arr, true). With it set, index 0 is the newest bar, which reads naturally for "how many bars ago" logic. This lesson uses series order for the scan — a different convention from Lesson 4, deliberately, so you get used to both and learn to check which one you are in.

Off-by-one

The most common bug in this shape of code is scanning one bar too few or too many. If you want the highest high of the last 20 completed bars, exclude bar 0 — it is still forming.

What you just did

Lesson 07 of 17 in MetaTrader 5 MQL5 for CFD Traders. When you have run the examples or read the section, tick it off and move to the next lesson.