From 0767139593693fabdbab08d4af8340561cd33c29 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 20 Aug 2017 19:25:40 +0200 Subject: [PATCH] Move finance to business --- {Math => Business}/Finance/Depreciation.php | 2 +- .../Finance/FinanceFormulas.php | 2 +- {Math => Business}/Finance/Forecasting/AR.php | 2 +- .../Finance/Forecasting/ARCH.php | 2 +- .../Finance/Forecasting/ARFIMA.php | 2 +- .../Finance/Forecasting/ARIMA.php | 2 +- .../Finance/Forecasting/ARMA.php | 2 +- .../Forecasting/ClassicalDecomposition.php | 2 +- .../ExponentialSmoothing.php | 622 ++++++++++++++++++ .../ExponentialSmoothing/SeasonalType.php | 2 +- .../ExponentialSmoothing/TrendType.php | 2 +- .../Finance/Forecasting/GARCH.php | 2 +- {Math => Business}/Finance/Forecasting/MA.php | 2 +- .../Finance/Forecasting/NAR.php | 2 +- .../Finance/Forecasting/NMA.php | 2 +- .../Finance/Forecasting/SARIMA.php | 2 +- .../Finance/Forecasting/SmoothingType.php | 2 +- {Math => Business}/Finance/Loan.php | 2 +- {Math => Business}/Finance/Lorenzkurve.php | 2 +- {Math => Business}/Finance/StockBonds.php | 2 +- .../ExponentialSmoothing.php | 4 +- 21 files changed, 643 insertions(+), 21 deletions(-) rename {Math => Business}/Finance/Depreciation.php (88%) rename {Math => Business}/Finance/FinanceFormulas.php (99%) rename {Math => Business}/Finance/Forecasting/AR.php (84%) rename {Math => Business}/Finance/Forecasting/ARCH.php (84%) rename {Math => Business}/Finance/Forecasting/ARFIMA.php (84%) rename {Math => Business}/Finance/Forecasting/ARIMA.php (99%) rename {Math => Business}/Finance/Forecasting/ARMA.php (84%) rename {Math => Business}/Finance/Forecasting/ClassicalDecomposition.php (99%) create mode 100644 Business/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php rename {Math => Business}/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php (90%) rename {Math => Business}/Finance/Forecasting/ExponentialSmoothing/TrendType.php (90%) rename {Math => Business}/Finance/Forecasting/GARCH.php (84%) rename {Math => Business}/Finance/Forecasting/MA.php (84%) rename {Math => Business}/Finance/Forecasting/NAR.php (84%) rename {Math => Business}/Finance/Forecasting/NMA.php (84%) rename {Math => Business}/Finance/Forecasting/SARIMA.php (84%) rename {Math => Business}/Finance/Forecasting/SmoothingType.php (92%) rename {Math => Business}/Finance/Loan.php (98%) rename {Math => Business}/Finance/Lorenzkurve.php (96%) rename {Math => Business}/Finance/StockBonds.php (99%) diff --git a/Math/Finance/Depreciation.php b/Business/Finance/Depreciation.php similarity index 88% rename from Math/Finance/Depreciation.php rename to Business/Finance/Depreciation.php index 9bbddd77a..cc0fd25b3 100644 --- a/Math/Finance/Depreciation.php +++ b/Business/Finance/Depreciation.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance; +namespace phpOMS\Business\Finance; class Depreciation { diff --git a/Math/Finance/FinanceFormulas.php b/Business/Finance/FinanceFormulas.php similarity index 99% rename from Math/Finance/FinanceFormulas.php rename to Business/Finance/FinanceFormulas.php index 543686261..066192afa 100644 --- a/Math/Finance/FinanceFormulas.php +++ b/Business/Finance/FinanceFormulas.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance; +namespace phpOMS\Business\Finance; use phpOMS\Math\Statistic\Average; use phpOMS\Math\Matrix\Exception\InvalidDimensionException; diff --git a/Math/Finance/Forecasting/AR.php b/Business/Finance/Forecasting/AR.php similarity index 84% rename from Math/Finance/Forecasting/AR.php rename to Business/Finance/Forecasting/AR.php index 2e640d215..33a693b69 100644 --- a/Math/Finance/Forecasting/AR.php +++ b/Business/Finance/Forecasting/AR.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class AR { diff --git a/Math/Finance/Forecasting/ARCH.php b/Business/Finance/Forecasting/ARCH.php similarity index 84% rename from Math/Finance/Forecasting/ARCH.php rename to Business/Finance/Forecasting/ARCH.php index 9b5a34a29..4c9edf6f6 100644 --- a/Math/Finance/Forecasting/ARCH.php +++ b/Business/Finance/Forecasting/ARCH.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class ARCH { diff --git a/Math/Finance/Forecasting/ARFIMA.php b/Business/Finance/Forecasting/ARFIMA.php similarity index 84% rename from Math/Finance/Forecasting/ARFIMA.php rename to Business/Finance/Forecasting/ARFIMA.php index b7bb8e2b9..0b674419e 100644 --- a/Math/Finance/Forecasting/ARFIMA.php +++ b/Business/Finance/Forecasting/ARFIMA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class ARFIMA { diff --git a/Math/Finance/Forecasting/ARIMA.php b/Business/Finance/Forecasting/ARIMA.php similarity index 99% rename from Math/Finance/Forecasting/ARIMA.php rename to Business/Finance/Forecasting/ARIMA.php index 4b92084dd..06155e65e 100644 --- a/Math/Finance/Forecasting/ARIMA.php +++ b/Business/Finance/Forecasting/ARIMA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; use phpOMS\Math\Statistic\Average; diff --git a/Math/Finance/Forecasting/ARMA.php b/Business/Finance/Forecasting/ARMA.php similarity index 84% rename from Math/Finance/Forecasting/ARMA.php rename to Business/Finance/Forecasting/ARMA.php index ad09b52e1..69c6d0b5b 100644 --- a/Math/Finance/Forecasting/ARMA.php +++ b/Business/Finance/Forecasting/ARMA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class ARMA { diff --git a/Math/Finance/Forecasting/ClassicalDecomposition.php b/Business/Finance/Forecasting/ClassicalDecomposition.php similarity index 99% rename from Math/Finance/Forecasting/ClassicalDecomposition.php rename to Business/Finance/Forecasting/ClassicalDecomposition.php index bcbc21a35..b45aaa8c9 100644 --- a/Math/Finance/Forecasting/ClassicalDecomposition.php +++ b/Business/Finance/Forecasting/ClassicalDecomposition.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance\Forecasting; +namespace phpOMS\Business\Finance\Forecasting; use phpOMS\Math\Statistic\Average; diff --git a/Business/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php b/Business/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php new file mode 100644 index 000000000..e44c60955 --- /dev/null +++ b/Business/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php @@ -0,0 +1,622 @@ +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 getForecast(int $future, int $trendType = TrendType::NONE, int $seasonalType = SeasonalType::NONE, int $cycle = 12, float $damping = 1) : array + { + $this->rmse = PHP_INT_MAX; + + if($trendType === TrendType::ALL || $seasonalType === SeasonalType::ALL) { + $trends = [$trendType]; + if($trendType === TrendType::ALL) { + $trends = [TrendType::NONE, TrendType::ADDITIVE, TrendType::MULTIPLICATIVE]; + } + + $seasonals = [$seasonalType]; + if($seasonalType === SeasonalType::ALL) { + $seasonals = [SeasonalType::NONE, SeasonalType::ADDITIVE, SeasonalType::MULTIPLICATIVE]; + } + + $forecast = []; + $bestError = PHP_INT_MAX; + foreach($trends as $trend) { + foreach($seasonals as $seasonal) { + $tempForecast = $this->getForecast($future, $trend, $seasonal, $cycle, $damping); + + if ($this->rmse < $bestError) { + $bestError = $this->rmse; + $forecast = $tempForecast; + } + } + } + + return $forecast; + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::NONE) { + return $this->getNoneNone($future); + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::ADDITIVE) { + return $this->getNoneAdditive($future, $cycle); + } elseif($trendType === TrendType::NONE && $seasonalType === SeasonalType::MULTIPLICATIVE) { + return $this->getNoneMultiplicative($future, $cycle); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::NONE) { + return $this->getAdditiveNone($future, $damping); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::ADDITIVE) { + return $this->getAdditiveAdditive($future, $cycle, $damping); + } elseif($trendType === TrendType::ADDITIVE && $seasonalType === SeasonalType::MULTIPLICATIVE) { + return $this->getAdditiveMultiplicative($future, $cycle, $damping); + } elseif($trendType === TrendType::MULTIPLICATIVE && $seasonalType === SeasonalType::NONE) { + return $this->getMultiplicativeNone($future, $damping); + } 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); + } + + throw new \Exception(); + } + + private function dampingSum(float $damping, int $length) : float + { + if(abs($damping - 1) < 0.001) { + return $length; + } + + $sum = 0; + for($i = 0; $i < $length; $i++) { + $sum += pow($damping, $i); + } + + return $sum; + } + + public function getNoneNone(int $future) : array + { + $level = [$this->data[0]]; + $dataLength = count($this->data) + $future; + $forecast = []; + + $alpha = 0.00; + while ($alpha < 1) { + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $level[$i] = $alpha * ($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) + (1 - $alpha) * $level[$i-1]; + + $tempForecast[$i] = $level[$i]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getNoneAdditive(int $future, int $cycle) : array + { + $level = [$this->data[0]]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i-1] - $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $seasonal[$i]) + (1 - $alpha) * $level[$i-1]; + $seasonal[$i+$cycle] = $gamma_*(($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $level[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[$i] = $level[$i] + $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getNoneMultiplicative(int $future, int $cycle) : array + { + $level = [$this->data[0]]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / $seasonal[$i]) + (1 - $alpha) * $level[$i-1]; + $seasonal[$i+$cycle] = $gamma_*(($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / $level[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[$i] = $level[$i] + $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getAdditiveNone(int $future, float $damping) : array + { + $level = [$this->data[0]]; + $trend = [$this->data[1] - $this->data[0]]; + $dataLength = count($this->data) + $future; + $forecast = []; + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $level[$i] = $alpha * ($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[$i] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + + $tempForecast[$i] = $level[$i] + $this->dampingSum($damping, $i) * $trend[$i]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $beta += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getAdditiveAdditive(int $future, int $cycle, float $damping) : array + { + $level = [1 / $cycle * array_sum(array_slice($this->data, 0, $cycle))]; + $trend = [1 / $cycle]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + + $sum = 0; + for($i = 1; $i < $cycle+1; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i-1] - $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $seasonal[$i]) + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[$i] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + $seasonal[$i+$cycle] = $gamma_*(($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $level[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[$i] = $level[$i] + $this->dampingSum($damping, $i) * $trend[$i] + $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $beta += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getAdditiveMultiplicative(int $future, int $cycle, float $damping) : array + { + $level = [1 / $cycle * array_sum(array_slice($this->data, 0, $cycle))]; + $trend = [1 / $cycle]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + $gamma_ = $gamma * (1 - $alpha); + + $sum = 0; + for($i = 1; $i < $cycle+1; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / $seasonal[$i]) + (1 - $alpha) * ($level[$i-1] + $damping * $trend[$i-1]); + $trend[$i] = $beta * ($level[$i] - $level[$i-1]) + (1 - $beta) * $damping * $trend[$i-1]; + $seasonal[$i+$cycle] = $gamma_*($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / ($level[$i-1] + $damping * $trend[$i-1]) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[] = ($level[$i] + $this->dampingSum($damping, $i) * $trend[$i-1]) * $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $beta += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getMultiplicativeNone(int $future, float $damping) : array + { + $level = [$this->data[0]]; + $trend = [$this->data[1] / $this->data[0]]; + $dataLength = count($this->data) + $future; + $forecast = []; + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $level[$i] = $alpha * ($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) + (1 - $alpha) * $level[$i-1] * pow($trend[$i-1], $damping); + $trend[$i] = $beta * ($level[$i] / $level[$i-1]) + (1 - $beta) * pow($trend[$i-1], $damping); + + $tempForecast[$i] = $level[$i] * pow($trend[$i], $this->dampingSum($damping, $i)); + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $beta += 0.01; + } + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getMultiplicativeAdditive(int $future, int $cycle, float $damping) : array + { + $level = [$this->data[0]]; + $trend = [1 / $cycle]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + + $sum = 0; + for($i = 1; $i < $cycle+1; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i-1] - $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $seasonal[$i]) + (1 - $alpha) * $level[$i-1] * pow($trend[$i-1], $damping); + $trend[$i] = $beta * ($level[$i] / $level[$i-1]) + (1 - $beta) * pow($trend[$i-1], $damping); + $seasonal[$i+$cycle] = $gamma_*(($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) - $level[$i-1] * pow($trend[$i-1], $damping)) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[$i] = $level[$i] * pow($trend[$i], $this->dampingSum($damping, $i)) + $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $beta += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + + public function getMultiplicativeMultiplicative(int $future, int $cycle, float $damping) : array + { + $level = [$this->data[0]]; + $trend = [1 / $cycle]; + $dataLength = count($this->data) + $future; + $forecast = []; + $seasonal = []; + + $sum = 0; + for($i = 1; $i < $cycle+1; $i++) { + $sum += ($this->data[$cycle] - $this->data[$i]) / $cycle; + } + + $trend[0] *= $sum; + + for($i = 1; $i < $cycle+1; $i++) { + $seasonal[$i] = $this->data[$i] / $level[0]; + } + + $alpha = 0.00; + while ($alpha < 1) { + $beta = 0.00; + + while($beta < 1) { + $gamma = 0.00; + + while($gamma < 1) { + $gamma_ = $gamma * (1 - $alpha); + $error = []; + $tempForecast = []; + + for($i = 1; $i < $dataLength; $i++) { + $hm = (int) floor(($i-1) % $cycle) + 1; + + $level[$i] = $alpha * (($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / $seasonal[$i]) + (1 - $alpha) * $level[$i-1] * pow($trend[$i-1], $damping); + $trend[$i] = $beta * ($level[$i] / $level[$i-1]) + (1 - $beta) * pow($trend[$i-1], $damping); + $seasonal[$i+$cycle] = $gamma_*($i < $dataLength - $future ? $this->data[$i-1] : $tempForecast[$i-1]) / ($level[$i-1] * pow($trend[$i-1], $damping)) + (1 - $gamma_) * $seasonal[$i]; + + $tempForecast[$i] = $level[$i] * pow($trend[$i], $this->dampingSum($damping, $i)) * $seasonal[$i+$hm]; + $error[] = $i < $dataLength - $future ? $this->data[$i] - $tempForecast[$i] : 0; + } + + $tempRMSE = Error::getRootMeanSquaredError($error); + + if ($tempRMSE < $this->rmse) { + $this->rmse = $tempRMSE; + $forecast = $tempForecast; + } + + $gamma += 0.01; + } + + $beta += 0.01; + } + + $alpha += 0.01; + } + + $this->errors = $error; + $this->mse = Error::getMeanSquaredError($error); + $this->mae = Error::getMeanAbsoulteError($error); + $this->sse = Error::getSumSquaredError($error); + + return $forecast; + } + +} \ No newline at end of file diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php b/Business/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php similarity index 90% rename from Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php rename to Business/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php index 48959cedd..22c8bd549 100644 --- a/Math/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php +++ b/Business/Finance/Forecasting/ExponentialSmoothing/SeasonalType.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; +namespace phpOMS\Business\Finance\Forecasting\ExponentialSmoothing; use phpOMS\Stdlib\Base\Enum; diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php b/Business/Finance/Forecasting/ExponentialSmoothing/TrendType.php similarity index 90% rename from Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php rename to Business/Finance/Forecasting/ExponentialSmoothing/TrendType.php index 423ac9c99..72413e498 100644 --- a/Math/Finance/Forecasting/ExponentialSmoothing/TrendType.php +++ b/Business/Finance/Forecasting/ExponentialSmoothing/TrendType.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; +namespace phpOMS\Business\Finance\Forecasting\ExponentialSmoothing; use phpOMS\Stdlib\Base\Enum; diff --git a/Math/Finance/Forecasting/GARCH.php b/Business/Finance/Forecasting/GARCH.php similarity index 84% rename from Math/Finance/Forecasting/GARCH.php rename to Business/Finance/Forecasting/GARCH.php index cce9e6647..07a3654b0 100644 --- a/Math/Finance/Forecasting/GARCH.php +++ b/Business/Finance/Forecasting/GARCH.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class GARCH { diff --git a/Math/Finance/Forecasting/MA.php b/Business/Finance/Forecasting/MA.php similarity index 84% rename from Math/Finance/Forecasting/MA.php rename to Business/Finance/Forecasting/MA.php index 7835bf3b6..4ec6a3103 100644 --- a/Math/Finance/Forecasting/MA.php +++ b/Business/Finance/Forecasting/MA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class MA { diff --git a/Math/Finance/Forecasting/NAR.php b/Business/Finance/Forecasting/NAR.php similarity index 84% rename from Math/Finance/Forecasting/NAR.php rename to Business/Finance/Forecasting/NAR.php index 3d48db0fb..7f499cfa7 100644 --- a/Math/Finance/Forecasting/NAR.php +++ b/Business/Finance/Forecasting/NAR.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class NAR { diff --git a/Math/Finance/Forecasting/NMA.php b/Business/Finance/Forecasting/NMA.php similarity index 84% rename from Math/Finance/Forecasting/NMA.php rename to Business/Finance/Forecasting/NMA.php index 79884ab82..c8a67b716 100644 --- a/Math/Finance/Forecasting/NMA.php +++ b/Business/Finance/Forecasting/NMA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class NMA { diff --git a/Math/Finance/Forecasting/SARIMA.php b/Business/Finance/Forecasting/SARIMA.php similarity index 84% rename from Math/Finance/Forecasting/SARIMA.php rename to Business/Finance/Forecasting/SARIMA.php index 3671547b9..53573e3c3 100644 --- a/Math/Finance/Forecasting/SARIMA.php +++ b/Business/Finance/Forecasting/SARIMA.php @@ -12,7 +12,7 @@ * @link http://orange-management.com */ declare(strict_types=1); - namespace phpOMS\Math\Finance\Forecasting; + namespace phpOMS\Business\Finance\Forecasting; class SARIMA { diff --git a/Math/Finance/Forecasting/SmoothingType.php b/Business/Finance/Forecasting/SmoothingType.php similarity index 92% rename from Math/Finance/Forecasting/SmoothingType.php rename to Business/Finance/Forecasting/SmoothingType.php index abc8f931b..d14f75f2d 100644 --- a/Math/Finance/Forecasting/SmoothingType.php +++ b/Business/Finance/Forecasting/SmoothingType.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance\Forecasting; +namespace phpOMS\Business\Finance\Forecasting; use phpOMS\Stdlib\Base\Enum; diff --git a/Math/Finance/Loan.php b/Business/Finance/Loan.php similarity index 98% rename from Math/Finance/Loan.php rename to Business/Finance/Loan.php index 482b75229..2938a44c5 100644 --- a/Math/Finance/Loan.php +++ b/Business/Finance/Loan.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance; +namespace phpOMS\Business\Finance; /** * Finance class. diff --git a/Math/Finance/Lorenzkurve.php b/Business/Finance/Lorenzkurve.php similarity index 96% rename from Math/Finance/Lorenzkurve.php rename to Business/Finance/Lorenzkurve.php index ed04d5e9b..fb1b15a56 100644 --- a/Math/Finance/Lorenzkurve.php +++ b/Business/Finance/Lorenzkurve.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance; +namespace phpOMS\Business\Finance; /** * Finance class. diff --git a/Math/Finance/StockBonds.php b/Business/Finance/StockBonds.php similarity index 99% rename from Math/Finance/StockBonds.php rename to Business/Finance/StockBonds.php index e61885014..cae66824c 100644 --- a/Math/Finance/StockBonds.php +++ b/Business/Finance/StockBonds.php @@ -13,7 +13,7 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance; +namespace phpOMS\Business\Finance; /** * Finance class. diff --git a/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php b/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php index 5176085e7..e44c60955 100644 --- a/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php +++ b/Math/Finance/Forecasting/ExponentialSmoothing/ExponentialSmoothing.php @@ -13,9 +13,9 @@ */ declare(strict_types=1); -namespace phpOMS\Math\Finance\Forecasting\ExponentialSmoothing; +namespace phpOMS\Business\Finance\Forecasting\ExponentialSmoothing; -use phpOMS\Math\Finance\Forecasting\SmoothingType; +use phpOMS\Business\Finance\Forecasting\SmoothingType; use phpOMS\Math\Statistic\Average; use phpOMS\Math\Statistic\Forecast\Error;