EMA M5 Scalping MQL5 Indicator: Moving Average Momentum on 5-Minute Chart
Display completed-bar 9/21 EMA crossovers on an M5 chart, filtered by a configurable same-timeframe trend EMA and ATR threshold. The indicator plots separate bullish and bearish arrows and can issue local or email alerts. It does not execute trades, provide an H4 filter, or report verified backtest performance.
How the indicator signal works
Calculation and signal conditions
Attach the indicator to M5. For each completed bar, compare the fast/slow EMA ordering with the preceding completed bar, then require its close to be on the corresponding side of the M5 trend EMA and its ATR to meet the point threshold. Historical arrows and live alerts use the same filtered condition. The 9/21/200/14 inputs are examples, not best settings.
Interpretation and limitations
There is no trailing stop, take-profit, position close, news filter or spread filter in this indicator. A separate EA must define and test those rules. Arrows are placed on the completed signal bar and become available after it closes. The 10-point threshold means 10 times SYMBOL_POINT; it is not universally 10 pips or a validated volatility cutoff.
MQL5 Custom Indicator Code
// Educational M5 crossover display. No orders or verified results.
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 4
#property indicator_label1 "Fast EMA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label2 "Slow EMA"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrange
#property indicator_label3 "Bullish crossover"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrLime
#property indicator_label4 "Bearish crossover"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrRed
input int InpFastEMA=9;
input int InpSlowEMA=21;
input int InpTrendPeriod=200; // Same M5 timeframe, not H4
input int InpATRPeriod=14;
input int InpMinATRPoints=10;
input bool InpEnableAlerts=true;
input bool InpEnableMail=false;
double Fast[],Slow[],Bull[],Bear[],Trend[],Atr[];
int hFast=INVALID_HANDLE,hSlow=INVALID_HANDLE,hTrend=INVALID_HANDLE,hATR=INVALID_HANDLE;
datetime lastAlert=0;
int OnInit()
{
if(_Period!=PERIOD_M5) {Print("Attach this example to an M5 chart"); return INIT_FAILED;}
if(InpFastEMA<1 || InpSlowEMA<=InpFastEMA || InpTrendPeriod<1 || InpATRPeriod<1 || InpMinATRPoints<0)
return INIT_PARAMETERS_INCORRECT;
SetIndexBuffer(0,Fast,INDICATOR_DATA);SetIndexBuffer(1,Slow,INDICATOR_DATA);
SetIndexBuffer(2,Bull,INDICATOR_DATA);SetIndexBuffer(3,Bear,INDICATOR_DATA);
ArraySetAsSeries(Fast,true);ArraySetAsSeries(Slow,true);
ArraySetAsSeries(Bull,true);ArraySetAsSeries(Bear,true);
ArraySetAsSeries(Trend,true);ArraySetAsSeries(Atr,true);
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpFastEMA-1);
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpSlowEMA-1);
PlotIndexSetInteger(2,PLOT_ARROW,233);PlotIndexSetInteger(3,PLOT_ARROW,234);
PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,EMPTY_VALUE);PlotIndexSetDouble(3,PLOT_EMPTY_VALUE,EMPTY_VALUE);
hFast=iMA(_Symbol,PERIOD_M5,InpFastEMA,0,MODE_EMA,PRICE_CLOSE);
hSlow=iMA(_Symbol,PERIOD_M5,InpSlowEMA,0,MODE_EMA,PRICE_CLOSE);
hTrend=iMA(_Symbol,PERIOD_M5,InpTrendPeriod,0,MODE_EMA,PRICE_CLOSE);
hATR=iATR(_Symbol,PERIOD_M5,InpATRPeriod);
if(hFast==INVALID_HANDLE || hSlow==INVALID_HANDLE || hTrend==INVALID_HANDLE || hATR==INVALID_HANDLE) return INIT_FAILED;
IndicatorSetString(INDICATOR_SHORTNAME,"M5 EMA crossover with M5 filters");
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(hFast!=INVALID_HANDLE) IndicatorRelease(hFast);
if(hSlow!=INVALID_HANDLE) IndicatorRelease(hSlow);
if(hTrend!=INVALID_HANDLE) IndicatorRelease(hTrend);
if(hATR!=INVALID_HANDLE) IndicatorRelease(hATR);
}
int OnCalculate(const int n,const int previous,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[])
{
int warm=MathMax(InpTrendPeriod,MathMax(InpSlowEMA,InpATRPeriod));
if(n<warm+3) return 0;
ArraySetAsSeries(time,true);ArraySetAsSeries(close,true);
ArraySetAsSeries(high,true);ArraySetAsSeries(low,true);
if(CopyBuffer(hFast,0,0,n,Fast)!=n || CopyBuffer(hSlow,0,0,n,Slow)!=n ||
CopyBuffer(hTrend,0,0,n,Trend)!=n || CopyBuffer(hATR,0,0,n,Atr)!=n) return previous;
ArrayInitialize(Bull,EMPTY_VALUE);ArrayInitialize(Bear,EMPTY_VALUE);
for(int i=n-warm-2;i>=1;i--)
{
if(Atr[i]<=0 || Atr[i]<InpMinATRPoints*_Point) continue;
bool up=Fast[i]>Slow[i] && Fast[i+1]<=Slow[i+1] && close[i]>Trend[i];
bool down=Fast[i]<Slow[i] && Fast[i+1]>=Slow[i+1] && close[i]<Trend[i];
if(up) Bull[i]=low[i]-5*_Point;
if(down) Bear[i]=high[i]+5*_Point;
}
if(previous>0 && time[1]!=lastAlert)
{
lastAlert=time[1];
if(Bull[1]!=EMPTY_VALUE || Bear[1]!=EMPTY_VALUE)
{
string msg=StringFormat("%s M5 EMA %s confirmed at %s",_Symbol,
Bull[1]!=EMPTY_VALUE ? "bullish" : "bearish",TimeToString(time[1]));
if(InpEnableAlerts) Alert(msg);
if(InpEnableMail && !SendMail("M5 EMA alert",msg)) Print("Mail failed: ",GetLastError());
}
}
return n;
}
Copy this code into MetaEditor, save it in the MQL5/Indicators folder, and compile with F7.
Change the settings or add your own signal filter
Describe the inputs, buffers, alerts, visual style, or confirmation filter you want. Pineify generates editable MQL5 source code that you can inspect and compile in MetaEditor.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.