calculate method
Pure computation function that produces an IndicatorResult from candles.
Implementation
@override
IndicatorResult calculate(List<Candle> candles) {
final n = candles.length;
final adx = List<double?>.filled(n, null);
final plusDI = List<double?>.filled(n, null);
final minusDI = List<double?>.filled(n, null);
if (n < period + 1) {
return _result(adx, plusDI, minusDI);
}
// Calculate True Range, +DM, -DM
final tr = List<double>.filled(n, 0);
final pdm = List<double>.filled(n, 0);
final mdm = List<double>.filled(n, 0);
for (int i = 1; i < n; i++) {
final high = candles[i].high;
final low = candles[i].low;
final prevClose = candles[i - 1].close;
final prevHigh = candles[i - 1].high;
final prevLow = candles[i - 1].low;
tr[i] = [high - low, (high - prevClose).abs(), (low - prevClose).abs()].reduce((a, b) => a > b ? a : b);
final upMove = high - prevHigh;
final downMove = prevLow - low;
pdm[i] = (upMove > downMove && upMove > 0) ? upMove : 0;
mdm[i] = (downMove > upMove && downMove > 0) ? downMove : 0;
}
// Smoothed (Wilder's) sums
double atr = 0, aPdm = 0, aMdm = 0;
for (int i = 1; i <= period; i++) {
atr += tr[i]; aPdm += pdm[i]; aMdm += mdm[i];
}
double adxSum = 0;
int adxCount = 0;
for (int i = period; i < n; i++) {
if (i > period) {
atr = atr - (atr / period) + tr[i];
aPdm = aPdm - (aPdm / period) + pdm[i];
aMdm = aMdm - (aMdm / period) + mdm[i];
}
final pdi = atr > 0 ? (100.0 * aPdm / atr) : 0.0;
final mdi = atr > 0 ? (100.0 * aMdm / atr) : 0.0;
plusDI[i] = pdi;
minusDI[i] = mdi;
final diSum = pdi + mdi;
final dx = diSum > 0 ? (100.0 * (pdi - mdi).abs() / diSum) : 0.0;
adxSum += dx;
adxCount++;
if (adxCount >= period) {
adx[i] = adxCount == period
? adxSum / period
: ((adx[i - 1] ?? 0) * (period - 1) + dx) / period;
}
}
return _result(adx, plusDI, minusDI);
}