Complete .mq5 source code

MT5 Supertrend Indicator: MQL5 Code and Alerts

A Supertrend indicator for MT5 is a custom MQL5 chart overlay that uses Average True Range to place a trailing band above or below price. This implementation includes complete source code, configurable ATR settings, separate bullish and bearish buffers, and alerts that trigger only after a candle closes.

What this MT5 indicator covers

ATR period 10 and multiplier 3.0 are example inputs, not tested optimal settings.

The code calculates signals in OnCalculate() and keeps indicator logic separate from order execution.

Closed-bar alerts use the last completed candle, so a forming candle cannot trigger a final signal.

The recurrence classifies direction from observed price and ATR; repeated flips can occur without profitable follow-through.

How the indicator signal works

Calculation and signal conditions

A bullish flip occurs when the current close moves above the final upper band after the previous state was bearish. The indicator then plots the final lower band beneath price. The code calculates the active candle for visual feedback, but alerts inspect the last completed candle and compare it with the candle before it. Check array direction and timestamps explicitly; a forming-bar value must not be labeled a completed signal.

Interpretation and limitations

A bearish flip occurs when the current close falls below the final lower band after the previous state was bullish. The plotted line moves above price and switches to the bearish buffer. Supertrend can be used as a direction filter or a trailing reference, but it is not an order system by itself. If an Expert Advisor uses these buffers, its own position sizing, spread checks, stop placement, and execution rules still need to be defined and tested.

MQL5 Custom Indicator Code

//+------------------------------------------------------------------+
//| SuperTrend_Custom.mq5                                            |
//| MT5 custom indicator with ATR bands and closed-bar alerts        |
//| Educational example. This is not financial advice.              |
//+------------------------------------------------------------------+
#property copyright "Pineify"
#property link      "https://pineify.app"
#property version   "1.10"
#property strict

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   2

#property indicator_label1  "Supertrend Up"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrLimeGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "Supertrend Down"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrTomato
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

input int    InpAtrPeriod    = 10;
input double InpMultiplier   = 3.0;
input bool   InpDesktopAlert = true;
input bool   InpPushAlert    = false;

double UpBuffer[];
double DownBuffer[];
double TrendBuffer[];
double FinalUpperBuffer[];
double FinalLowerBuffer[];
double AtrBuffer[];

int      atrHandle = INVALID_HANDLE;
datetime lastAlertBar = 0;

int OnInit()
  {
   if(InpAtrPeriod < 1 || InpMultiplier <= 0.0)
      return INIT_PARAMETERS_INCORRECT;

   SetIndexBuffer(0, UpBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, DownBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, TrendBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(3, FinalUpperBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(4, FinalLowerBuffer, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, AtrBuffer, INDICATOR_CALCULATIONS);

   ArraySetAsSeries(UpBuffer, false);
   ArraySetAsSeries(DownBuffer, false);
   ArraySetAsSeries(TrendBuffer, false);
   ArraySetAsSeries(FinalUpperBuffer, false);
   ArraySetAsSeries(FinalLowerBuffer, false);
   ArraySetAsSeries(AtrBuffer, false);

   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpAtrPeriod);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpAtrPeriod);

   atrHandle = iATR(_Symbol, _Period, InpAtrPeriod);
   if(atrHandle == INVALID_HANDLE)
     {
      Print("Could not create iATR handle. Error: ", GetLastError());
      return INIT_FAILED;
     }

   IndicatorSetString(
      INDICATOR_SHORTNAME,
      StringFormat("Supertrend(%d, %.2f)", InpAtrPeriod, InpMultiplier)
   );
   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);

   return INIT_SUCCEEDED;
  }

void OnDeinit(const int reason)
  {
   if(atrHandle != INVALID_HANDLE)
      IndicatorRelease(atrHandle);
  }

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 <= InpAtrPeriod + 2)
      return 0;

   ArraySetAsSeries(time, false);
   ArraySetAsSeries(high, false);
   ArraySetAsSeries(low, false);
   ArraySetAsSeries(close, false);

   int copied = CopyBuffer(atrHandle, 0, 0, rates_total, AtrBuffer);
   if(copied < rates_total)
      return prev_calculated;

   bool reset=prev_calculated==0 || prev_calculated>rates_total;
   int start = reset ? InpAtrPeriod : (int)MathMax(InpAtrPeriod,prev_calculated-1);

   if(reset)
     {
      for(int i = 0; i < InpAtrPeriod; i++)
        {
         UpBuffer[i] = EMPTY_VALUE;
         DownBuffer[i] = EMPTY_VALUE;
         TrendBuffer[i] = 0.0;
         FinalUpperBuffer[i] = 0.0;
         FinalLowerBuffer[i] = 0.0;
        }
     }

   for(int i = start; i < rates_total && !IsStopped(); i++)
     {
      double midpoint = (high[i] + low[i]) * 0.5;
      double basicUpper = midpoint + InpMultiplier * AtrBuffer[i];
      double basicLower = midpoint - InpMultiplier * AtrBuffer[i];

      if(i == InpAtrPeriod)
        {
         FinalUpperBuffer[i] = basicUpper;
         FinalLowerBuffer[i] = basicLower;
         TrendBuffer[i] = -1.0;
        }
      else
        {
         int previous = i - 1;

         FinalUpperBuffer[i] =
            (basicUpper < FinalUpperBuffer[previous] ||
             close[previous] > FinalUpperBuffer[previous])
            ? basicUpper
            : FinalUpperBuffer[previous];

         FinalLowerBuffer[i] =
            (basicLower > FinalLowerBuffer[previous] ||
             close[previous] < FinalLowerBuffer[previous])
            ? basicLower
            : FinalLowerBuffer[previous];

         if(TrendBuffer[previous] < 0.0)
            TrendBuffer[i] =
               close[i] > FinalUpperBuffer[i] ? 1.0 : -1.0;
         else
            TrendBuffer[i] =
               close[i] < FinalLowerBuffer[i] ? -1.0 : 1.0;
        }

      if(TrendBuffer[i] > 0.0)
        {
         UpBuffer[i] = FinalLowerBuffer[i];
         DownBuffer[i] = EMPTY_VALUE;
        }
      else
        {
         UpBuffer[i] = EMPTY_VALUE;
         DownBuffer[i] = FinalUpperBuffer[i];
        }
     }

   int closedBar=rates_total-2,priorBar=rates_total-3;
   if(reset || lastAlertBar==0) lastAlertBar=time[closedBar];
   else if(time[closedBar]!=lastAlertBar)
   {
      lastAlertBar=time[closedBar];
      if(TrendBuffer[closedBar]!=TrendBuffer[priorBar])
      {
         string message=StringFormat("%s %s Supertrend completed %s at %.*f",_Symbol,
            EnumToString(_Period),TrendBuffer[closedBar]>0?"up":"down",_Digits,close[closedBar]);
         if(InpDesktopAlert) Alert(message);
         if(InpPushAlert && !SendNotification(message)) Print("Push failed: ",GetLastError());
      }
   }

   return rates_total;
  }

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

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.