/**
* Weighted n-point moving average (WMA)
*
* Similar to simple n-point moving average,
* however, each n-point has a weight associated with it,
* and instead of dividing by n, we divide by the sum of the weights.
*
* Each weighted average = ∑(weighted values) / ∑(weights)
*
* @param array $numbers
* @param int $n n-point moving average
* @param array $weights Weights for each n points
*
* @return array of averages
*
* @throws BadDataException if number of weights is not equal to number of n-points
*/
public static function weightedMovingAverage(array $numbers, int $n, array $weights) : array
{
if (count($weights) !== $n) {
throw new Exception\BadDataException('Number of weights must equal number of n-points');
}
$m = count($numbers);
$∑w = array_sum($weights);
$WMA = [];
for ($i = 0; $i <= $m - $n; $i++) {
$∑wp = array_sum(Map\Multi::multiply(array_slice($numbers, $i, $n), $weights));
$WMA[] = $∑wp / $∑w;
}
return $WMA;
}