MQL5 iMA Explained: How to Use Moving Averages and CopyBuffer Correctly

目次

1. What Is iMA?

1.1 The Role and Basic Concept of iMA

iMA (Moving Average) is a standard MQL5 function used to obtain a moving average (MA: an indicator that smooths the average price over a fixed period).

A moving average is one of the most basic technical indicators used to determine market direction (trend), and it is widely used for the following purposes.

  • Trend identification (uptrend / downtrend)
  • Golden cross and dead cross detection
  • Support for pullback and rebound analysis
  • Filter conditions (enter trades only in the trend direction)

In MQL5, you do not need to implement the moving average calculation yourself.
By using the iMA function, you can obtain an internally calculated moving average indicator.

However, one important point is that iMA in MQL5 is not a function that directly returns a value.

In MQL4, calling iMA() returned the value immediately, but in MQL5 it was changed to an indicator handle model.

1.2 How iMA Works in MQL5 (Handle-Based Model)

In MQL5, calling iMA follows this process.

  1. Create an indicator handle (identifier) with iMA
  2. Use CopyBuffer to retrieve the actual moving average values

In other words, iMA returns not the moving average value itself, but a reference ID (handle) for the moving average indicator.

If you do not understand this structure, misunderstandings like the following will occur.

❌ Common Misunderstandings

  • Assuming iMA returns the value directly
  • Creating iMA on every tick inside OnTick
  • Writing comparison logic without using CopyBuffer

All of these are typical beginner mistakes.

1.3 Types of Moving Averages (ENUM_MA_METHOD)

With iMA, you can specify multiple moving average types.

TypeDescription
MODE_SMASimple Moving Average
MODE_EMAExponential Moving Average
MODE_SMMASmoothed Moving Average
MODE_LWMALinear Weighted Moving Average

EMA is commonly used in trend-following strategies, but the appropriate choice depends on the strategy.

1.4 When You Should Use iMA

Use iMA in cases like the following.

  • When you want an EA to determine the trend direction
  • When you want to use whether the price is above or below a moving average as a condition
  • When you want to perform multi-timeframe analysis (for example, referencing an H1 MA on an M5 chart)

Especially in EA development, this is a very frequently used function as a trend filter.

1.5 Common Stumbling Points

⚠ Not Understanding the Difference from MQL4

In MQL5, you cannot retrieve the value directly.
You must always follow the flow: handle → CopyBuffer.

⚠ Creating the Indicator in the Wrong Place

  • Creating iMA on every tick in OnTick increases the processing load
  • The correct approach is to create it in OnInit

⚠ Insufficient Data

If there are not enough bars, CopyBuffer may not work correctly.
This is especially important immediately after starting the tester.

To use iMA correctly, you first need to accurately understand its syntax and the meaning of its arguments.

2. Basic iMA Syntax

2.1 iMA Function Definition

The basic iMA syntax in MQL5 is as follows.

int iMA(
   string              symbol,         // Symbol
   ENUM_TIMEFRAMES     period,         // Timeframe
   int                 ma_period,      // Moving average period
   int                 ma_shift,       // Display shift
   ENUM_MA_METHOD      ma_method,      // MA type
   ENUM_APPLIED_PRICE  applied_price   // Applied price
);

This function returns the handle (identifier) of the moving average indicator.

If the return value is INVALID_HANDLE, indicator creation has failed.

2.2 Detailed Explanation of Each Argument

① symbol (symbol)

  • Using _Symbol is common
  • Example: you can also explicitly specify "EURUSD"
_Symbol

⚠ In multi-currency EAs, explicit symbol specification may be required.

② period (timeframe)

Specifies the timeframe.

Examples:

  • PERIOD_M1
  • PERIOD_M5
  • PERIOD_H1
  • PERIOD_D1
  • PERIOD_CURRENT (the current chart timeframe)
PERIOD_CURRENT

⚠ In multi-timeframe analysis, getting this wrong will break the logic.

③ ma_period (moving average period)

This is the calculation period for the moving average.

Examples:

  • 20 (short-term)
  • 50 (medium-term)
  • 200 (long-term)
20

⚠ It cannot be calculated if there are not enough bars.
Be especially careful immediately after starting the tester.

④ ma_shift (display shift)

This is the value used to shift the moving average to the right.

Usually, 0 is used.

0

⚠ This is not a calculation shift, but a display position shift.
For logic evaluation, using 0 is generally fine.

⑤ ma_method (moving average type)

