diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/Brown.php b/Math/Finance/Forecasting/ExponentialSmoothing/Brown.php deleted file mode 100644 index 372e0ba41..000000000 --- a/Math/Finance/Forecasting/ExponentialSmoothing/Brown.php +++ /dev/null @@ -1,238 +0,0 @@ - - * @author Dennis Eichhorn - * @copyright 2013 Dennis Eichhorn - * @license OMS License 1.0 - * @version 1.0.0 - * @link http://orange-management.com - */ - namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; - -use phpOMS\Math\Finance\Forecasting\SmoothingType; -use phpOMS\Math\Statistic\Average; -use phpOMS\Math\Statistic\Forecast\Error; - -class Brown implements ExponentialSmoothingInterface -{ - private $data = []; - - private $errors = []; - - private $cycle = 0; - - private $type = ForecastType::LINEAR; - - private $rmse = 0.0; - - private $mse = 0.0; - - private $mae = 0.0; - - private $sse = 0.0; - - public function __construct(array $data, int $cycle = 0, int $type = ForecastType::LINEAR) - { - $this->data = $data; - $this->type = $type; - } - - public function setCycle(int $cycle) /* : void */ - { - $this->cycle = $cycle; - } - - public function getRMSE() : float - { - return $this->rmse; - } - - public function getMSE() : float - { - return $this->mse; - } - - public function getMAE() : float - { - return $this->mae; - } - - public function getSSE() : float - { - return $this->sse; - } - - public function getErrors() : array - { - return $this->errors; - } - - public function getForecast(int $future = 1, int $smoothing = SmoothingType::CENTERED_MOVING_AVERAGE) : array - { - $trendCycle = $this->getTrendCycle($this->cycle, $smoothing); - $seasonality = $this->getSeasonality($trendCycle); - $seasonalityIndexMap = $this->generateSeasonalityMap($this->cycle, $seasonality); - $adjustedSeasonalityIndexMap = $this->generateAdjustedSeasonalityMap($this->cycle, $seasonalityIndexMap); - $adjustedData = $this->getAdjustedData($this->cycle, $adjustedSeasonalityIndexMap); - $optimizedForecast = $this->getOptimizedForecast($future, $adjustedData); - - return $this->getReseasonalized($this->cycle, $optimizedForecast, $adjustedSeasonalityIndexMap); - } - - private function getTrendCycle(int $cycle, int $smoothing) : array - { - $centeredMovingAverage = []; - - $length = count($this->data); - for ($i = $cycle; $i < $length - $cycle; $i++) { - $centeredMovingAverage[$i] = Average::arithmeticMean(array_slice($this->data, $i - $cycle, $cycle)); - } - - return $centeredMovingAverage; - } - - private function getSeasonality(array $trendCycle) : array - { - $seasonality = []; - foreach ($trendCycle as $key => $value) { - $seasonality[$key] = $this->data[$key] / $value; - } - - return $seasonality; - } - - private function generateSeasonalityMap(int $cycle, array $seasonality) : array - { - $map = []; - foreach ($seasonality as $key => $value) { - $map[$key % $cycle][] = $value; - } - - foreach ($map as $key => $value) { - $map[$key] = Average::arithmeticMean($value); - } - - return $map; - } - - private function generateAdjustedSeasonalityMap(int $cycle, array $seasonality) : array - { - $total = array_sum($seasonality); - - foreach ($seasonality as $key => $value) { - $seasonality[$key] = $cycle * $value / $total; - } - - return $seasonality; - } - - private function getSeasonalIndex(int $cycle, array $seasonalityMap) : array - { - $index = []; - - foreach ($this->data as $key => $value) { - $index[$key] = $seasonalityMap[$key % $cycle]; - } - - return $index; - } - - private function getAdjustedData(int $cycle, array $seasonalIndex) : array - { - $adjusted = []; - - foreach ($this->data as $key => $value) { - $adjusted[$key] = $value / ($seasonalIndex[$key % $cycle] === 0 ? 1 : $seasonalIndex[$key % $cycle]); - } - - return $adjusted; - } - - private function forecastLinear(int $future, float $alpha, array $data, array &$error) : array - { - $forecast = []; - $dataLength = count($data); - $length = $dataLength + $future; - - $forecast[0] = $data[0]; - $forecast[1] = $data[1]; - - $error[0] = 0; - $error[1] = $data[1] - $forecast[1]; - - for ($i = 2; $i < $length; $i++) { - $forecast[$i] = 2 * ($data[$i - 1] ?? $forecast[$i - 1]) - ($data[$i - 2] ?? $forecast[$i - 2]) - 2 * (1 - $alpha) * $error[$i - 1] + pow(1 - $alpha, 2) * $error[$i - 2]; - $error[$i] = $i < $dataLength ? $data[$i] - $forecast[$i] : 0; - } - - return $forecast; - } - - private function forecastSimple(int $future, float $alpha, array $data, array &$error) : array - { - $forecast = []; - $dataLength = count($data); - $length = $dataLength + $future; - - $forecast[0] = $data[0]; - - $error[0] = 0; - - for ($i = 1; $i < $length; $i++) { - $forecast[$i] = $alpha * $data[$i-1] + (1-$alpha)*$forecast[$i-1]; - $error[$i] = $i < $dataLength ? $data[$i] - $forecast[$i] : 0; - } - - return $forecast; - } - - private function getOptimizedForecast(int $future, array $adjustedDatae) : array - { - $this->rmse = PHP_INT_MAX; - $alpha = 0.00; - $forecast = []; - - while ($alpha < 1) { - $error = []; - - if($this->type === ForecastType::LINEAR) { - $tempForecast = $this->forecastLinear($future, $alpha, $adjustedData, $error); - } else { - $tempForecast = $this->forecastSimple($future, $alpha, $adjustedData, $error); - } - - $alpha += 0.001; - - $tempRMSE = Error::getRootMeanSquaredError($error); - - if ($tempRMSE < $this->rmse) { - $this->rmse = $tempRMSE; - $forecast = $tempForecast; - } - } - - $this->errors = $error; - $this->mse = Error::getMeanSquaredError($error); - $this->mae = Error::getMeanAbsoulteError($error); - $this->sse = Error::getSumSquaredError($error); - - return $forecast; - } - - private function getReseasonalized(int $cycle, array $forecast, array $seasonalIndex) : array - { - $reSeasonalized = []; - - foreach ($forecast as $key => $value) { - $reSeasonalized[$key] = $value * ($seasonalIndex[$key % $cycle] === 0 ? 1 : $seasonalIndex[$key % $cycle]); - } - - return $reSeasonalized; - } -} diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php b/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php new file mode 100644 index 000000000..42be7c514 --- /dev/null +++ b/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php @@ -0,0 +1,285 @@ +@@ -1,265 +0,0 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ + namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; + +use phpOMS\Math\Finance\Forecasting\SmoothingType; +use phpOMS\Math\Statistic\Average; +use phpOMS\Math\Statistic\Forecast\Error; + +class Holt implements ExponentialSmoothingInterface +{ + private $data = []; + + private $errors = []; + + private $rmse = 0.0; + + private $mse = 0.0; + + private $mae = 0.0; + + private $sse = 0.0; + + public function __construct(array $data) + { + $this->data = $data; + } + + public function getRMSE() : float + { + return $this->rmse; + } + + public function getMSE() : float + { + return $this->mse; + } + + public function getMAE() : float + { + return $this->mae; + } + + public function getSSE() : float + { + return $this->sse; + } + + public function getErrors() : array + { + return $this->errors; + } + + public function forecast(int $future, int $trendType = TrendType::NONE, int $seasonalType = SeasonalType::NONE, int $cycle = 12, float $damping = 1) : array + { + if($trendType === TrendType::ALL || $seasonalType === SeasonalType::ALL) { + // todo: loob through all and find best + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::NONE) { + return $this->getNoneNone($future, $alpha); + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::ADDITIVE) { + return $this->getNoneAdditive($future, $alpha, $gamma, $cycle); + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::MULTIPLICATIVE) { + return $this->getNoneMultiplicative($future, $alpha, $gamma, $cycle); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::NONE) { + return $this->getAdditiveNone($future, $alpha, $damping); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::ADDITIVE) { + return $this->getAdditiveAdditive($future, $alpha, $beta, $gamma, $cycle, $damping); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::MULTIPLICATIVE) { + return $this->getAdditiveMultiplicative($future, $alpha, $beta, $gamma, $cycle, $damping); + } elseif($trendType === TrendType::MULTIPLICATIVE && $seasonalType === SeasonalType::NONE) { + return $this->getMultiplicativeNone($future); + } elseif($trendType === TrendType::MULTIPLICATIVE && $seasonalType === SeasonalType::ADDITIVE) { + return $this->getMultiplicativeAdditive($future, $cycle, $damping); + } elseif($trendType === TrendType::MULTIPLICATIVE && $seasonalType === SeasonalType::MULTIPLICATIVE) { + return $this->getMultiplicativeMultiplicative($future, $cycle, $damping); + } + } + + private dampingSum(float $damping, int $length) : float + { + $sum = 0; + for($i = 0; $i < $length; $i++) { + $sum += pow($damping, $i); + } + + return $sum; + } + + public function getNoneNone($future, $alpha) : array + { + $level[0] = $data[0]; + $dataLength = count($this->data) + $future; + $forecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $level[] = $alpha * $this->data[$i-1] + (1 - $alpha) * $level[$i-1]; + + $forecast[] = $level[$i]; + } + + return $forecast; + } + + public function getNoneAdditive(int $future, float $alpha, float $gamma, int $cycle) : array + { + $level[0] = $data[0]; + $dataLength = count($this->data) + $future; + $forecast = []; + $gamma_ = $gamma * (1 - $alpha); + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $data[$i] - $level[0]; + } + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[] = $alpha * ($this->data[$i-1] - $seasonal[$i]) + (1 - $alpha) * $level[$i-1]; + $seasonal[] = $gamma_*($this->data[$i-1] - $level[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $forecast[] = $level[$i] + $seasonal[$i+$hm]; + } + + return $forecast; + } + + public function getNoneMultiplicative(int $future, float $alpha, float $gamma, int $cycle) : array + { + $level[0] = $data[0]; + $dataLength = count($this->data) + $future; + $forecast = []; + $gamma_ = $gamma * (1 - $alpha); + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[] = $alpha * ($this->data[$i-1] / $seasonal[$i]) + (1 - $alpha) * $level[$i-1]; + $seasonal[] = $gamma_*($this->data[$i-1] / $level[$i-1]) + (1 - $gamma_) * $seasonal[$i] + + $forecast[] = $level[$i] + $seasonal[$i+$hm]; + } + + return $forecast; + } + + public function getAdditiveNone(int $future, float $alpha, float $damping) : array + { + $level[0] = $this->data[0]; + $trend[0] = $this->data[1] - $this->data[0]; + $dataLength = count($this->data) + $future; + $forecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $level[] = $alpha * $this->data[$i-1] + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + + $forecast[] = $level[$i] + $this->dampingSum($damping, $i) * $trend[$i]; + } + + return $forecast; + } + + public function getAdditiveAdditive(int $future, float $alpha, float $beta, float $gamma, int $cycle, float $damping) : array + { + $level[0] = $1 / $cycle * array_sum($this->data, 0, $cycle); + $trend[0] = 1 / $cycle; + $dataLength = count($this->data) + $future; + $forecast = []; + $gamma_ = $gamma * (1 - $alpha); + + $sum = 0; + for($i = 0; $i < $cycle; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $data[$i] - $level[0]; + } + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[] = $alpha * ($this->data[$i-1] - $seasonal[$i]) + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + $seasonal[] = $gamma_*($this->data[$i-1] - $level[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $forecast[] = $level[$i] + $this->dampingSum($damping, $i) * $trend[$i] + $seasonal[$i+$hm]; + } + + return $forecast; + } + + public function getAdditiveMultiplicative(int $future, float $alpha, float $beta, float $gamma, int $cycle, float $damping) : array + { + $level[0] = 1 / $cycle * array_sum($this->data, 0, $cycle); + $trend[0] = 1 / $cycle; + $dataLength = count($this->data) + $future; + $forecast = []; + $gamma_ = $gamma * (1 - $alpha); + + $sum = 0; + for($i = 0; $i < $cycle; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[] = $alpha * ($this->data[$i-1] / $seasonal[$i]) + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + $seasonal[] = $gamma_*($this->data[$i-1] / ($level[$i-1] + $damping * $trend[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $forecast[] = ($level[$i] + $this->dampingSum($damping, $i) * $trend[$i-1]) * $seasonal[$i+$hm]; + } + + return $forecast; + } + + public function getMultiplicativeNone() : array + { + $level[0] = $this->data[0]; + $trend[0] = $this->data[1] / $this->data[0]; + } + + public function getMultiplicativeAdditive() : array + { + $level[0] = $this->data[0]; + $trend[0] = 1 / $cycle; + + $sum = 0; + for($i = 0; $i < $cycle; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $data[$i] - $level[0]; + } + } + + public function getMultiplicativeMultiplicative() : array + { + $level[0] = $this->data[0]; + + $trend[0] = 1 / $cycle; + + $sum = 0; + for($i = 0; $i < $cycle; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 0; $i < $cycle; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + } + +} \ No newline at end of file diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothingInterface.php b/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothingInterface.php deleted file mode 100644 index e268cdbc7..000000000 --- a/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothingInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * @author Dennis Eichhorn - * @copyright 2013 Dennis Eichhorn - * @license OMS License 1.0 - * @version 1.0.0 - * @link http://orange-management.com - */ - namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; - -use phpOMS\Math\Finance\Forecasting\SmoothingType; -use phpOMS\Math\Statistic\Average; -use phpOMS\Math\Statistic\Forecast\Error; - -interface ExponentialSmoothingInterface -{ - public function setCycle(int $cycle) /* : void */; - - public function getRMSE() : float; - - public function getMSE() : float; - - public function getMAE() : float; - - public function getSSE() : float; - - public function getErrors() : array; - - public function getForecast(int $future = 1, int $smoothing = SmoothingType::CENTERED_MOVING_AVERAGE) : array; -} diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/Holt.php b/Math/Finance/Forecasting/ExponentialSmoothing/Holt.php deleted file mode 100644 index 935bf097e..000000000 --- a/Math/Finance/Forecasting/ExponentialSmoothing/Holt.php +++ /dev/null @@ -1,265 +0,0 @@ - - * @author Dennis Eichhorn - * @copyright 2013 Dennis Eichhorn - * @license OMS License 1.0 - * @version 1.0.0 - * @link http://orange-management.com - */ - namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; - -use phpOMS\Math\Finance\Forecasting\SmoothingType; -use phpOMS\Math\Statistic\Average; -use phpOMS\Math\Statistic\Forecast\Error; - -class Holt implements ExponentialSmoothingInterface -{ - private $data = []; - - private $errors = []; - - private $cycle = 0; - private $damping = 0; - private $type = 0; - - private $rmse = 0.0; - - private $mse = 0.0; - - private $mae = 0.0; - - private $sse = 0.0; - - public function __construct(array $data, int $cycle = 0, int $type = ForecastType::LINEAR, float $damping = 1) - { - $this->data = $data; - $this->cycle = $cycle; - $this->type = $type; - $this->damping = $damping; - } - - public function setCycle(int $cycle) /* : void */ - { - $this->cycle = $cycle; - } - - public function getRMSE() : float - { - return $this->rmse; - } - - public function getMSE() : float - { - return $this->mse; - } - - public function getMAE() : float - { - return $this->mae; - } - - public function getSSE() : float - { - return $this->sse; - } - - public function getErrors() : array - { - return $this->errors; - } - - public function getForecast(int $future = 1, int $smoothing = SmoothingType::CENTERED_MOVING_AVERAGE) : array - { - $trendCycle = $this->getTrendCycle($this->cycle, $smoothing); - $seasonality = $this->getSeasonality($trendCycle); - $seasonalityIndexMap = $this->generateSeasonalityMap($this->cycle, $seasonality); - $adjustedSeasonalityIndexMap = $this->generateAdjustedSeasonalityMap($this->cycle, $seasonalityIndexMap); - $adjustedData = $this->getAdjustedData($this->cycle, $adjustedSeasonalityIndexMap); - $optimizedForecast = $this->getOptimizedForecast($future, $adjustedData); - - return $this->getReseasonalized($this->cycle, $optimizedForecast, $adjustedSeasonalityIndexMap); - } - - private function getTrendCycle(int $cycle, int $smoothing) : array - { - $centeredMovingAverage = []; - - $length = count($this->data); - for ($i = $cycle; $i < $length - $cycle; $i++) { - $centeredMovingAverage[$i] = Average::arithmeticMean(array_slice($this->data, $i - $cycle, $cycle)); - } - - return $centeredMovingAverage; - } - - private function getSeasonality(array $trendCycle) : array - { - $seasonality = []; - foreach ($trendCycle as $key => $value) { - $seasonality[$key] = $this->data[$key] / $value; - } - - return $seasonality; - } - - private function generateSeasonalityMap(int $cycle, array $seasonality) : array - { - $map = []; - foreach ($seasonality as $key => $value) { - $map[$key % $cycle][] = $value; - } - - foreach ($map as $key => $value) { - $map[$key] = Average::arithmeticMean($value); - } - - return $map; - } - - private function generateAdjustedSeasonalityMap(int $cycle, array $seasonality) : array - { - $total = array_sum($seasonality); - - foreach ($seasonality as $key => $value) { - $seasonality[$key] = $cycle * $value / $total; - } - - return $seasonality; - } - - private function getSeasonalIndex(int $cycle, array $seasonalityMap) : array - { - $index = []; - - foreach ($this->data as $key => $value) { - $index[$key] = $seasonalityMap[$key % $cycle]; - } - - return $index; - } - - private function getAdjustedData(int $cycle, array $seasonalIndex) : array - { - $adjusted = []; - - foreach ($this->data as $key => $value) { - $adjusted[$key] = $value / ($seasonalIndex[$key % $cycle] === 0 ? 1 : $seasonalIndex[$key % $cycle]); - } - - return $adjusted; - } - - private function forecastLinear(int $future, float $alpha, float $beta, array $data, array &$error) : array - { - $forecast = []; - $dataLength = count($data); - $length = $dataLength + $future; - - $forecast[0] = $data[0]; - - $error[0] = 0; - - $level[0] = $data[0]; - $trend[0] = $data[1] - $data[0]; - - for ($i = 1; $i < $length; $i++) { - $level[$i] = $alpha * $data[$i-1] + (1 - $alpha) * ($level[$i-1] + $this->damping * $trend[$i-1]); - $trend[$i] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $this->damping * $trend[$i - 1]; - $forecast[$i] = $level[$i] + $this->dampingSum($this->damping, $i) * $trend[$i]; - $error[$i] = $i < $dataLength ? $data[$i] - $forecast[$i] : 0; - } - - return $forecast; - } - - private function dampingSum(float $damping, int $future) : float - { - $sum = 0; - - for($i = 1; $i < $future; $i++) { - $sum += pow($damping, $i); - } - - return $sum; - } - - private function forecastExponential(int $future, float $alpha, float $beta, array $data, array &$error) : array - { - $forecast = []; - $dataLength = count($data); - $length = $dataLength + $future; - - $forecast[0] = $data[0]; - - $error[0] = 0; - - $level[0] = $data[0]; - $trend[0] = $data[1] - $data[0]; - - for ($i = 1; $i < $length; $i++) { - $level[$i] = $alpha * $data[$i-1] + (1 - $alpha) * $level[$i-1] * pow($trend[$i-1], $this->damping); - $trend[$i] = $beta * $level[$i] / $level[$i-1] + (1 - $beta) * pow($trend[$i - 1], $this->damping); - $forecast[$i] = $level[$i] * pow($trend[$i], $this->dampingSum($this->damping, $i)); - $error[$i] = $i < $dataLength ? $data[$i] - $forecast[$i] : 0; - } - - return $forecast; - } - - private function getOptimizedForecast(int $future, array $adjustedData) : array - { - $this->rmse = PHP_INT_MAX; - $alpha = 0.00; - $forecast = []; - - while ($alpha < 1) { - $beta = 0.00; - - while($beta < 1) { - $error = []; - - if($this->type === ForecastType::LINEAR) { - $tempForecast = $this->forecastLinear($future, $alpha, $beta, $adjustedData, $error); - } else { - $tempForecast = $this->forecastExponential($future, $alpha, $beta, $adjustedData, $error); - } - - $beta += 0.01; - - $tempRMSE = Error::getRootMeanSquaredError($error); - - if ($tempRMSE < $this->rmse) { - $this->rmse = $tempRMSE; - $forecast = $tempForecast; - } - } - - $alpha += 0.001; - } - - $this->errors = $error; - $this->mse = Error::getMeanSquaredError($error); - $this->mae = Error::getMeanAbsoulteError($error); - $this->sse = Error::getSumSquaredError($error); - - return $forecast; - } - - private function getReseasonalized(int $cycle, array $forecast, array $seasonalIndex) : array - { - $reSeasonalized = []; - - foreach ($forecast as $key => $value) { - $reSeasonalized[$key] = $value * ($seasonalIndex[$key % $cycle] === 0 ? 1 : $seasonalIndex[$key % $cycle]); - } - - return $reSeasonalized; - } -} diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/HoltWinter.php b/Math/Finance/Forecasting/ExponentialSmoothing/HoltWinter.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php b/Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php new file mode 100644 index 000000000..b9cd70d05 --- /dev/null +++ b/Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php @@ -0,0 +1,37 @@ + + * @author Dennis Eichhorn + * @copyright 2013 Dennis Eichhorn + * @license OMS License 1.0 + * @version 1.0.0 + * @link http://orange-management.com + */ +namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; + +use phpOMS\Datatypes\Enum; + +/** + * Smoothing enum. + * + * @category Framework + * @package phpOMS\Html + * @author OMS Development Team + * @author Dennis Eichhorn + * @license OMS License 1.0 + * @link http://orange-management.com + * @since 1.0.0 + */ +abstract class SeasonalType extends Enum +{ + /* public */ const ALL = 0; + /* public */ const NONE = 1; + /* public */ const ADDITIVE = 2; + /* public */ const MULTIPLICATIVE = 4; +} diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/ForecastType.php b/Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php similarity index 79% rename from Math/Finance/Forecasting/ExponentialSmoothing/ForecastType.php rename to Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php index 7832e4c04..271916790 100644 --- a/Math/Finance/Forecasting/ExponentialSmoothing/ForecastType.php +++ b/Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php @@ -28,9 +28,10 @@ use phpOMS\Datatypes\Enum; * @link http://orange-management.com * @since 1.0.0 */ -abstract class ForecastType extends Enum +abstract class TrendType extends Enum { - /* public */ const SIMPLE = 1; - /* public */ const LINEAR = 2; - /* public */ const EXPONENTIAL = 3; + /* public */ const ALL = 0; + /* public */ const NONE = 1; + /* public */ const ADDITIVE = 2; + /* public */ const MULTIPLICATIVE = 4; }