Complete .mq5 source code

MACD MQL5 Indicator: Difference Histogram and Closed-Bar Alerts

Build a custom MT5 indicator with MACD main and signal lines, a main-minus-signal histogram, and completed-bar crossover alerts. The source uses the chart symbol and timeframe. It is an indicator, not an Expert Advisor: it cannot place orders, size positions, or manage stops. No strategy performance is established by these indicator values.

How the indicator signal works

Calculation and signal conditions

iMACD supplies main line buffer 0 and signal line buffer 1. This indicator plots their difference as a separate histogram. An upward signal compares completed bars 2 and 1: main was at or below signal and is now above it. A downward signal uses the reverse comparison. The histogram sign change expresses the same crossover, not independent confirmation. There is no below-zero, swing-low, volume, or ATR filter.

Interpretation and limitations

Alerts report a completed-bar crossover and do not create or close a trade. Current-bar lines can change as prices arrive. Historical values can also change when source history changes; closed-bar signaling does not guarantee immutable broker data. If an EA consumes this indicator with iCustom, its custom buffers are 0 difference, 1 main, and 2 signal, which differs from the built-in iMACD mapping. Trade rules and costs require a separate tested EA.

MQL5 Custom Indicator Code

// MACD_Custom.mq5: indicator only, no trading operations.
#property copyright "Pineify.app"
#property version "1.10"
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots 3
#property indicator_label1 "Main minus signal"
#property indicator_type1 DRAW_HISTOGRAM
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
#property indicator_label2 "MACD main"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrRed
#property indicator_label3 "Signal"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrOrange
input int InpFastEMA = 12;
input int InpSlowEMA = 26;
input int InpSignalSMA = 9;
input bool InpAlerts = true;
input bool InpPush = false;
double Histogram[], MainLine[], SignalLine[];
int handle = INVALID_HANDLE;
datetime lastChecked = 0;
int OnInit()
{
   if(InpFastEMA <= 0 || InpSlowEMA <= InpFastEMA || InpSignalSMA <= 0)
      return INIT_PARAMETERS_INCORRECT;
   SetIndexBuffer(0, Histogram, INDICATOR_DATA);
   SetIndexBuffer(1, MainLine, INDICATOR_DATA);
   SetIndexBuffer(2, SignalLine, INDICATOR_DATA);
   ArraySetAsSeries(Histogram, false);
   ArraySetAsSeries(MainLine, false);
   ArraySetAsSeries(SignalLine, false);
   for(int p = 0; p < 3; p++)
   {
      PlotIndexSetInteger(p, PLOT_DRAW_BEGIN, InpSlowEMA + InpSignalSMA - 2);
      PlotIndexSetDouble(p, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   }
   IndicatorSetString(INDICATOR_SHORTNAME, "MACD difference and lines");
   handle = iMACD(_Symbol, _Period, InpFastEMA, InpSlowEMA, InpSignalSMA, PRICE_CLOSE);
   return handle == INVALID_HANDLE ? INIT_FAILED : 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[])
{
   int warmup = InpSlowEMA + InpSignalSMA - 2;
   if(rates_total < warmup + 3) return 0;
   ArraySetAsSeries(time, false);
   double main[], signal[];
   if(CopyBuffer(handle, 0, 0, rates_total, main) != rates_total ||
      CopyBuffer(handle, 1, 0, rates_total, signal) != rates_total) return prev_calculated;
   // Full chronological copy for clarity; optimize only after profiling.
   for(int i = 0; i < rates_total; i++)
   {
      MainLine[i] = i < warmup ? EMPTY_VALUE : main[i];
      SignalLine[i] = i < warmup ? EMPTY_VALUE : signal[i];
      Histogram[i] = i < warmup ? EMPTY_VALUE : main[i] - signal[i];
   }
   int bar = rates_total - 2;
   if(prev_calculated == 0) { lastChecked = time[bar]; return rates_total; }
   if(time[bar] == lastChecked) return rates_total;
   lastChecked = time[bar];
   bool up = main[bar-1] <= signal[bar-1] && main[bar] > signal[bar];
   bool down = main[bar-1] >= signal[bar-1] && main[bar] < signal[bar];
   if(up || down)
   {
      string msg = _Symbol + " " + EnumToString(_Period) + (up ? " MACD cross up" : " MACD cross down");
      if(InpAlerts) Alert(msg);
      if(InpPush && !SendNotification(msg)) Print("Push failed: ", GetLastError());
   }
   return rates_total;
}
void OnDeinit(const int reason)
{
   if(handle != INVALID_HANDLE) IndicatorRelease(handle);
}

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.

Pine Script vs MQL5: Same Strategy, Different Platforms

AspectPine Script (TradingView)MQL5 (MetaTrader 5)
ExecutionSeries evaluated on chart updatesEvent handlers with explicit buffers
DeploymentRuns in TradingView with alertsRuns in the MT5 terminal or on a VPS
Broker accessStrategy orders are simulated; live automation needs a separate integrationDirect broker connectivity
BacktestingStrategy Tester for strategy scriptsStrategy Tester for Expert Advisors
Code complexitySimpler, functional syntaxC++-like, more powerful

The calculation can be implemented on either platform, but the runtime model and buffer APIs differ. Read the Pine Script reference guide before porting logic between them.

Frequently Asked Questions

Related MQL5 pages

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.