Specify an enumeration value (ENUM_MA_METHOD).

MODE_EMA

Main types:

  • MODE_SMA (Simple Moving Average)
  • MODE_EMA (Exponential)
  • MODE_SMMA (Smoothed)
  • MODE_LWMA (Weighted)

You need to choose appropriately depending on the strategy.

⑥ applied_price (applied price)

Specifies which price to use as the basis for calculation.

Main options:

  • PRICE_CLOSE (close price)
  • PRICE_OPEN (open price)
  • PRICE_HIGH (high price)
  • PRICE_LOW (low price)
  • PRICE_MEDIAN (median price)
  • PRICE_TYPICAL (typical price)

Usually, PRICE_CLOSE is used.

PRICE_CLOSE

2.3 Minimal iMA Example

int maHandle;

int OnInit()
{
   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);

   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

The important points here are:

  • Create it in OnInit
  • Always include an INVALID_HANDLE check

2.4 Common Mistakes

❌ Calling iMA Inside OnTick

Creating it on every tick causes unnecessary memory consumption and performance degradation.

❌ Forgetting to Release the Handle

If you do not call IndicatorRelease() when the EA ends, memory may remain allocated.

❌ Using the Wrong ENUM Type

If you force it with int, the code may still compile, but readability becomes worse.

Even if you understand the iMA syntax, you still cannot retrieve the moving average value yet.

3. Correct Usage of iMA (Handle Acquisition and Management)

3.1 The Correct Timing for Handle Creation

In MQL5, iMA is not a function that retrieves a value, but a function that creates an indicator handle.
Because of this, if you create it at the wrong time, you may run into performance and stability problems.

The correct basic structure is as follows.

int maHandle;

int OnInit()
{
   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);

   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed");
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

Why Create It in OnInit?

  • An indicator can be reused once it has been created
  • Creating it on every tick is unnecessary processing
  • It has a major impact on tester speed

❌ Common Mistake

void OnTick()
{
   int handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
}

This means a new indicator is being created on every tick.
It makes backtesting slower.

3.2 Checking Handle Validity

Immediately after creating the handle, always check for INVALID_HANDLE.

if(maHandle == INVALID_HANDLE)
{
   Print("Error creating iMA handle");
   return(INIT_FAILED);
}

Main reasons for failure:

  • Invalid timeframe specification
  • The symbol is unavailable
  • Insufficient historical data (environment-dependent)

3.3 Releasing the Indicator (Important)

In MQL5, it is safer by design to explicitly release indicators you create.

void OnDeinit(const int reason)
{
   if(maHandle != INVALID_HANDLE)
      IndicatorRelease(maHandle);
}

What Happens If You Do Not Release It?

  • Memory usage may increase
  • It may cause instability in long-running EAs

Especially in VPS operation, memory management should not be ignored.

3.4 Notes for Multi-Timeframe Usage

Example: when obtaining an H1 moving average on an M5 chart

maHandle = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_EMA, PRICE_CLOSE);

Points to note:

  • The higher timeframe data must be loaded
  • At the first execution, CopyBuffer may fail due to insufficient data

Countermeasure:

if(Bars(_Symbol, PERIOD_H1) < 100)
{
   Print("Not enough bars for H1");
   return;
}

3.5 Design Points from a Practical Operation Perspective

✔ Manage Handles as Global Variables

→ If it goes out of scope, you will need to create it again

✔ Use Clear Names When Using Multiple MAs

int maFastHandle;
int maSlowHandle;

✔ Consider Reinitialization Behavior

When parameters are changed, OnDeinit → OnInit is executed again.
If handle management is not appropriate, it can cause abnormal behavior.

4. How to Retrieve Moving Average Values with CopyBuffer

4.1 What Is CopyBuffer?

CopyBuffer() is a function used to retrieve actual calculated values from an indicator handle.

iMA only returns a handle, and the moving average value itself is retrieved with CopyBuffer.

The basic syntax is as follows.

int CopyBuffer(
   int      indicator_handle,   // Indicator handle
   int      buffer_num,         // Buffer number
   int      start_pos,          // Start position
   int      count,              // Number of elements to retrieve
   double   buffer[]            // Destination array
);

The return value is the number of elements successfully copied.
If it is 0 or less, treat it as a failure.

4.2 Basic Example (Retrieving the Latest Values)

double maBuffer[];

ArraySetAsSeries(maBuffer, true);

if(CopyBuffer(maHandle, 0, 0, 3, maBuffer) <= 0)
{
   Print("CopyBuffer failed");
   return;
}

