Complete .mq5 source code

MACD H1 MQL5 Indicator: Completed-Bar Crosses and EMA Filter

This H1-only custom indicator plots the built-in MACD main and signal lines, their difference histogram, and separate bullish/bearish completed-bar arrows. An optional same-H1 EMA filter compares the signal-bar close with its EMA. It displays calculations and alerts; it contains no orders, exits, H4 filter or verified trading-performance record.

How the indicator signal works

Calculation and signal conditions

A bullish marker requires MACD main to move from at/below the signal line to above it between two completed H1 bars; bearish reverses the relation. With the EMA filter enabled, the same completed close must be above/below the same-bar EMA. Main-minus-signal is positive/negative as a consequence of that cross, not independent confirmation. There is no three-bar contraction requirement or extra one-bar wait.

Interpretation and limitations

The program marks signals and optionally sends desktop, push and sound alerts independently. It does not open or close positions or implement ATR trailing. Histogram colors show the signed main-minus-signal value rising, falling or unchanged versus its prior bar; green does not always mean accelerating bullish momentum. Current-bar plots can change, while arrows require a completed bar. History updates and data availability still need testing; full-history handle copies have a computational cost.

MQL5 Custom Indicator Code

// MACD H1 display and completed-bar alerts; no trading or verified results.
#property copyright "Pineify.app"
#property version "1.01"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots 5
#property indicator_label1 "MACD main"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label2 "Signal"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrangeRed
#property indicator_label3 "Main minus signal"
#property indicator_type3 DRAW_COLOR_HISTOGRAM
#property indicator_color3 clrLimeGreen,clrIndianRed,clrDarkGray
#property indicator_width3 2
#property indicator_label4 "Bull cross"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrDodgerBlue
#property indicator_label5 "Bear cross"
#property indicator_type5 DRAW_ARROW
#property indicator_color5 clrRed
input int InpFastEMA=12;
input int InpSlowEMA=26;
input int InpSignalSMA=9;
input bool InpUseTrendFilter=true;
input int InpTrendFilterPeriod=200;
input bool InpAlerts=true;
input bool InpPushAlerts=false;
input bool InpSoundAlerts=false;
int macdHandle=INVALID_HANDLE,emaHandle=INVALID_HANDLE;
double mainBuf[],signalBuf[],histBuf[],colorBuf[],bullBuf[],bearBuf[];
datetime lastAlertBar=0;
int OnInit() {
   if(_Period!=PERIOD_H1 || InpFastEMA<1 || InpSlowEMA<=InpFastEMA || InpSignalSMA<1 ||
      (InpUseTrendFilter && InpTrendFilterPeriod<1)) return INIT_PARAMETERS_INCORRECT;
   SetIndexBuffer(0,mainBuf,INDICATOR_DATA); SetIndexBuffer(1,signalBuf,INDICATOR_DATA);
   SetIndexBuffer(2,histBuf,INDICATOR_DATA); SetIndexBuffer(3,colorBuf,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(4,bullBuf,INDICATOR_DATA); SetIndexBuffer(5,bearBuf,INDICATOR_DATA);
   ArraySetAsSeries(mainBuf,false); ArraySetAsSeries(signalBuf,false);
   ArraySetAsSeries(histBuf,false); ArraySetAsSeries(colorBuf,false);
   ArraySetAsSeries(bullBuf,false); ArraySetAsSeries(bearBuf,false);
   PlotIndexSetInteger(2,PLOT_COLOR_INDEXES,3);
   PlotIndexSetInteger(3,PLOT_ARROW,233); PlotIndexSetInteger(4,PLOT_ARROW,234);
   PlotIndexSetInteger(3,PLOT_ARROW_SHIFT,8); PlotIndexSetInteger(4,PLOT_ARROW_SHIFT,-8);
   for(int p=0;p<5;p++) {
      PlotIndexSetDouble(p,PLOT_EMPTY_VALUE,EMPTY_VALUE);
      PlotIndexSetInteger(p,PLOT_DRAW_BEGIN,InpSlowEMA+InpSignalSMA-2);
   }
   macdHandle=iMACD(_Symbol,PERIOD_H1,InpFastEMA,InpSlowEMA,InpSignalSMA,PRICE_CLOSE);
   if(macdHandle==INVALID_HANDLE) return INIT_FAILED;
   if(InpUseTrendFilter) {
      emaHandle=iMA(_Symbol,PERIOD_H1,InpTrendFilterPeriod,0,MODE_EMA,PRICE_CLOSE);
      if(emaHandle==INVALID_HANDLE) return INIT_FAILED;
   }
   IndicatorSetString(INDICATOR_SHORTNAME,"MACD H1 completed crosses");
   return INIT_SUCCEEDED;
}
void OnDeinit(const int reason) {
   if(macdHandle!=INVALID_HANDLE) IndicatorRelease(macdHandle);
   if(emaHandle!=INVALID_HANDLE) IndicatorRelease(emaHandle);
}
int OnCalculate(const int n,const int prev,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=InpSlowEMA+InpSignalSMA-2;
   int crossWarm=InpUseTrendFilter ? MathMax(warm+1,InpTrendFilterPeriod-1) : warm+1;
   if(n<crossWarm+2) return 0;
   ArraySetAsSeries(time,false); ArraySetAsSeries(close,false);
   double m[],s[],ema[];
   if(CopyBuffer(macdHandle,0,0,n,m)!=n || CopyBuffer(macdHandle,1,0,n,s)!=n) return prev;
   if(InpUseTrendFilter && CopyBuffer(emaHandle,0,0,n,ema)!=n) return prev;
   int start=MathMax(warm,prev-1);
   if(prev==0 || prev>n) {
      ArrayInitialize(mainBuf,EMPTY_VALUE); ArrayInitialize(signalBuf,EMPTY_VALUE);
      ArrayInitialize(histBuf,EMPTY_VALUE); ArrayInitialize(colorBuf,2);
      ArrayInitialize(bullBuf,EMPTY_VALUE); ArrayInitialize(bearBuf,EMPTY_VALUE);
      lastAlertBar=0; start=warm;
   }
   for(int i=start;i<n;i++) {
      mainBuf[i]=m[i]; signalBuf[i]=s[i]; histBuf[i]=m[i]-s[i];
      colorBuf[i]=i>warm ? (histBuf[i]>histBuf[i-1] ? 0 : (histBuf[i]<histBuf[i-1] ? 1 : 2)) : 2;
      bullBuf[i]=EMPTY_VALUE; bearBuf[i]=EMPTY_VALUE;
      if(i<crossWarm || i==n-1) continue;
      bool bull=m[i]>s[i] && m[i-1]<=s[i-1];
      bool bear=m[i]<s[i] && m[i-1]>=s[i-1];
      if(InpUseTrendFilter) { bull=bull && close[i]>ema[i]; bear=bear && close[i]<ema[i]; }
      if(bull) bullBuf[i]=histBuf[i];
      if(bear) bearBuf[i]=histBuf[i];
   }
   // Read only completed bar n-2. Historical calculation does not replay old alerts.
   int bar=n-2;
   if(prev>0 && time[bar]!=lastAlertBar) {
      lastAlertBar=time[bar];
      bool bull=bullBuf[bar]!=EMPTY_VALUE,bear=bearBuf[bar]!=EMPTY_VALUE;
      if(bull || bear) {
         string msg=StringFormat("%s H1 MACD %s at %s",_Symbol,bull?"bull":"bear",TimeToString(time[bar]));
         if(InpAlerts) Alert(msg);
         if(InpPushAlerts && !SendNotification(msg)) Print("Push failed: ",GetLastError());
         if(InpSoundAlerts && !PlaySound("alert.wav")) Print("Sound 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.