1

I need to calculate the ATR the same way as in Pine Script, the trading view code. I'm talking about the Average True Range indicator in technical analysis for stocks or FX. In the documentation in Pine Script says is calculated like this:

plot(rma(close, 15))

// same on pine, but much less efficient
pine_rma(x, y) =>
    alpha = y
    sum = 0.0
    sum := (x + (alpha - 1) * nz(sum[1])) / alpha
plot(pine_rma(close, 15))
RETURNS
Exponential moving average of x with alpha = 1 / y.

I have tried the same way as in the documentation in MQL5, and the results of the strategy are not similar at all, something is wrong with the ATR. Calculate the True Range is straightforward, I know the problem is in how is calculated this RMA (rolling moving average?). It says is calculated as in the original RSI indicator. Can someone explain better please how is calculated the ATR in Pine Script, hopefully with a example. At the moment I used the EMA with alpha= 1 / ATR_Period , as in the documentation, but seems is not the same. Bellow is the code for the new ATR, basically is the same as the default in MT5, I only changed the last part, where is calculated. Thank you for the help!

//--- the main loop of calculations
   for(i=limit;i<rates_total && !IsStopped();i++)
     {
      ExtTRBuffer[i]=MathMax(high[i],close[i-1])-MathMin(low[i],close[i-1]);
      ExtATRBuffer[i]=(ExtTRBuffer[i] - ExtATRBuffer[i-1]) * (1 / ATR_Period) +ExtATRBuffer[i-1] ; // Here I calculated the EMA of the True Range
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
cristianc
  • 51
  • 1
  • 2
  • 8

3 Answers3

3

On Pine version 4, you can use :

//@version=4
myAtr = atr(14)

https://www.tradingview.com/pine-script-reference/#fun_atr

OlivierLarue
  • 2,234
  • 27
  • 28
2

That's ATR implementation in Pine Script

//@version=3
study(title="Average True Range", shorttitle="ATR", overlay=false)

pine_rma(x, y) =>
    alpha = y
    sum = 0.0
    sum := (x + (alpha - 1) * nz(sum[1])) / alpha

true_range() =>
    max(high - low, max(abs(high - close[1]), abs(low - close[1])))

plot(pine_rma(true_range(), 14), color=red)
//plot(atr(14))
Michel_T.
  • 2,741
  • 5
  • 21
  • 31
  • Thanks for the response. On Pine documentation says alpha = 1 / Y is this not true? Also, the sum variable is "zero" only at the start right? in the next iterations is equal to the Average True Range of the previous bar right? I can't get similar results in MQL5. – cristianc Apr 03 '19 at 20:26
  • 1) that's true, `pine_rma` it can be rewritten in the next way: https://stackoverflow.com/a/48960194/1910483, but the result is the same. 2) `sum` at first becomes zero at every bar, and then is calculated in the next way: `sum := (x + (alpha - 1) * nz(sum[1])) / alpha`, so at the end of the very first calculation `sum` equals to `x`. We have to use `sum = 0.0` to let the compiller know what the variable's type is. – Michel_T. Apr 04 '19 at 06:49
  • Thank you very much Michel T. know I have less difference with the results in MT5. I really tried different types of moving averages and this is the one more similar. I know it would never be same because I tried a simple moving average in both Trading View and Metatrader and they are similar but not exactly. The difference I think is in the prices data and the spread at the moment of calculation. Anyway, I really appreciate your help. I can't vote at the moment, seems I'm to little just yet, haha. : ) – cristianc Apr 05 '19 at 12:53
0

Quoting Michael, I just was realized that implementation means in practice

(tr1+tr2+...tr_n)/n

where n means periods back. So it means that atr(periods) means the average of tr in each bar along n periods. Michal do that in pinescript because all in pinescripte is a serie and needs recursion hack back the past sum.

Take a look of the refactored same code, so you will realize about what I'm saying:

/@version=3
study(title="Average True Range", shorttitle="ATR", overlay=false)
averageTrueRange(tr, periods) =>
    sum = 0.0
    sum := (tr + (periods - 1) * nz(sum[1])) / periods

currentTrueRange() =>
    max(high - low, max(abs(high - close[1]), abs(low - close[1])))

plot(averageTrueRange(currentTrueRange(), 15))
jechaviz
  • 551
  • 1
  • 9
  • 23