ADX-and-DI/ADX_and_DI.mq5

319 lines
28 KiB
MQL5
Raw Permalink Normal View History

2026-02-21 21:15:26 -06:00
<EFBFBD><EFBFBD>//T%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%W%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%W% Q%
//Q% <EFBFBD>%<EFBFBD>%T%P%P%P%]%Z%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%P%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%P%]%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%T%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%T%P%P%]% <EFBFBD>%<EFBFBD>%T%<EFBFBD>%<EFBFBD>%W% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%P%P%]% <EFBFBD>%<EFBFBD>%T%P%P%<EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%<EFBFBD>%<EFBFBD>%Q%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% <EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%T%]% <EFBFBD>%<EFBFBD>%W%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%<EFBFBD>%<EFBFBD>%Q% <EFBFBD>%<EFBFBD>%Q%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%W%Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%<EFBFBD>%T%]%<EFBFBD>%<EFBFBD>%Q% Z%<EFBFBD>%<EFBFBD>%<EFBFBD>%Q% Q%
//Q% Z%P%P%P%P%P%]%Z%P%]% Z%P%]% Z%P%P%P%P%]% Z%P%P%P%P%P%]% Z%P%P%P%P%P%]%Z%P%]% Z%P%]% Z%P%P%P%P%]% Z%P%P%P%P%]% Z%P%]% Z%P%P%]% Q%
//Z%P%P%P%P%P%P%P% Algorithms that observe P%P%P%P% Signals that speak P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%P%]%
//+------------------------------------------------------------------+
//| R<EFBFBD>plica fiel del indicador "ADX and DI" de BeikabuOyaji |
//| TradingView Pine Script v4 <EFBFBD>! MQL5 |
//| Fuente: tradingview.com/script/VTPMMOrx-ADX-and-DI/ |
//| Licencia original: Mozilla Public License 2.0 |
//+------------------------------------------------------------------+
//| NOTAS T<EFBFBD>CNICAS: |
//| - Suavizado Wilder (<EFBFBD>=1/N) para TR, +DM, -DM <EFBFBD>! DI+, DI- |
//| - SMA simple (media aritm<EFBFBD>tica ventana deslizante) para ADX |
//| - Esta combinaci<EFBFBD>n h<EFBFBD>brida NO coincide con iADX (usa EMA) |
//| ni con iADXWilder (usa SMMA para el ADX final) |
//| - Inicializaci<EFBFBD>n desde 0 (replica nz() de Pine Script) |
//+------------------------------------------------------------------+
#property copyright "Exobeacon Labs"
#property link "https://www.exobeacon.com/"
#property version "1.0"
#property description "ADX and DI (by BeikabuOyaji) v1.1"
#property description "Exact replica of BeikabuOyaji's ADX and DI indicator."
#property description "Uses Wilder smoothing for DI and SMA for ADX."
#property description " "
#property description "0000000000((=<3D>}<7D>))0000000000"
#property description "=<3D><><EFBFBD> mql5.com/en/users/ulisescalb"
#property description "=<3D><><EFBFBD> github.com/Exobeacon-Labs"
#property strict
#property indicator_separate_window
#property indicator_buffers 7 // 3 visibles + 4 de c<EFBFBD>lculo interno
#property indicator_plots 3 // DI+, DI-, ADX
//--- Plot 0: DI+ (verde)
#property indicator_label1 "DI+"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrGreen
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- Plot 1: DI- (rojo)
#property indicator_label2 "DI-"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- Plot 2: ADX (azul marino)
#property indicator_label3 "ADX"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrNavy
#property indicator_style3 STYLE_SOLID
#property indicator_width3 2
//--- Nivel horizontal por defecto (se sobreescribe din<EFBFBD>micamente en OnInit)
#property indicator_level1 20
#property indicator_levelcolor clrBlack
#property indicator_levelstyle STYLE_SOLID
//+------------------------------------------------------------------+
//| Par<EFBFBD>metros de entrada |
//| len <EFBFBD>! InpPeriod (per<EFBFBD>odo de suavizado y SMA) |
//| th <EFBFBD>! InpThreshold (l<EFBFBD>nea horizontal de referencia) |
//+------------------------------------------------------------------+
input int InpPeriod = 14; // Per<EFBFBD>odo (len)
input int InpThreshold = 20; // Umbral horizontal (th)
//+------------------------------------------------------------------+
//| Buffers globales |
//+------------------------------------------------------------------+
//--- Buffers de datos (INDICATOR_DATA: visibles, accesibles v<EFBFBD>a CopyBuffer)
double DIPlusBuffer[]; // Buffer 0 <EFBFBD>! Plot 0: DI+
double DIMinusBuffer[]; // Buffer 1 <EFBFBD>! Plot 1: DI-
double ADXBuffer[]; // Buffer 2 <EFBFBD>! Plot 2: ADX
//--- Buffers de c<EFBFBD>lculo interno (INDICATOR_CALCULATIONS: no visibles)
double SmoothedTRBuffer[]; // Buffer 3: True Range suavizado (Wilder)
double SmoothedDMPlusBuffer[]; // Buffer 4: +DM suavizado (Wilder)
double SmoothedDMMinusBuffer[]; // Buffer 5: -DM suavizado (Wilder)
double DXBuffer[]; // Buffer 6: DX (entrada para SMA <EFBFBD>! ADX)
//+------------------------------------------------------------------+
//| Inicializaci<EFBFBD>n del indicador |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Validaci<EFBFBD>n de par<EFBFBD>metros
if(InpPeriod < 1)
{
PrintFormat("ADXandDI: Error - Per<00>odo (%d) debe ser >= 1", InpPeriod);
return(INIT_PARAMETERS_INCORRECT);
}
//--- Asignar buffers de datos (plots)
SetIndexBuffer(0, DIPlusBuffer, INDICATOR_DATA);
SetIndexBuffer(1, DIMinusBuffer, INDICATOR_DATA);
SetIndexBuffer(2, ADXBuffer, INDICATOR_DATA);
//--- Asignar buffers de c<EFBFBD>lculo interno
SetIndexBuffer(3, SmoothedTRBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(4, SmoothedDMPlusBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(5, SmoothedDMMinusBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(6, DXBuffer, INDICATOR_CALCULATIONS);
//--- Configurar inicio de dibujo
// DI+/DI- requieren al menos 1 barra previa (para close[i-1], high[i-1])
// pero el suavizado de Wilder necesita ~InpPeriod barras para converger
// ADX = SMA(DX, InpPeriod) necesita InpPeriod valores de DX adicionales
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriod); // DI+
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, InpPeriod); // DI-
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, InpPeriod * 2); // ADX
//--- Valor vac<EFBFBD>o para barras sin datos
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
//--- Configurar nivel horizontal seg<EFBFBD>n par<EFBFBD>metro th
IndicatorSetInteger(INDICATOR_LEVELS, 1);
IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, (double)InpThreshold);
IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, clrBlack);
IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, STYLE_SOLID);
//--- Precisi<EFBFBD>n de decimales mostrados
IndicatorSetInteger(INDICATOR_DIGITS, 2);
//--- Nombre corto
string short_name = "ADX and DI (" + IntegerToString(InpPeriod) + ")";
IndicatorSetString(INDICATOR_SHORTNAME, short_name);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Funci<EFBFBD>n principal de c<EFBFBD>lculo |
//| |
//| Algoritmo (r<EFBFBD>plica del Pine Script de BeikabuOyaji): |
//| |
//| 1. True Range = max(H-L, |H-C[1]|, |L-C[1]|) |
//| 2. +DM = (H-H[1] > L[1]-L) ? max(H-H[1], 0) : 0 |
//| -DM = (L[1]-L > H-H[1]) ? max(L[1]-L, 0) : 0 |
//| 3. Suavizado Wilder: |
//| S(i) = S(i-1) - S(i-1)/len + valor |
//| (equivale a running sum con decaimiento <EFBFBD>=1/N) |
//| 4. DI+ = SmoothedDM+ / SmoothedTR * 100 |
//| DI- = SmoothedDM- / SmoothedTR * 100 |
//| 5. DX = |DI+ - DI-| / (DI+ + DI-) * 100 |
//| 6. ADX = SMA(DX, len) <EFBFBD>! <EFBFBD>SMA simple, NO Wilder/SMMA! |
//+------------------------------------------------------------------+
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[])
{
//--- Verificar datos m<EFBFBD>nimos (necesitamos al menos 2 barras)
if(rates_total < 2)
return(0);
int start;
//=================================================================
// FASE 1: True Range, Movimiento Direccional, Suavizado Wilder,
// DI+, DI-, DX
//=================================================================
if(prev_calculated == 0)
{
//--- Primera ejecuci<EFBFBD>n completa: inicializar barra 0
// Pine Script nz() retorna 0 para valores inexistentes,
// as<EFBFBD> que los buffers suavizados empiezan desde 0
SmoothedTRBuffer[0] = 0.0;
SmoothedDMPlusBuffer[0] = 0.0;
SmoothedDMMinusBuffer[0] = 0.0;
DIPlusBuffer[0] = 0.0;
DIMinusBuffer[0] = 0.0;
DXBuffer[0] = 0.0;
ADXBuffer[0] = EMPTY_VALUE;
start = 1;
}
else
{
//--- Recalcular solo la <EFBFBD>ltima barra (o desde donde se qued<EFBFBD>)
start = prev_calculated - 1;
}
//--- Bucle principal: indexaci<EFBFBD>n de izquierda a derecha (0 = m<EFBFBD>s antigua)
for(int i = start; i < rates_total && !IsStopped(); i++)
{
//-------------------------------------------------------
// 1. True Range: max(H-L, |H-C<EFBFBD> <EFBFBD> |, |L-C<EFBFBD> <EFBFBD> |)
// Replica: max(max(high-low, abs(high-nz(close[1]))), abs(low-nz(close[1])))
//-------------------------------------------------------
double prev_close = close[i - 1];
double tr = MathMax(MathMax(high[i] - low[i],
MathAbs(high[i] - prev_close)),
MathAbs(low[i] - prev_close));
//-------------------------------------------------------
// 2. Movimiento Direccional (+DM, -DM)
// Regla de exclusividad mutua de Wilder:
// Solo el mayor movimiento (si es positivo) se cuenta
//-------------------------------------------------------
double up_move = high[i] - high[i - 1]; // UpMove
double down_move = low[i - 1] - low[i]; // DownMove
double dm_plus, dm_minus;
if(up_move > down_move && up_move > 0.0)
dm_plus = up_move;
else
dm_plus = 0.0;
if(down_move > up_move && down_move > 0.0)
dm_minus = down_move;
else
dm_minus = 0.0;
//-------------------------------------------------------
// 3. Suavizado de Wilder (forma running sum)
// S(i) = S(i-1) - S(i-1)/len + valor
// Equivalente a: S(i) = S(i-1) * (1 - 1/len) + valor
//-------------------------------------------------------
double prev_str = SmoothedTRBuffer[i - 1];
double prev_sdmp = SmoothedDMPlusBuffer[i - 1];
double prev_sdmm = SmoothedDMMinusBuffer[i - 1];
SmoothedTRBuffer[i] = prev_str - prev_str / InpPeriod + tr;
SmoothedDMPlusBuffer[i] = prev_sdmp - prev_sdmp / InpPeriod + dm_plus;
SmoothedDMMinusBuffer[i] = prev_sdmm - prev_sdmm / InpPeriod + dm_minus;
//-------------------------------------------------------
// 4. DI+ y DI- (en porcentaje)
// DI+ = SmoothedDM+ / SmoothedTR * 100
// DI- = SmoothedDM- / SmoothedTR * 100
//-------------------------------------------------------
double smoothed_tr = SmoothedTRBuffer[i];
if(smoothed_tr > 0.0)
{
DIPlusBuffer[i] = SmoothedDMPlusBuffer[i] / smoothed_tr * 100.0;
DIMinusBuffer[i] = SmoothedDMMinusBuffer[i] / smoothed_tr * 100.0;
}
else
{
DIPlusBuffer[i] = 0.0;
DIMinusBuffer[i] = 0.0;
}
//-------------------------------------------------------
// 5. DX = |DI+ - DI-| / (DI+ + DI-) * 100
//-------------------------------------------------------
double di_sum = DIPlusBuffer[i] + DIMinusBuffer[i];
if(di_sum > 0.0)
DXBuffer[i] = MathAbs(DIPlusBuffer[i] - DIMinusBuffer[i]) / di_sum * 100.0;
else
DXBuffer[i] = 0.0;
}
//=================================================================
// FASE 2: ADX = SMA(DX, len)
// Media aritm<EFBFBD>tica simple de ventana deslizante sobre DX
// <EFBFBD>CR<EFBFBD>TICO: es SMA, NO Wilder/SMMA/RMA!
//=================================================================
int adx_first_bar = InpPeriod; // Primera barra con ADX v<EFBFBD>lido
// (necesita InpPeriod valores de DX: barras 1..InpPeriod)
int adx_start;
if(prev_calculated == 0)
{
//--- Marcar todas las barras sin ADX v<EFBFBD>lido
for(int i = 0; i < MathMin(adx_first_bar, rates_total); i++)
ADXBuffer[i] = EMPTY_VALUE;
//--- Verificar que hay suficientes barras para calcular el primer SMA
if(rates_total <= adx_first_bar)
return(rates_total);
//--- Calcular el primer valor de ADX como SMA de DX[1..InpPeriod]
// DX es v<EFBFBD>lido desde barra 1 (primera barra que tiene barra previa)
// Pine Script sma(DX, len) en la barra InpPeriod toma las barras
// [InpPeriod-len+1 .. InpPeriod] = [1 .. InpPeriod]
double sum = 0.0;
for(int j = 1; j <= InpPeriod; j++)
sum += DXBuffer[j];
ADXBuffer[adx_first_bar] = sum / InpPeriod;
adx_start = adx_first_bar + 1;
}
else
{
adx_start = MathMax(prev_calculated - 1, adx_first_bar + 1);
}
//--- Calcular SMA incremental para las barras restantes
// SMA(i) = SMA(i-1) + (DX[i] - DX[i-InpPeriod]) / InpPeriod
// Esto es algebraicamente equivalente a sumar los <EFBFBD>ltimos InpPeriod
// valores de DX y dividir entre InpPeriod, pero es O(1) por barra
for(int i = adx_start; i < rates_total && !IsStopped(); i++)
{
double new_val = DXBuffer[i];
double old_val = DXBuffer[i - InpPeriod];
ADXBuffer[i] = ADXBuffer[i - 1] + (new_val - old_val) / InpPeriod;
}
return(rates_total);
}
//+------------------------------------------------------------------+