0

TradingView calculates their DMI (equivalent to MT4 ADX) on the bars used, i.e. when you select Heiken Ashi bars for the price display, the Open and Close values for the ADX calculation are the modified HA values. In addition, their DMI takes an extra input, a smoothing period, by which the ADX line is smoothed, which if set to 1 would leave the unchanged traditional ADX line a la Metatrader.

Their code for the DMI is freely available. I have tried to replicate the use of their DMI on Heiken Ashi Bars in the quoted script below.

The plot is very different between Metatrader and Tradingview (see pics).

Trading View Metatrader

I have tidied up the code and added the original PINE script for clarity.

Relevant line numbers are in comments which also contain the lines from the original PINE code.

//+------------------------------------------------------------------+
//|                                                SmoothedHAADX.mq4 |
//|                               Copyright 2021, andydoc1@gmail.com |
//|                                      mailto://andydoc1@gmail.com |
//+------------------------------------------------------------------+
//---- port of DMI from Tradingview
//---- (https://www.tradingview.com/pine-script-reference/v4/#fun_dmi)
//---- applied to Heiken-Ashi Candles.
//---- Still not correct as plots differently.
//---- 
//---- PINE source code for DMI:
//---- up = change(security(heikinashi(syminfo.tickerid), timeframe.period, high))
//---- down = -change(security(heikinashi(syminfo.tickerid), timeframe.period, low))
//---- plusDM = na(up) ? na : (up > down and up > 0 ? up : 0)
//---- minusDM = na(down) ? na : (down > up and down > 0 ? down : 0)
//---- trur = rma(tr, di_len)
//---- plus = fixnan(100 * rma(plusDM, di_len) / trur)
//---- minus = fixnan(100 * rma(minusDM, di_len) / trur)
//---- sum = plus + minus
//---- adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), adx_len)
//---- 
//---- na fills an empty value with NULL
//---- tr is true range
//---- rma is EMA
//---- fixnan fills empty value with previous value
//---- 
//---- original inputs:
//---- di_len = ADX period
//---- adx_len = ADX Smoothing period

#property copyright "Copyright 2020, andydoc1"
#property link      "mailto://andydoc1@gmail.com"
#property version   "1.00"
#property strict

#property indicator_separate_window
#property indicator_buffers 9
#property indicator_color1 White
#property indicator_width1 2
#property indicator_color2 Green
#property indicator_width2 1
#property indicator_style2 1
#property indicator_color3 Red
#property indicator_width3 1
#property indicator_style3 2

//---- buffers
double ExtMapBufferADX[]; //ADX
double ExtMapBufferPDI[]; //+DI
double ExtMapBufferNDI[]; //-DI
double ExtMapBufferHAO[]; //O
double ExtMapBufferHAC[]; //C
double ExtMapBufferTR[]; //tr
double ExtMapBufferPDM[]; //plusDM
double ExtMapBufferMDM[]; //minusDM
double ExtMapBufferDIratio[]; //DI ratio
double up, down, trur, sum, diff;

extern int ADXperiod=14;
extern int ADXsmperiod =14;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBufferADX); //ADX
   SetIndexLabel(0,"ADX"); 
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,ExtMapBufferPDI); //+DI
   SetIndexLabel(1,"Plus DI");
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,ExtMapBufferNDI); //-DI
   SetIndexLabel(2,"Minus DI");
   SetIndexBuffer(3,ExtMapBufferHAO); //Heiken-Ashi Open
   SetIndexBuffer(4,ExtMapBufferHAC); //Heiken-Ashi Close
   SetIndexBuffer(5,ExtMapBufferTR); //True Range
   SetIndexBuffer(6,ExtMapBufferPDM); //+DM
   SetIndexBuffer(7,ExtMapBufferMDM); //-DM
   SetIndexBuffer(8,ExtMapBufferDIratio); //Ratio of Diff(+DI, -DI):Sum(+DI, -DI)
   IndicatorShortName("ADX("+IntegerToString(ADXperiod)+"), based on Heiken Ashi Candles, smoothed over "+IntegerToString(14)+" periods.");
