EMA in MetaTrader 5 — MQL5 Source Code

A custom exponential moving average for MT5

EMA in MetaTrader 5
EMA in MetaTrader 5

Writing your own EMA in MQL5 is a great follow-up to the SMA indicator — same overlay setup, but now with a recurrence and a seed to get right. See the explainer for the concept.

What you’ll need

  • MetaTrader 5 with MetaEditor
  • Save as AlgoGen.EMA.mq5 under MQL5/Indicators/

The source

We seed the recursion with a simple average of the first window (the convention MT5’s own EMA uses), then apply the α = 2/(period+1) update.

//+------------------------------------------------------------------+
//|                                                  AlgoGen.EMA.mq5 |
//|                                          Copyright 2026, AlgoGen |
//|                                           https://www.algogen.io |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, AlgoGen"
#property link      "https://www.algogen.io"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_label1  "EMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrOrangeRed
#property indicator_width1  2

input int InpPeriod = 20; // EMA period

double EMABuffer[];

int OnInit()
  {
   SetIndexBuffer(0, EMABuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriod - 1);
   IndicatorSetString(INDICATOR_SHORTNAME, "AlgoGen EMA(" + (string)InpPeriod + ")");
   return(INIT_SUCCEEDED);
  }

int OnCalculate(const int rates_total, const int prev_calculated,
                const datetime &time[], const double &open[],
                const double &high[],   const double &low[],
                const double &close[],  const long &tick_volume[],
                const long &volume[],   const int &spread[])
  {
   if(rates_total < InpPeriod)
      return(0);

   double alpha = 2.0 / (InpPeriod + 1.0);

   if(prev_calculated == 0)
     {
      // Seed with an SMA of the first window.
      double sum = 0.0;
      for(int j = 0; j < InpPeriod; j++)
         sum += close[j];
      EMABuffer[InpPeriod - 1] = sum / InpPeriod;

      for(int i = InpPeriod; i < rates_total; i++)
         EMABuffer[i] = alpha * close[i] + (1.0 - alpha) * EMABuffer[i - 1];
     }
   else
     {
      for(int i = prev_calculated - 1; i < rates_total; i++)
         EMABuffer[i] = alpha * close[i] + (1.0 - alpha) * EMABuffer[i - 1];
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+

Install & compile

  1. Drop it in MQL5/Indicators/, press F7.
  2. Drag onto a chart and set the period — the orange EMA overlays price, matching the output chart.

Gotchas

  • The seed. We start the recursion from an SMA of the first InpPeriod bars, which matches MT5’s built-in EMA. Seeding from close[0] instead is also valid but will differ slightly early on.
  • Incremental updates. The prev_calculated branch continues the recursion from the last computed bar each tick, rather than recomputing history.
  • Built-in shortcut / MQL4. In an EA use iMA(..., MODE_EMA, ...). In MQL4 the same recurrence applies; swap the OnCalculate signature and buffer setup.

Same indicator elsewhere: Python, Pine Script, EasyLanguage, NinjaScript. Then backtest it in AlgoGen.


This post is educational, not financial advice. Indicators describe the past; they don’t predict the future. Backtest anything before you risk real money on it.

Sources and further reading

  1. Statistical Forecasting for Inventory Control (Royal Statistical Society and Oxford Academic)
  2. Technical indicator functions (MetaQuotes)

Historical research from the Algogen archive. Not investment advice.

Blog

Have a strategy idea?

Describe it in plain English, preview where your rules fire, then decide whether the evidence is worth a backtest.

Keep me postedHow it works