calculate method

  1. @override
IndicatorResult calculate(
  1. List<Candle> candles
)
override

Pure computation function that produces an IndicatorResult from candles.

Implementation

@override
IndicatorResult calculate(List<Candle> candles) {
  final values = List<double?>.filled(candles.length, null);

  if (candles.length < period) {
    return IndicatorResult(
      indicatorId: id,
      name: name,
      isOverlay: false,
      series: [
        IndicatorSeries(
          id: 'cci',
          label: name,
          color: color,
          strokeWidth: strokeWidth,
          values: values,
        ),
      ],
      horizontalLevels: const [-100.0, 0.0, 100.0],
    );
  }

  // 1. Calculate Typical Price (TP) for all candles
  final tp = List<double>.generate(
    candles.length,
    (i) => (candles[i].high + candles[i].low + candles[i].close) / 3.0,
  );

  // 2. Compute CCI for each window
  for (int i = period - 1; i < candles.length; i++) {
    double sumTp = 0.0;
    for (int j = i - period + 1; j <= i; j++) {
      sumTp += tp[j];
    }
    final smaTp = sumTp / period;

    double sumDev = 0.0;
    for (int j = i - period + 1; j <= i; j++) {
      sumDev += (tp[j] - smaTp).abs();
    }
    final meanDev = sumDev / period;

    if (meanDev == 0.0) {
      values[i] = 0.0;
    } else {
      values[i] = (tp[i] - smaTp) / (0.015 * meanDev);
    }
  }

  return IndicatorResult(
    indicatorId: id,
    name: name,
    isOverlay: false,
    series: [
      IndicatorSeries(
        id: 'cci',
        label: name,
        color: color,
        strokeWidth: strokeWidth,
        values: values,
      ),
    ],
    horizontalLevels: const [-100.0, 0.0, 100.0],
  );
}