// Rate-of-change family: ROC, MOM, CMO, APO and PPO.

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

///|
/// Rate of change in percent: `100 * (x[i] - x[i - period]) / x[i - period]`.
/// A zero base value yields NaN.
pub fn roc(
  data : Array[Double],
  period : Int32,
) -> Array[Double] raise @base.TaError {
  @base.validate_series(data, period)
  let n = data.length()
  let out : Array[Double] = []
  for i in 0.. Int32 {
  period
}

///|
/// Momentum: `x[i] - x[i - period]`. NaN inputs yield NaN.
pub fn mom(
  data : Array[Double],
  period : Int32,
) -> Array[Double] raise @base.TaError {
  @base.validate_series(data, period)
  let n = data.length()
  let out : Array[Double] = []
  for i in 0.. Int32 {
  period
}

///|
/// Chande Momentum Oscillator:
/// `100 * (sum_up - sum_down) / (sum_up + sum_down)` over the last `period`
/// price changes. A completely flat window reads 0.
pub fn cmo(
  data : Array[Double],
  period : Int32,
) -> Array[Double] raise @base.TaError {
  @base.validate_series(data, period)
  let n = data.length()
  // Signed per-bar changes split into up/down series; each window then only
  // reads two O(n) rolling sums.
  let ups : Array[Double] = []
  let downs : Array[Double] = []
  ups.push(@base.nan())
  downs.push(@base.nan())
  for j in 1.. 0.0 {
      ups.push(d)
      downs.push(0.0)
    } else {
      ups.push(0.0)
      downs.push(-d)
    }
  }
  let sum_up = @base.rolling_sum(ups, period)
  let sum_down = @base.rolling_sum(downs, period)
  let out : Array[Double] = []
  for i in 0.. Array[Double] raise @base.TaError {
  @base.validate_series(data, slow_period)
  if fast_period <= 0 || slow_period <= 0 {
    raise @base.InvalidPeriod("all periods must be positive")
  }
  if fast_period >= slow_period {
    raise @base.InvalidPeriod("fast_period must be smaller than slow_period")
  }
  let fast_ma = @overlap.moving_average(data, fast_period, ma_type~)
  let slow_ma = @overlap.moving_average(data, slow_period, ma_type~)
  let n = data.length()
  let out : Array[Double] = []
  for i in 0.. Array[Double] raise @base.TaError {
  @base.validate_series(data, slow_period)
  if fast_period <= 0 || slow_period <= 0 {
    raise @base.InvalidPeriod("all periods must be positive")
  }
  if fast_period >= slow_period {
    raise @base.InvalidPeriod("fast_period must be smaller than slow_period")
  }
  let fast_ma = @overlap.moving_average(data, fast_period, ma_type~)
  let slow_ma = @overlap.moving_average(data, slow_period, ma_type~)
  let n = data.length()
  let out : Array[Double] = []
  for i in 0.. Array[Double] raise @base.TaError {
  @base.validate_candles(candles)
  let n = candles.close.length()
  let out : Array[Double] = []
  for i in 0..