Meaning of Each Argument

  • maHandle: the handle obtained with iMA
  • 0: buffer number (for iMA, this is basically 0)
  • 0: retrieve starting from the current bar
  • 3: retrieve 3 values
  • maBuffer: the array used to store the retrieved results

4.3 The Relationship Between start_pos and Indexes (Important)

start_pos = 0 points to the current unconfirmed bar.

Meaning of the indexes:

  • maBuffer[0] → current bar (unconfirmed)
  • maBuffer[1] → 1 bar ago (confirmed)
  • maBuffer[2] → 2 bars ago

Practical Usage Notes

The unconfirmed bar (index 0) changes as the price moves.

In EA logic, it is common to use:

double currentMA = maBuffer[1]; // Use the confirmed bar

If you use the unconfirmed bar, backtest and live results may not match.

4.4 The Meaning of ArraySetAsSeries

ArraySetAsSeries(maBuffer, true);

When this is specified:

  • Index 0 becomes the latest data
  • Larger indexes become older data

That is how the array is handled.

If you do not specify it, the order is reversed, which makes the logic confusing.

❌ Common Mistakes

  • Forgetting ArraySetAsSeries
  • Misunderstanding the index direction
  • Referencing an index larger than the number of retrieved values (array out of range)

4.5 What to Check Before Retrieving Data

① Whether There Are Enough Bars

if(Bars(_Symbol, PERIOD_CURRENT) < 50)
{
   Print("Not enough bars");
   return;
}

If you use an MA period of 20, you need at least 20 bars.

② Check the Return Value of CopyBuffer

int copied = CopyBuffer(maHandle, 0, 0, 3, maBuffer);

if(copied <= 0)
{
   Print("CopyBuffer failed. Error: ", GetLastError());
   return;
}

The cause of the error may depend on the environment.

4.6 Performance Design Notes

  • Do not retrieve a large number of values on every tick
  • Retrieve only the minimum number of values you need
  • Do not call CopyBuffer repeatedly inside a loop

Example:

// Bad example
for(int i=0; i<100; i++)
{
   CopyBuffer(maHandle, 0, i, 1, maBuffer);
}

This is very inefficient.

4.7 Minimal Working Example Summary

double maBuffer[];

ArraySetAsSeries(maBuffer, true);

int copied = CopyBuffer(maHandle, 0, 0, 2, maBuffer);

if(copied > 0)
{
   double prevMA = maBuffer[1]; // Confirmed bar
}

This structure is the basic pattern for retrieving moving averages in MQL5.

5. Common Errors and Solutions (Typical Problems with iMA / CopyBuffer)

5.1 Basic Strategy for Isolating Errors

Many issues related to iMA are not caused by logical mistakes, but by one of the following factors.

  • Handle creation failed (iMA side)
  • CopyBuffer failed (retrieval side)
  • Incorrect array handling (very common)
  • Insufficient historical data (environment dependent)
  • Using an unconfirmed bar, causing unstable logic (difference between backtest and live trading)

First, always insert logging to determine exactly where the failure occurs.

int copied = CopyBuffer(maHandle, 0, 0, 3, maBuffer);
if(copied <= 0)
{
   int err = GetLastError();
   Print("CopyBuffer failed. err=", err);
}

5.2 array out of range (Array Out-of-Bounds Access)

Symptoms

  • The program stops with a runtime error
  • array out of range appears in the log
  • Often occurs during conditional evaluation

Main Causes

  • Referencing an index larger than the number of elements retrieved by CopyBuffer
  • The array size was not properly allocated (dynamic array initialization problem)
  • Misunderstanding the index direction due to missing ArraySetAsSeries()

Typical Example (Failure)

double maBuffer[];
ArraySetAsSeries(maBuffer, true);

CopyBuffer(maHandle, 0, 0, 2, maBuffer);
// Only two values retrieved but referencing maBuffer[2]
double x = maBuffer[2];

Solution

  • Always retrieve at least the maximum referenced index + 1 elements
  • Check the return value of CopyBuffer before referencing the array
double maBuffer[];
ArraySetAsSeries(maBuffer, true);

int need = 3;
int copied = CopyBuffer(maHandle, 0, 0, need, maBuffer);
if(copied < need)
{
   Print("Not enough data copied: ", copied);
   return;
}

double prevMA = maBuffer[1];
double prev2MA = maBuffer[2];

5.3 INVALID_HANDLE (Handle Creation Failure)

