If you are building or running high-frequency scalping EAs in MetaTrader 5, you have likely run into the dreaded "Array out of range" error in your Journal tab. This is a fatal execution error that instantly halts your Expert Advisor—which is the absolute last thing you want to happen during a volatile liquidity spike.
Unlike MQL4, MQL5 is highly asynchronous. When your EA requests historical data (like indicator buffers or price action arrays), the terminal doesn't guarantee that the data is immediately available in memory. If your EA tries to access an index before verifying the array is populated, it crashes.
Here is a breakdown of why this happens and the exact architectural pattern you should use to fix it.
The Root Cause
In a scalping EA, speed is everything. We often rely on CopyBuffer, CopyRates, or CopyTicks inside the OnTick() function to make split-second execution decisions.
The error triggers when you do something like this:
Code: Select all
// ❌ THE FLAWED APPROACH
double rsi_buffer[];
CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer);
// If the terminal hasn't loaded the data yet, CopyBuffer returns -1.
// The array is empty. Accessing index [0] crashes the EA.
double current_rsi = rsi_buffer[0];To build an enterprise-grade EA that can run for months without crashing, you must treat every data request as a potential point of failure.
You need to implement a three-step validation check:
Verify the exact number of elements returned by the Copy... function.
Handle terminal data synchronization delays gracefully.
Explicitly verify ArraySize() before mapping data to your execution logic.
Here is the robust implementation:
Code: Select all
// ✅ THE ROBUST APPROACH
void OnTick()
{
// 1. Define dynamic array for the indicator or price data
double rsi_buffer[];
// 2. Set the array as series (index 0 = current candle)
ArraySetAsSeries(rsi_buffer, true);
// 3. Attempt to copy the data and store the result
int copied = CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer);
// 4. Validate the response BEFORE accessing the array
if(copied <= 0)
{
// The terminal is still syncing, or there is a history error.
// Do NOT proceed. Exit the OnTick and wait for the next incoming tick.
Print("Data not ready or CopyBuffer error: ", GetLastError());
return;
}
// 5. Final safety check on array bounds
if(ArraySize(rsi_buffer) < 3)
{
Print("Insufficient array size for strategy logic.");
return;
}
// 6. Safe to execute your scalping logic
double current_rsi = rsi_buffer[0];
double previous_rsi = rsi_buffer[1];
// ... entry criteria logic ...
}Never assume the terminal is ready: Always capture the integer return value of CopyBuffer or CopyRates. If it is less than or equal to zero, simply return; out of the tick.
Watch your indexing: Remember that MQL5 arrays are not time-series by default. Always use ArraySetAsSeries(array, true) if you want index [0] to represent the current active candle.
Initialize properly: Make sure your indicator handles (e.g., rsi_handle) are successfully created in OnInit(), not re-created on every tick.
Have you run into any specific edge cases with array indexing during high-impact news events? Drop your snippets below and we can optimize them.
Take a care,
bye bye.