// Band indicators and volume-weighted averaging.

///|
/// Bollinger Bands: upper / middle / lower arrays of equal length. Produced
/// by `bbands`; fields are readable everywhere but the struct is only
/// constructed inside this package.
pub struct BBands {
  upper : Array[Double]
  middle : Array[Double]
  lower : Array[Double]
}

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

///|
/// Bollinger Bands over `data` with a moving window of `period` values and
/// `ndev` standard deviations (population stddev, TA-Lib convention).
/// A NaN inside a window makes all three outputs NaN at that position.
pub fn bbands(
  data : Array[Double],
  period : Int32,
  ndev~ : Double,
) -> BBands raise @base.TaError {
  @base.validate_series(data, period)
  let n = data.length()
  let pd = period.to_double()
  let upper : Array[Double] = []
  let middle : Array[Double] = []
  let lower : Array[Double] = []
  for i in 0.. Array[Double] raise @base.TaError {
  @base.validate_series(price, period)
  if volume.length() != price.length() {
    raise @base.MismatchedLength("price and volume must have equal lengths")
  }
  let n = price.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.. hh {
          hh = h
        }
        if l < ll {
          ll = l
        }
      }
    }
    if valid {
      out.push((hh + ll) / 2.0)
    } else {
      out.push(@base.nan())
    }
  }
  out
}