Symptoms

  • Log messages such as iMA handle creation failed
  • CopyBuffer always fails
  • The EA fails initialization (INIT_FAILED)

Main Causes (May Vary by Environment)

  • The symbol is unavailable (no quote or incorrect specification)
  • Incorrect period specification (special environments such as custom timeframes)
  • History data is not yet available at startup
  • Insufficient data in the tester environment

Solution

  • Always check for INVALID_HANDLE immediately after creating the handle
  • Check the minimum number of bars with Bars() (especially for higher timeframes)
int OnInit()
{
   if(Bars(_Symbol, PERIOD_CURRENT) < 100)
   {
      Print("Not enough bars yet");
      return(INIT_FAILED);
   }

   maHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
   if(maHandle == INVALID_HANDLE)
   {
      Print("iMA handle creation failed. err=", GetLastError());
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

5.4 CopyBuffer Failed (Cannot Retrieve Values / Returns 0 or Less)

Symptoms

  • The return value of CopyBuffer is 0 or -1
  • The buffer remains empty or values never update

Main Causes

  • There is not enough data yet to calculate the indicator (most common)
  • The start_pos or count values are excessive
  • The handle is invalid (still INVALID_HANDLE)
  • The logic relies on an unconfirmed bar

Solution

  • Retrieve the minimum required number of values (often 2–3 is enough)
  • If there are not enough bars, design the EA to wait
  • Always use confirmed bars ([1])
double maBuffer[];
ArraySetAsSeries(maBuffer, true);

if(Bars(_Symbol, PERIOD_CURRENT) < 30) return;

int copied = CopyBuffer(maHandle, 0, 0, 2, maBuffer);
if(copied < 2)
{
   Print("CopyBuffer not ready. copied=", copied, " err=", GetLastError());
   return;
}

double maConfirmed = maBuffer[1];

5.5 The Value Becomes 0 or an Impossible Value

Symptoms

  • The MA remains near 0
  • The value is far from the price
  • Strange behavior only immediately after the tester starts

Main Causes

  • Data is not fully loaded yet (immediately after start)
  • Misunderstanding the direction of series arrays (forgot ArraySetAsSeries)
  • Referencing the current unconfirmed bar

Solution

  • Do not perform calculations until enough bars have accumulated
  • Use maBuffer[1] (confirmed bar)

5.6 Dangerous Pitfalls That Cause Differences in Real Operation

⚠ Using the Unconfirmed Bar (index 0)

This is a major cause of discrepancies between backtest and live trading.
EA logic should generally rely on confirmed bars.

⚠ Retrieving Large Amounts of Data with CopyBuffer on Every Tick

In VPS operation or multi-symbol EAs, this can cause heavy load.
Design your system to retrieve only the minimum required number of values.

6. Practical Considerations (Performance and Safety Design)

6.1 Avoid Unnecessary Processing on Every Tick

The most common design mistake in EAs using iMA and CopyBuffer is repeating unnecessary calculations on every tick.

❌ Typical Inefficient Example

void OnTick()
{
   double maBuffer[];
   ArraySetAsSeries(maBuffer, true);

   CopyBuffer(maHandle, 0, 0, 100, maBuffer);
}

Problems:

  • Retrieving 100 values on every tick
  • Unnecessary memory allocation occurs
  • Load increases dramatically in multi-symbol EAs

✔ Improvement Strategy

  • Retrieve only the minimum required number of values (usually 2–3)
  • Update only when a new bar is confirmed

6.2 Detect New Bars (Practical Design)

Many moving-average-based strategies rely on confirmed bars.
Therefore, processing only when a new bar appears is often sufficient.

datetime lastBarTime = 0;

void OnTick()
{
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(currentBarTime == lastBarTime)
      return;

   lastBarTime = currentBarTime;

   // Write MA retrieval logic here
}

This approach:

  • Prevents unnecessary CopyBuffer calls per tick
  • Improves tester speed
  • Stabilizes the logic

6.3 Notes for Multi-Symbol EAs

When using iMA across multiple symbols, keep the following in mind.

✔ Manage Handles for Each Symbol

int maHandle_EURUSD;
int maHandle_USDJPY;

✔ Each Symbol Has Its Own Bar Update Timing

The iTime() check must also be performed per symbol.

⚠ Common Mistakes

  • Reusing the same array for different symbols
  • Using _Symbol even though the symbol being processed is different

6.4 Do Not Forget IndicatorRelease

Each time the EA stops or reinitializes, handles are recreated.
If you do not release them, long-term operation may become unstable.

void OnDeinit(const int reason)
{
   if(maHandle != INVALID_HANDLE)
      IndicatorRelease(maHandle);
}

This is particularly important in continuous VPS operation.

7. Example Integration into an EA (Golden Cross Detection and Pitfalls)

7.1 Basic Concept of Golden Cross Detection

A typical example of using moving averages in an EA is detecting a crossover between a short-term MA and a long-term MA.

  • The short-term MA crosses the long-term MA from below → Golden Cross (buy signal)
  • The short-term MA crosses the long-term MA from above → Dead Cross (sell signal)

The key point is not the current position, but detecting the crossover by comparing it with the previous confirmed bar.

7.2 Create Two MA Handles (OnInit)

int maFastHandle;
int maSlowHandle;

int OnInit()
{
   maFastHandle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_EMA, PRICE_CLOSE);
   if(maFastHandle == INVALID_HANDLE)
   {
      Print("Fast MA handle failed. err=", GetLastError());
      return(INIT_FAILED);
   }

   maSlowHandle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE);
   if(maSlowHandle == INVALID_HANDLE)
   {
      Print("Slow MA handle failed. err=", GetLastError());
      return(INIT_FAILED);
   }

   return(INIT_SUCCEEDED);
}

