calculate method
Pure computation function that produces an IndicatorResult from candles.
Implementation
@override
IndicatorResult calculate(List<Candle> candles) {
final macdValues = List<double?>.filled(candles.length, null);
final signalValues = List<double?>.filled(candles.length, null);
final histValues = List<double?>.filled(candles.length, null);
if (candles.length < slowPeriod) {
return IndicatorResult(
indicatorId: id,
name: name,
isOverlay: false,
series: [
IndicatorSeries(
id: 'histogram',
label: 'Hist',
color: const Color(0xFF00E676),
values: histValues,
),
IndicatorSeries(
id: 'macd',
label: 'MACD',
color: macdColor,
strokeWidth: 1.5,
values: macdValues,
),
IndicatorSeries(
id: 'signal',
label: 'Signal',
color: signalColor,
strokeWidth: 1.5,
values: signalValues,
),
],
horizontalLevels: const [0.0],
);
}
// 1. Calculate Fast EMA (12) and Slow EMA (26)
final fastEma = _calculateEmaSeries(candles, fastPeriod);
final slowEma = _calculateEmaSeries(candles, slowPeriod);
// 2. Calculate MACD Line = Fast EMA - Slow EMA
for (int i = 0; i < candles.length; i++) {
if (fastEma[i] != null && slowEma[i] != null) {
macdValues[i] = fastEma[i]! - slowEma[i]!;
}
}
// 3. Calculate Signal Line = EMA (9) of MACD Line
// First find start index of non-null MACD values
int macdStartIndex = -1;
for (int i = 0; i < candles.length; i++) {
if (macdValues[i] != null) {
macdStartIndex = i;
break;
}
}
if (macdStartIndex != -1 &&
(candles.length - macdStartIndex) >= signalPeriod) {
// SMA of first signalPeriod valid MACD values
double sum = 0.0;
for (int i = macdStartIndex; i < macdStartIndex + signalPeriod; i++) {
sum += macdValues[i]!;
}
double currentSignal = sum / signalPeriod;
signalValues[macdStartIndex + signalPeriod - 1] = currentSignal;
final k = 2.0 / (signalPeriod + 1);
for (int i = macdStartIndex + signalPeriod; i < candles.length; i++) {
if (macdValues[i] != null) {
currentSignal = (macdValues[i]! * k) + (currentSignal * (1 - k));
signalValues[i] = currentSignal;
}
}
}
// 4. Calculate Histogram = MACD - Signal
for (int i = 0; i < candles.length; i++) {
if (macdValues[i] != null && signalValues[i] != null) {
histValues[i] = macdValues[i]! - signalValues[i]!;
}
}
return IndicatorResult(
indicatorId: id,
name: name,
isOverlay: false,
series: [
IndicatorSeries(
id: 'histogram',
label: 'Histogram',
color: const Color(0xFF00E676),
values: histValues,
),
IndicatorSeries(
id: 'macd',
label: 'MACD',
color: macdColor,
strokeWidth: 1.5,
values: macdValues,
),
IndicatorSeries(
id: 'signal',
label: 'Signal',
color: signalColor,
strokeWidth: 1.5,
values: signalValues,
),
],
horizontalLevels: const [0.0],
);
}