将 DMI 从 Tradingview 移植到 MQL4 中修订的 ADX - 未给出等效结果

问题描述

TradingView 在所使用的柱上计算其 DMI(相当于 MT4 ADX),即当您选择 Heiken Ashi 柱作为价格显示时,ADX 计算的开盘和收盘值是修改后的 HA 值。此外,他们的 DMI 需要一个额外的输入,即一个平滑周期,通过该周期平滑 ADX 线,如果设置为 1,则将保持不变的传统 ADX 线作为 MetaTrader。

他们的 DMI 代码是免费提供的。我试图在下面引用的脚本中复制他们的 DMI 在 Heiken Ashi Bars 上的使用。

MetaTrader 和 Tradingview 之间的情节非常不同(见图片)。

Trading View

Metatrader

为了清晰起见,我整理了代码添加了原始 PINE 脚本。

相关行号在注释中,其中也包含原始 PINE 代码中的行。

//+------------------------------------------------------------------+
//|                                                SmoothedHAADX.mq4 |
//|                               copyright 2021,[email protected] |
//|                                      mailto://[email protected] |
//+------------------------------------------------------------------+
//---- 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),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 protected]"
#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,ADXperiod,1,i);//trur = rma(tr,len) -- line 122
      ExtMapBufferPDI[i] = !(100*iMAOnArray(ExtMapBufferPDM,i)/trur) ? ExtMapBufferPDI[i+1] : 100*iMAOnArray(ExtMapBufferPDM,i)/trur;//plus = fixnan(100 * rma(plusDM,ADXperiod) / trur)
      ExtMapBufferNDI[i] = !(100*iMAOnArray(ExtMapBufferMDM,i)/trur) ? ExtMapBufferNDI[i+1] : 100*iMAOnArray(ExtMapBufferMDM,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,ADXsmperiod,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);
  }
//+------------------------------------------------------------------+

有关如何使其工作的任何想法?该指标是 Tradingview 中非常有利可图的回测的基础,我很乐意与任何帮助实现此目标的人分享该策略...

感谢 AnyDozer 提供上述反映的各种提示/建议

解决方法

将所有 iMAOnArray() 从 MODE_EMA 或 1 更改为 MODE_SMMA 或 2