7.3 Retrieve Two Confirmed Bars Using CopyBuffer (Only on a New Bar)

To detect a crossover, at least two confirmed bars are required.
(Because you compare the previous bar and the bar before it.)

bool GetMAValues(int handle, double &v1, double &v2)
{
   double buf[];
   ArraySetAsSeries(buf, true);

   int copied = CopyBuffer(handle, 0, 1, 2, buf); // start_pos=1 → confirmed bars
   if(copied < 2)
      return false;

   v1 = buf[0]; // previous bar (confirmed)
   v2 = buf[1]; // two bars ago
   return true;
}

Important points here:

  • start_pos = 1 (avoid unconfirmed bars)
  • count = 2 (minimum required for cross detection)

7.4 Cross Detection Logic (Confirmed Bar Based)

void OnTick()
{
   static datetime lastBarTime = 0;
   datetime t = iTime(_Symbol, PERIOD_CURRENT, 0);
   if(t == lastBarTime) return;
   lastBarTime = t;

   double fast1, fast2, slow1, slow2;

   if(!GetMAValues(maFastHandle, fast1, fast2))
   {
      Print("Fast MA not ready");
      return;
   }
   if(!GetMAValues(maSlowHandle, slow1, slow2))
   {
      Print("Slow MA not ready");
      return;
   }

   bool goldenCross = (fast2 <= slow2) && (fast1 > slow1);
   bool deadCross   = (fast2 >= slow2) && (fast1 < slow1);

   if(goldenCross)
      Print("Golden Cross detected (confirmed bar)");
   if(deadCross)
      Print("Dead Cross detected (confirmed bar)");
}

This logic detects the exact moment of the crossover using confirmed bars.
It is suitable for real-world use because it minimizes differences between backtests and live trading.

7.5 Common Pitfalls (Where Many People Get Stuck)

❌ Mistaking Position Comparison for a Cross

Example: Buy if the short MA is above, sell if it is below.

Problem:

  • It repeatedly signals even when the MA is already above
  • This can cause continuous entries

A crossover must be detected using a change from the previous state to the current state.

❌ Detecting Crossovers on Unconfirmed Bars (index 0)

If you use unconfirmed bars, the following issues may occur.

  • The crossover condition fluctuates on every tick
  • False detections like “cross → revert → cross again”
  • Results differ significantly between backtest and live trading

The solution is to strictly use start_pos = 1.

❌ Incorrect CopyBuffer Start Position

Example: if you write CopyBuffer(handle, 0, 0, 2, buf), then

  • buf[0] becomes the unconfirmed bar
  • buf[1] becomes the confirmed bar

This can easily confuse the comparison logic.

For crossover detection, it is safest to use only confirmed bars.

7.6 Additional Safety Measures for Practical Trading

A simple crossover strategy alone often produces too much noise.
In real trading systems, filters are typically combined.

Examples:

  • Do not trade when spreads are wide
  • Disable re-entry for a certain time period
  • Trade only when the direction matches the higher timeframe MA

8. Related Topics (Planned Future Extensions)

This article explained the basics of the iMA function in MQL5, including syntax, retrieving values using CopyBuffer, and integrating it into an EA.

