Complete .mq5 source code

ATR Trailing Stop H1 MQL5: Volatility-Adaptive Stop Loss & Exit Strategy

Plot Chandelier-style ATR reference levels on an H1 chart: a rolling high minus an ATR multiple and a rolling low plus that distance. This educational indicator uses the chart timeframe, so attach it to H1 for hourly calculations. It does not place orders, track entry prices, ratchet a live stop or demonstrate a profitable exit strategy.

How the indicator signal works

Calculation and signal conditions

There is no entry signal or position state. For each chart bar the indicator scans the selected lookback using completed bars when InpShift is 1, reads ATR from that same source bar, and plots the two reference levels. In close-based mode it uses the selected close instead of rolling highs and lows. Values 14, 2.0 and 20 are illustrative inputs.

Interpretation and limitations

The plotted levels can move in either direction when the rolling window or ATR changes. They are not ratcheted stops and do not switch active sides after a breach. An EA must separately decide when a position exists, whether to move a stop only toward price, how to handle broker stop/freeze distances, and how to verify a modification result. Shift 0 includes a forming bar and can change intrabar.

MQL5 Custom Indicator Code

// ATR reference levels for the chart timeframe; attach to H1 for hourly data.
// Educational display only: no orders, position state, or performance claim.
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
#property indicator_label1 "Long ATR reference"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrMediumSeaGreen
#property indicator_label2 "Short ATR reference"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrTomato
input int InpAtrPeriod=14;
input double InpAtrMultiplier=2.0;
input int InpLookback=20;
input int InpShift=1;
input bool InpUseHighLow=true;
input bool InpShowOnlyLong=false;
input bool InpShowOnlyShort=false;
double longLevel[],shortLevel[],atrValues[];
int atrHandle=INVALID_HANDLE;
int OnInit()
{
 if(InpAtrPeriod<2 || InpAtrMultiplier<=0 || InpLookback<1 || InpShift<0 ||
    (InpShowOnlyLong && InpShowOnlyShort)) return INIT_PARAMETERS_INCORRECT;
 SetIndexBuffer(0,longLevel,INDICATOR_DATA);
 SetIndexBuffer(1,shortLevel,INDICATOR_DATA);
 ArraySetAsSeries(longLevel,true);
 ArraySetAsSeries(shortLevel,true);
 ArraySetAsSeries(atrValues,true);
 PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE);
 PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE);
 IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
 atrHandle=iATR(_Symbol,_Period,InpAtrPeriod);
 return atrHandle==INVALID_HANDLE ? INIT_FAILED : 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[])
{
 int warmup=MathMax(InpAtrPeriod,InpLookback)+InpShift;
 if(rates_total<=warmup) return 0;
 if(CopyBuffer(atrHandle,0,0,rates_total,atrValues)!=rates_total) return 0;
 ArraySetAsSeries(high,true);
 ArraySetAsSeries(low,true);
 ArraySetAsSeries(close,true);
 ArrayInitialize(longLevel,EMPTY_VALUE);
 ArrayInitialize(shortLevel,EMPTY_VALUE);
 // Recalculate the display for clarity; large histories require profiling.
 for(int i=rates_total-warmup-1;i>=0 && !IsStopped();i--)
 {
  int source=i+InpShift;
  double upper=close[source],lower=close[source];
  if(InpUseHighLow)
  {
   upper=high[source]; lower=low[source];
   for(int j=source+1;j<source+InpLookback;j++)
   {
    upper=MathMax(upper,high[j]); lower=MathMin(lower,low[j]);
   }
  }
  double distance=atrValues[source]*InpAtrMultiplier;
  if(distance<=0) continue;
  if(!InpShowOnlyShort) longLevel[i]=upper-distance;
  if(!InpShowOnlyLong) shortLevel[i]=lower+distance;
 }
 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.

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.