- Code: Select all
TR = MAX(PREVIOUS CLOSE, CURRENT HIGH) - MIN(PREVIOUS CLOSE, CURRENT LOW)
PLUSDM = IF ((CURRENT HIGH > PREVIOUS HIGH AND CURRENT LOW >= PREVIOUS LOW) OR
(CURRENT HIGH > PREVIOUS HIGH AND CURRENT LOW < PREVIOUS LOW AND
CURRENT HIGH - PREVIOUS HIGH < PREVIOUS LOW - CURRENT LOW)
THEN
CURRENT HIGH - PREVIOUS HIGH
ELSE
0
MINUSDM = IF ((CURRENT HIGH <= PREVIOUS HIGH AND CURRENT LOW < PREVIOUS LOW) OR
(CURRENT HIGH > PREVIOUS HIGH AND CURRENT LOW < PREVIOUS LOW AND
CURRENT HIGH - PREVIOUS HIGH < PREVIOUS LOW - CURRENT LOW)
THEN
PREVIOUS LOW - CURRENT LOW
ELSE
0
PLUSDI = 100 * WMA(PLUSDM, N1) / WMA(TR, N1)
MINUSDI = 100 * WMA(MINUSDM, N1) / WMA(TR, N1)
ADX = 100 * WMA((PLUSDI - MINUSDI) / (PLUSDI + MINUSDI), N2)
where WMA is Wilders Moving Average.
Compare the view of the standard ADX and VT-version of the ADX on the snapshot below:
The VT-like version of the ADX is below:
Please, do not forget to download and install WMA.lua (Wilders Moving Average). This indicator is used by VTADX and, therefore, is required to be installed.
- Code: Select all
-- Indicator profile initialization routine
-- Defines indicator profile properties and indicator parameters
function Init()
indicator:name("Average Directional Movement Index (VTTrader version)");
indicator:description("");
indicator:requiredSource(core.Bar);
indicator:type(core.Oscillator);
indicator.parameters:addInteger("SM1", "Smoothing periods 1", "No description", 14, 1, 100);
indicator.parameters:addInteger("SM2", "Smoothing periods 2", "No description", 14, 1, 100);
indicator.parameters:addColor("ADX_color", "Color of ADX", "Color of ADX", core.rgb(255, 0, 0));
end
-- Indicator instance initialization routine
-- Processes indicator parameters and creates output streams
-- Parameters block
local SM1;
local SM2;
local first;
local firstTR;
local firstDI;
local source = nil;
-- Streams block
local TR = nil;
local TR_W = nil;
local PlusDM = nil;
local PlusDM_W = nil;
local PlusDI = nil;
local MinusDM = nil;
local MinusDM_W = nil;
local MinusDI = nil;
local R = nil;
local R_W = nil;
local ADX = nil;
local H, L, C;
-- Routine
function Prepare()
SM1 = instance.parameters.SM1;
SM2 = instance.parameters.SM2;
source = instance.source;
firstTR = source:first() + 1;
H = source.high;
L = source.low;
C = source.close;
TR = instance:addInternalStream(firstTR, 0);
PlusDM = instance:addInternalStream(firstTR, 0);
MinusDM = instance:addInternalStream(firstTR, 0);
TR_W = core.indicators:create("WMA", TR, SM1);
PlusDM_W = core.indicators:create("WMA", PlusDM, SM1);
MinusDM_W = core.indicators:create("WMA", MinusDM, SM1);
firstDI = TR_W.DATA:first();
PlusDI = instance:addInternalStream(firstDI, 0);
MinusDI = instance:addInternalStream(firstDI, 0);
R = instance:addInternalStream(firstDI, 0);
R_W = core.indicators:create("WMA", R, SM2);
first = R_W.DATA:first();
local name = profile:id() .. "(" .. source:name() .. ", " .. SM1 .. ", " .. SM2 .. ")";
instance:name(name);
ADX = instance:addStream("ADX", core.Line, name, "ADX", instance.parameters.ADX_color, first);
ADX:addLevel(20);
end
-- Indicator calculation routine
function Update(p, mode)
if p >= firstTR then
local th, tl;
if C[p - 1] > H[p] then
th = C[p - 1];
else
th = H[p];
end
if C[p - 1] < L[p] then
tl = C[p - 1];
else
tl = L[p];
end
TR[p] = th - tl;
if H[p] > H[p - 1] and L[p] >= L[p - 1] then
PlusDM[p] = H[p] - H[p - 1];
elseif H[p] > H[p - 1] and L[p] < L[p - 1] and ((H[p] - H[p - 1]) > (L[p - 1] - L[p])) then
PlusDM[p] = H[p] - H[p - 1];
else
PlusDM[p] = 0;
end
if L[p] < L[p - 1] and H[p] <= H[p - 1] then
MinusDM[p] = L[p - 1] - L[p];
elseif L[p] < L[p - 1] and H[p] > H[p - 1] and ((H[p] - H[p - 1]) < (L[p - 1] - L[p])) then
MinusDM[p] = L[p - 1] - L[p];
else
MinusDM[p] = 0;
end
end
TR_W:update(mode);
PlusDM_W:update(mode);
MinusDM_W:update(mode);
if p >= firstDI then
PlusDI[p] = 100 * PlusDM_W.DATA[p] / TR_W.DATA[p]
MinusDI[p] = 100 * MinusDM_W.DATA[p] / TR_W.DATA[p]
local diff, sum;
diff = math.abs(PlusDI[p] - MinusDI[p]);
summ = PlusDI[p] + MinusDI[p];
R[p] = diff / summ;
end
R_W:update(mode);
if p >= first then
ADX[p] = 100 * R_W.DATA[p];
end
end
The indicator was revised and updated