However, to use iMA effectively at a professional level, understanding the following related topics is essential.

8.1 Complete Understanding of CopyBuffer

iMA only returns a handle, and actual value retrieval depends entirely on CopyBuffer.

Topics planned for future articles:

  • How buffer numbers work
  • The exact meaning of start_pos and count
  • Internal behavior of ArraySetAsSeries
  • Efficient data retrieval design without performance loss
  • Handling indicators with multiple buffers

Even if you understand iMA, incorrect CopyBuffer usage will almost certainly create bugs.

8.2 Complete Countermeasures for array out of range

This is the most common runtime error encountered by MQL5 beginners.

Planned future topics:

  • Detailed explanation of the error mechanism
  • The relationship between CopyBuffer and array size
  • How to detect mistakes in series array direction
  • Reusable template code to prevent recurrence
  • Defensive design techniques in production EAs

Systematically handling these errors greatly improves EA stability.

8.3 Differences from iCustom

iMA is a standard indicator, but when dealing with custom indicators, you must use iCustom.

Planned explanation topics:

  • Basic syntax of iCustom
  • How to pass parameters
  • How to identify buffer numbers
  • Managing multi-buffer indicators
  • Common design for handle management

After understanding iMA, moving on to iCustom is the natural next step.

8.4 EA Design Philosophy Using Moving Averages

Simple crossover strategies tend to generate too much noise and rarely work well in real trading without modification.

Topics to be covered in the future:

  • Filter design (alignment with higher timeframe trend)
  • Entry frequency control
  • Integration with automatic lot calculation
  • Integration with maximum drawdown control
  • Architecture designed for forward testing

This site focuses not just on code examples but on EA structures that emphasize safe design and reproducibility.

8.5 Position of This Article

This article represents the first foundational step for retrieving indicator data in MQL5.

If this concept is not properly understood:

  • Backtests and live trading results will not match
  • Execution stops due to CopyBuffer errors
  • Runtime errors occur due to array issues
  • Performance may degrade significantly

These types of problems may occur.

Although iMA appears simple, it requires an understanding of the MQL5 handle structure, buffer structure, and series arrays.

With this foundation in place, the next step is a deeper exploration of CopyBuffer design.

9. Frequently Asked Questions (FAQ)

9.1 Why Does the iMA Value Become 0 in MQL5?

The main causes are usually one of the following.

  • Insufficient historical data (not enough bars)
  • CopyBuffer failed to retrieve the values correctly
  • Improper start position (start_pos) or number of elements (count)
  • The tester has just started and not enough data has formed yet

Countermeasures:

  • Check with Bars() that there are enough bars
  • Always verify the return value of CopyBuffer
  • Use confirmed bars (index 1 or later)

If you proceed with logic when the value is 0, it can lead to incorrect trade entries.

9.2 What Is the Difference Between iMA in MQL4 and MQL5?

The biggest difference is the handle-based architecture.

  • MQL4: iMA() directly returns the value
  • MQL5: iMA() returns a handle, and values are retrieved using CopyBuffer

Therefore, MQL4 code cannot be ported directly.

A common beginner confusion is that iMA does not return a value.
In MQL5, the process is always: handle creation → CopyBuffer retrieval.

9.3 How Many Values Should Be Retrieved with CopyBuffer?

This depends on the purpose.

  • Simple value reference: 2 values (confirmed bar and previous bar)
  • Cross detection: at least 2 values (comparison with previous state required)
  • Slope detection: 3 or more values

The important rule is to always retrieve more elements than the maximum index you reference.

Otherwise, you will encounter an array out of range error.

9.4 Is It a Problem to Call iMA on Every Tick?

It is not recommended.

Reasons:

  • Creating indicators on every tick generates unnecessary load
  • Backtest speed decreases
  • Performance issues become visible in multi-symbol EAs

Safe design:

  • Create the handle in OnInit
  • Execute CopyBuffer only when a new bar is confirmed

9.5 Is It Okay to Use the Unconfirmed Bar (index 0)?

Technically possible, but not recommended in real trading.

Reasons:

  • Unconfirmed bars change as price fluctuates
  • Backtest and live results become inconsistent
  • Cross detection becomes unstable

For reproducibility, use confirmed bars (index 1 or later).

This website stores cookies on your computer. These cookies are used to provide a more personalized experience and to track your whereabouts around our website in compliance with the European General Data Protection Regulation. If you decide to to opt-out of any future tracking, a cookie will be setup in your browser to remember this choice for one year.

Accept or Deny