Porting DMI from Tradingview into revised ADX in MQL4 - not giving equivalent result

Porting DMI from Tradingview into revised ADX in MQL4 - not giving equivalent result

Manage alerts

Loading saved threads...

Andy Thompson · External communityPost link
External question — Stack Overflow Stack Exchange Author: Andy Thompson Original post: https://stackoverflow.com/questions/66337390 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. 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). 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, [email removed] | //| mailto://[email removed] | //+------------------------------------------------------------------+ //---- 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://[email removed]" #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
Quote
Report
moh irwan · External communityPost link
External answer — Stack Overflow Stack Exchange Author: moh irwan Original post: https://stackoverflow.com/a/68645662 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. change all iMAOnArray() from MODE_EMA or 1 to MODE_SMMA or 2
Quote
Report

Post Reply

Quoted from Forex.com.bd-Editorial External question — Stack Overflow Stack Exchange Author: Andy Thompson Source score (net votes, not local likes): 0 Original post: https://stackoverflow.com/questions/66337390 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. 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). 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, [email removed] | //| mailto://[email removed] | //+------------------------------------------------------------------+ //---- 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://[email removed]" #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

Cancel quote

Checking account access…