// Commodity Channel Index and TRIX.

///|
/// Number of leading NaN values produced by `cci` for the given period.
pub fn cci_lookback(period : Int32) -> Int32 {
  period - 1
}

///|
/// Commodity Channel Index (Donald Lambert): the deviation of the typical
/// price `(high + low + close) / 3` from its SMA, normalized by
/// `0.015 * mean absolute deviation`. A flat window (mean deviation 0) reads
/// 0.
pub fn cci(
  candles : @base.Candles,
  period : Int32,
) -> Array[Double] raise @base.TaError {
  @base.validate_candles(candles)
  if period <= 0 {
    raise @base.InvalidPeriod("period must be positive, got \{period}")
  }
  let n = candles.close.length()
  let tp : Array[Double] = []
  for i in 0.. Int32 {
  3 * (period - 1) + 1
}

///|
/// TRIX: the percent rate of change of a triple-EMA,
/// `100 * (e3[i] - e3[i - 1]) / e3[i - 1]`.
pub fn trix(
  data : Array[Double],
  period : Int32,
) -> Array[Double] raise @base.TaError {
  @base.validate_series(data, period)
  let e1 = @overlap.ema_from(data, period, 0)
  let e2 = @overlap.ema_from(e1, period, period - 1)
  let e3 = @overlap.ema_from(e2, period, 2 * (period - 1))
  let n = data.length()
  let out : Array[Double] = []
  for i in 0..