first to answer you: your highlighted line is very different from the actual RMA in TW : thats not even close
I can convert almost anything from pinescript to MT4/5 but this part is always impossible ta.atr() But enough is enough and I needed to have it done so here it is:
TRADINGVIEW ATR INDICATOR IN METATRADER 4 : cheers
//+------------------------------------------------------------------+
//| Tradingview ATR.mq4 |
//| Copyright 2023, Filip Valkovic |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Filip Valkovic"
#property version "1.00"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_label1 "ATR_TradingView"
//--- input parameters
input int period=14; // ATR period
//--- indicator buffers
double ATRBuffer[];
double ExtTRBuffer[];
//--- global variable
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- check for input value
//--- indicator buffers mapping
//IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
SetIndexBuffer(0,ATRBuffer);
SetIndexBuffer(1,ExtTRBuffer);
string short_name="TW ATR("+string(period)+")";
IndicatorSetString(INDICATOR_SHORTNAME,short_name);
SetIndexLabel(1,"TrueRange");
SetIndexStyle(1,DRAW_NONE);
//--- initialization done
}
//+------------------------------------------------------------------+
//| Average True Range |
//+------------------------------------------------------------------+
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[])
{
double alpha=1.0/period;
int i=rates_total-prev_calculated+1;
if(i<0)
i=0;
for(; i>=0 && !IsStopped(); i--)
{
if(i+1>rates_total-1)
continue;
ExtTRBuffer[i]=MathMax(MathMax(high[i]-low[i],MathAbs(high[i]-close[i+1])),MathAbs(low[i]-close[i+1]));
ATRBuffer[i]=ExtTRBuffer[i];
}
i=rates_total-prev_calculated+1;
if(i<0)
i=0;
for(; i>=0 && !IsStopped(); i--)
{
// DONT ASK ABOUT THIS PART it was error catching, it doesnt matter, it works
if(i+period>rates_total && i>rates_total-2*(period+1))
continue;
if(i+period>ArraySize(ExtTRBuffer) && prev_calculated<2*period)
continue;
ATRBuffer[i]=rma(ExtTRBuffer,period,i);
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double rma(double &array[],int len,int i)
{
double result = 0;
double alpha = 1.0/(double)len;
for(int j=0; j<len; j++)
{
if(j==0) // HERE'S THE TRICK - cannot use iMAOnArray() that throws access violation error
result = SimpleMA(i+2*len,len+1,array); // and to get most precise TW output you use double len backstep (i+2*LEN) and then must use LEN+1
else
result=(alpha* array[i+len-j] + (1.0-alpha)*result); //array[i+len-j] another big brain point
}
return result;
}
//+------------------------------------------------------------------+
double SimpleMA(const int position,const int len,const double &price[])
{
//---
double result=0.0;
//--- check position
if(position>=len-1 && len>0)
{
//--- calculate value
for(int i=0;i<len;i++) result+=price[position-i];
result/=len;
}
//---
return(result);
}
Trading View's RMA is the same as MT's SMMA. Never any reason to use the SMMA(L) or RMA(L). They are equivalent to the EMA(2L-1).
My version. Same for MT4. I do not know if there are any differences from the exemple above. I don't have time to compare, although it would be interesting
Forum on trading, automated trading systems and testing trading strategies
Vladislav Boyko, 2023.01.05 00:18
In the end, this
ta.atr
is what I turned into this😄
#property strict #property indicator_separate_window #property indicator_buffers 1 #property indicator_label1 "pine_atr" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDodgerBlue input int inpAtrLength = 14; // Length double tr[]; double atr[]; int OnInit() { IndicatorShortName(StringFormat("pine_atr(%i)", inpAtrLength)); int buffersNumber = 2; IndicatorBuffers(buffersNumber); SetIndexBuffer(0, atr); SetIndexBuffer(1, tr); for(int i = 0; i < buffersNumber; i++) SetIndexEmptyValue(i, EMPTY_VALUE); return(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[]) { pine_buffer_tr(tr, high, low, close, rates_total, prev_calculated); pine_buffer_atr(inpAtrLength, atr, tr, rates_total, prev_calculated); return(rates_total); } void pine_buffer_atr(int period, double &buffer[], const double &tr_data[], int rates_total, int prev_calculated) // Different from the built-in MT4 ATR. Most likely, a different averaging is used in MT4 { pine_buffer_rma(buffer, tr_data, period, rates_total, prev_calculated, 1); } void pine_buffer_rma(double &buffer[], const double &source[], int period, int rates_total, int prev_calculated, int sourceBeginOffset = 0) { for(int i = bufferCalculFrom(rates_total, prev_calculated, period, sourceBeginOffset); i >= 0; i--) buffer[i] = pine_rma(source, period, i, buffer[i+1]); } double pine_rma(const double &source[], int length, int bar, double prevValue = EMPTY_VALUE) { double alpha = 1.0 / length; return(prevValue == EMPTY_VALUE ? pine_sma(source, length, bar) : alpha * source[bar] + (1.0 - alpha) * prevValue); } double pine_sma(const double &source[], int period, int bar) { double sum = 0.0; for(int i = 0; i <= period - 1; i++) sum += source[bar + i] / period; return(sum); } void pine_buffer_tr(double &buffer[], const double &high[], const double &low[], const double &close[], int rates_total, int prev_calculated) { for(int i = bufferCalculFrom(rates_total, prev_calculated, 2, 0); i >= 0; i--) buffer[i] = pine_tr(high[i], low[i], close[i + 1]); } double pine_tr(double high, double low, double prevClose) { return(MathMax(high - low, MathMax(MathAbs(high - prevClose), MathAbs(low - prevClose)))); } int bufferCalculFrom(int rates_total, int prev_calculated, int period, int sourceBeginOffset) { int notCalculated = rates_total - prev_calculated; int lastIndex = rates_total - 1; return((notCalculated == 0 || notCalculated == 1) ? notCalculated : (lastIndex - (period - 1)) - sourceBeginOffset); }
I can convert almost anything from pinescript to MT4/5 but this part is always impossible ta.atr() But enough is enough and I needed to have it done so here it is:
Oh, I've been interested in this for a long time: ta.linreg()
Could you share your conversion please (if you have worked with it)?
Oh, I've been interested in this for a long time: ta.linreg()
Could you share your conversion please (if you have worked with it)?
I see, linreg is a pain too, I hope I can help. I don't have MQL4 code, but I have pretty simple script in pinescript, this should help you get the linreg() equivalent result with ease.
study("Linear Regression Line",overlay=true) length = input(14) // x = n y = close x_ = sma(x,length) y_ = sma(y,length) mx = stdev(x,length) my = stdev(y,length) c = correlation(x,y,length) slope = c * (my/mx) // inter = y_ - slope*x_ // reg = x*slope + inter plot(reg,color=red,transp=0) https://
so for sma(x) you would best use iMAOnArray(array x, .....)
and same for stdev(X) = iStdDevOnArray()
everything else have its direct equivalent in MQL4 so its should be straightforward conversion.
1. iMAOnArray(ExtTRBuffer,0,2*period-1,0,MODE_EMA,i); = 100 % IDENTICAL RESULT as tradingview ATR
and
2. rma(ExtTRBuffer,period,i);
and I couldn't get them to return same results, mainly because in RMA im using: SimpleMA(const int position,const int len,const double &price[]) and I think it works differently as iMAOnArray
I did try many variations of period and shift/position parameters and it just never returned identical results
So in RMA I ended up using THIS: because it was most precise to correct output.
SimpleMA(i+2*(len-1),2*len-1,array)
here is the updated indicator code, with both calculations plotted: (the correct one is 1st plot = iMAonarray = clrDodgerBlue = ( light blue) the 2nd plot is with RMA = clrBlue = ( darker blue)
TRADINGVIEW ATR INDICATOR IN METATRADER 4: (both plots 1.MAonArray 2.RMA)
//+------------------------------------------------------------------+ //| Tradingview ATR.mq4 | //| Copyright 2023, Filip Valkovic | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, Filip Valkovic" #property version "1.20" #property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 2 #property indicator_type1 DRAW_LINE #property indicator_color1 clrDodgerBlue #property indicator_label1 "ATR_TradingView" #property indicator_type2 DRAW_LINE #property indicator_color2 clrBlue #property indicator_label2 "ATR_TradingView" //--- input parameters input int period=14; // ATR period //--- indicator buffers double ATRBuffer[]; double ATRBuffer2[]; double ExtTRBuffer[]; //--- global variable //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //--- check for input value //--- indicator buffers mapping IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1); SetIndexBuffer(0,ATRBuffer); SetIndexBuffer(1,ATRBuffer2); SetIndexBuffer(2,ExtTRBuffer); string short_name="TW ATR("+string(period)+")"; IndicatorSetString(INDICATOR_SHORTNAME,short_name); SetIndexLabel(1,"RMA ATR"); SetIndexStyle(2,DRAW_NONE); //--- initialization done } //+------------------------------------------------------------------+ //| Average True Range | //+------------------------------------------------------------------+ 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 i=rates_total-prev_calculated+1; if(i<0) i=0; for(; i>=0 && !IsStopped(); i--) { if(i+2>rates_total) { //SET START OF HISTORY DATA ExtTRBuffer[rates_total-1]=0; ExtTRBuffer[rates_total-2]=0; ATRBuffer[rates_total-1]=0; ATRBuffer[rates_total-2]=0; ATRBuffer2[rates_total-1]=0; ATRBuffer2[rates_total-2]=0; continue; } ExtTRBuffer[i]=MathMax(MathMax(high[i]-low[i],MathAbs(high[i]-close[i+1])),MathAbs(low[i]-close[i+1])); ATRBuffer[i]=ExtTRBuffer[i]; ATRBuffer2[i]=ExtTRBuffer[i]; } i=rates_total-prev_calculated+1; if(i<0) i=0; for(; i>=0 && !IsStopped(); i--) { int lenght = 2*period-1; if(i+2>rates_total) continue; ATRBuffer2[i]=rma(ExtTRBuffer,period,i); ATRBuffer[i]=iMAOnArray(ExtTRBuffer,0,lenght,0,MODE_EMA,i); } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ | // could use the SMMA(L) or RMA(L). // Trading View's RMA is equivalent to the EMA(2L-1). //+------------------------------------------------------------------+ double rma(double &array[],int len,int i) { double result = 0; double alpha = 1.0/(double)len; for(int j=0; j<len; j++) { if(j==0) //iMAOnArray(array,len,len,0,MODE_SMA,i); throws access violation error result = SimpleMA(i+2*(len-1),2*len-1,array); //i+2*len-1, len else result=(alpha* array[i+len-1-j] + (1.0-alpha)*result); //array[i+len-1-j] } return result; } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double SimpleMA(const int position,const int len,const double &price[]) { //--- double result=0.0; //--- check position if(position>=len-1 && len>0) { //--- calculate value for(int i=0; i<len; i++) result+=price[position-i]; result/=(double)len; } //--- return(result); } //+------------------------------------------------------------------+
I see, linreg is a pain too, I hope I can help. I don't have MQL4 code, but I have pretty simple script in pinescript, this should help you get the linreg() equivalent result with ease.
so for sma(x) you would best use iMAOnArray(array x, .....)
and same for stdev(X) = iStdDevOnArray()
everything else have its direct equivalent in MQL4 so its should be straightforward conversion.
Very interesting, thanks a lot!

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I need to use the same ATR calculation from trading view in Metatrader 5. This is the code I have so far, it work, but is not getting similar results with Trading View. I know the data is slightly different, but my results in the strategy are very different and I have checked everything, the think that makes big differences is the ATR calculation. This is the code I have so far, the highlighted part is what I changed from the ATR indicator by default in MT5 (only 2 lines).
In the documentation in Trading view this is what it says about the RMA calculations, once you got the True Range (the True Range is a simple calculation and the problem is not there):
Exponential moving average of x with alpha = 1 / y.
Anyone understand the problem here? Like I said the ATR itself is different from Trading View and is making the Strategy is very different from the results I get on Metatrader 5. Thank you!