How to Calculate Moving Average (MA) on an Array in MQL5?

What is a Moving Average (MA)?

A moving average (MA) is a widely used technical indicator that smooths out price data by creating an average price over a specified period. It helps to identify trends and potential support/resistance levels by filtering out short-term price fluctuations. There are several types of moving averages, with the Simple Moving Average (SMA) and Exponential Moving Average (EMA) being the most common.

Why Use Moving Averages in MQL5?

In MQL5, MAs are invaluable tools for:

  • Trend Identification: Determining the overall direction of the market.
  • Signal Generation: Identifying potential buy or sell signals when price crosses an MA or when two MAs cross each other.
  • Smoothing Price Data: Reducing noise and highlighting underlying trends.
  • Algorithmic Trading: Incorporating MA values into automated trading strategies (Expert Advisors).

Overview of Array Handling in MQL5

MQL5 arrays are fundamental for storing and manipulating historical price data or any series of numerical values. Understanding array indexing, dynamic array resizing, and efficient data access is crucial for implementing MA calculations. MQL5 provides functions for array manipulation, such as ArrayResize(), ArrayCopy(), and ArraySetAsSeries(), which are essential for optimizing your MQL5 code.

Implementing Moving Average Calculation on an Array

Basic MA Calculation Logic

The core concept involves iterating through a defined array (e.g., price data) and calculating an average based on a given period. For SMA, this involves summing the values within the period and dividing by the period. For EMA, a weighting factor is applied to give more importance to recent data.

MQL5 Function for Simple Moving Average (SMA)

Here’s an MQL5 function to calculate the Simple Moving Average (SMA) on an array:

double CalculateSMA(const double& data[], int period, int shift) {
 if(shift < 0 || shift >= ArraySize(data))
 return EMPTY_VALUE; // Invalid shift value

 if(period <= 0 || period > ArraySize(data))
 return EMPTY_VALUE; // Invalid period value

 double sum = 0.0;
 int startIndex = shift;
 int endIndex = MathMin(shift + period, ArraySize(data));

 if (endIndex <= startIndex)
 return EMPTY_VALUE;

 for (int i = startIndex; i < endIndex; i++) {
 sum += data[i];
 }
 return sum / period;
}

MQL5 Function for Exponential Moving Average (EMA)

Here’s an MQL5 function to calculate the Exponential Moving Average (EMA) on an array:

double CalculateEMA(const double& data[], int period, int shift, double previousEMA) {
 if(shift < 0 || shift >= ArraySize(data))
 return EMPTY_VALUE; // Invalid shift value

 if(period <= 0 || period > ArraySize(data))
 return EMPTY_VALUE; // Invalid period value

 double alpha = 2.0 / (period + 1);
 double ema = alpha * data[shift] + (1 - alpha) * previousEMA;
 return ema;
}

double CalculateEMAFirstValue(const double& data[], int period){
 double sum = 0.0;
 if(period <= 0 || period > ArraySize(data))
 return EMPTY_VALUE; // Invalid period value

 for(int i = 0; i < period; i++){
 sum += data[i];
 }
 return sum / period;
}

Practical Examples and Code Snippets

Calculating SMA on a Price Array

double prices[];
ArraySetAsSeries(prices, true);
CopyClose(_Symbol, _Period, 0, 100, prices);

int period = 20;
double smaValue = CalculateSMA(prices, period, 0); // SMA for the most recent price
Print("SMA Value: ", smaValue);

Calculating EMA on a Price Array

double prices[];
ArraySetAsSeries(prices, true);
CopyClose(_Symbol, _Period, 0, 100, prices);

int period = 20;
double firstEMA = CalculateEMAFirstValue(prices, period);
double emaValue = CalculateEMA(prices, period, 0, firstEMA); // EMA for the most recent price
Print("EMA Value: ", emaValue);

Visualizing MA on a Chart Using Arrays

To visualize the MA, you’d typically calculate the MA for each bar in a range and plot it on the chart using IndicatorSetInteger, IndicatorSetDouble and SetIndexBuffer functions. A custom indicator would be the appropriate tool for this task.

Optimizing MA Calculation for Performance

Pre-calculating Values for Efficiency

In EMA calculations, the previous EMA value is used. Storing and reusing these values can significantly improve performance, especially when calculating the EMA over a large dataset.

Array Initialization and Management

Use ArrayResize() carefully to avoid unnecessary memory allocation. Consider pre-allocating the array with a reasonable size if you know the approximate data size beforehand. ArraySetAsSeries() is crucial for ensuring that the array is indexed correctly for time series data (most recent data at index 0).

Reducing Loop Iterations

For real-time applications, avoid recalculating the entire MA with each tick. Instead, update the MA using the new price data. For SMA, subtract the oldest value from the sum and add the newest value. For EMA, apply the EMA formula using the previous EMA value and the new price.

Advanced Techniques and Considerations

Handling Edge Cases (Array Size vs. MA Period)

Always validate that the array size is greater than or equal to the MA period. Handle cases where the array is smaller than the period by either returning a default value (e.g., EMPTY_VALUE) or calculating the MA using the available data (e.g., a shorter-period SMA).

Using Different Price Types (Open, High, Low, Close)

The MA can be calculated using different price types. Choose the price type that best suits your trading strategy and analysis. Common options include:

  • Close Price: Most commonly used.
  • Open Price: Useful for identifying gaps.
  • High/Low Prices: Used to calculate the typical price or median price.
  • Typical Price: (High + Low + Close) / 3
  • Median Price: (High + Low) / 2

Combining Multiple MAs

Many trading strategies involve using multiple MAs with different periods. Crossovers of these MAs can generate buy/sell signals. Implement functions to calculate and manage these multiple MAs efficiently.

For example, a common strategy involves using a short-period MA (e.g., 9-period) and a long-period MA (e.g., 21-period). A buy signal is generated when the short-period MA crosses above the long-period MA, and a sell signal is generated when the short-period MA crosses below the long-period MA.


Leave a Reply