//----
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 counted_bars=IndicatorCounted();
   if(counted_bars < 0)  return(-1);
   if(counted_bars>0) counted_bars--;
   int limit=Bars-counted_bars;
   if(counted_bars==0) limit-=1+ADXperiod+ADXsmperiod;
//---- main loop
   for(int i=limit-1; i>=0; i--)
     {
      ExtMapBufferHAO[i] = (Open[i+1]+Close[i+1])/2;
      ExtMapBufferHAC[i] = (Open[i]+High[i]+Low[i]+Close[i])/4;
     }
   for(int i=limit-1; i>=0; i--)
     {
      up = High[i]-High[i+1]; //up = change(high) 
      down = -(Low[i]-Low[i+1]); //down = -change(low)
      ExtMapBufferPDM[i] = !up ? NULL : (up > down && up > 0 ? up : 0); //+DM = na(up) ? na : (up > down and up > 0 ? up : 0)
      ExtMapBufferMDM[i] = !down ? NULL : (down > up && down > 0 ? down : 0);//-DM = na(down) ? na : (down > up and down > 0 ? down : 0)
      ExtMapBufferTR[i] = MathMax(High[i] - Low[i+1], MathMax(MathAbs(High[i] - ExtMapBufferHAC[i+1]), MathAbs(Low[i+1] - ExtMapBufferHAC[i+1])));// --tr definition for line 122
     } // -- line 94
   for(int i=limit-(2+ADXperiod); i>=0; i--)
     {
      trur = iMAOnArray(ExtMapBufferTR,0,ADXperiod,0,1,i);//trur = rma(tr, len) -- line 122
      ExtMapBufferPDI[i] = !(100*iMAOnArray(ExtMapBufferPDM,0,ADXperiod,0,1,i)/trur) ? ExtMapBufferPDI[i+1] : 100*iMAOnArray(ExtMapBufferPDM,0,ADXperiod,0,1,i)/trur;//plus = fixnan(100 * rma(plusDM, ADXperiod) / trur)
      ExtMapBufferNDI[i] = !(100*iMAOnArray(ExtMapBufferMDM,0,ADXperiod,0,1,i)/trur) ? ExtMapBufferNDI[i+1] : 100*iMAOnArray(ExtMapBufferMDM,0,ADXperiod,0,1,i)/trur;//minus = fixnan(100 * rma(minusDM, len) / trur)
      sum = ExtMapBufferPDI[i] + ExtMapBufferNDI[i] == 0.0 ? 1.0 : ExtMapBufferPDI[i] + ExtMapBufferNDI[i];//sum == 0 ? 1 : sum -- for line 127
      diff = MathAbs(ExtMapBufferPDI[i] - ExtMapBufferNDI[i]);//abs(plus - minus) -- for line 127
      ExtMapBufferDIratio[i] = diff / sum;//abs(plus - minus) / (sum == 0 ? 1 : sum) -- line 127 for line 131
     }
   for(int i=limit-(3+ADXperiod+ADXsmperiod); i>=0; i--)
     {
      ExtMapBufferADX[i] = 100*iMAOnArray(ExtMapBufferDIratio,0,ADXsmperiod,0,1,i);//adx = 100 * rma(abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen) -- line 131
     }
   //--- Debugging
   for(int i = 0;i<100;i++)
      {
      //Print(ExtMapBufferHAO[i],",",ExtMapBufferHAC[i],",",ExtMapBufferPDM[i],",",ExtMapBufferMDM[i],",",ExtMapBufferTR[i],",",ExtMapBufferPDI[i],",",ExtMapBufferNDI[i],",",ExtMapBufferDIratio[i],",",ExtMapBufferADX[i]);
      }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Any ideas on how to get this working? The indicator is the basis for a very profitable backtest in Tradingview and I will be happy to share the strategy with anyone who helps get this working...

Thanks to AnyDozer for various prompts / suggestions reflected above

1 Answers1

0

change all iMAOnArray() from MODE_EMA or 1 to MODE_SMMA or 2