DemandForecasting
Author: Tinotenda Joe
This contract is used for forecasting demand using historical data. It uses the ABDKMath64x64 library for fixed point arithmetic operations. The contract allows stakeholders to add demand data, calculate forecasted demand, and retrieve demand data.
This contract heavily relies on the ABDKMath64x64 library for fixed point arithmetic operations. The contract uses a moving average approach with optimized alpha for forecasting. The alpha value is optimized using the gradient descent algorithm. The contract also uses linear regression to determine the underlying trend in the historical data.
State Variables
historicalDemand
mapping(uint256 => DemandEntry) historicalDemand;
demandCount
uint256 demandCount;
forecastedDemand
int128 forecastedDemand;
MAX_ITERATIONS
uint256 public MAX_ITERATIONS = 1000;
MIN_ALPHA
int128 public MIN_ALPHA;
MAX_ALPHA
int128 public MAX_ALPHA;
LEARNING_RATE
int128 public LEARNING_RATE;
INITIAL_ALPHA
int128 public INITIAL_ALPHA;
Functions
constructor
Constructor for the DemandForecasting contract
Initializes the MIN_ALPHA, MAX_ALPHA, LEARNING_RATE, and INITIAL_ALPHA values
constructor();
addDemandData
Add new demand data
This function allows stakeholders to add new demand data to the library.
function addDemandData(uint256 _demand) external;
Parameters
Name | Type | Description |
---|---|---|
_demand | uint256 | The demand value to be added. |
calculateForecastedDemand
Calculates the forecasted demand using the moving average approach with optimized alpha.
This function calculates the forecasted demand based on historical demand data using a moving average approach. It first optimizes the alpha value by calling the internal function _optimizeAlpha, passing the demandCount. The optimized alpha is then used to calculate the moving average by calling the internal function _calculateMovingAverage.
function calculateForecastedDemand() external;
_calculateMovingAverage
Calculates the moving average forecast using Exponential Smoothing and linear regression.
This function calculates the moving average forecast for a specified number of periods (_n) based on historical demand data.
The historical demand data must be added using the addDemandData function before calling this function.
function _calculateMovingAverage(uint256 _n, int128 _alpha) internal;
Parameters
Name | Type | Description |
---|---|---|
_n | uint256 | The number of periods to consider for the moving average calculation. |
_alpha | int128 | The smoothing factor used in the Exponential Smoothing calculation. The function initializes the forecast with the latest demand value from the historical data. It then performs linear regression on the historical demand data to determine the underlying trend. Afterward, it applies Exponential Smoothing to adjust the forecast based on the trend and the smoothing factor. |
_optimizeAlpha
Optimizes the alpha value for forecasting using the gradient descent algorithm.
This function optimizes the alpha value for forecasting using the gradient descent algorithm.
function _optimizeAlpha(uint256 _n) internal view returns (int128 optimizedAlpha);
Parameters
Name | Type | Description |
---|---|---|
_n | uint256 | The number of periods to consider for optimization. |
Returns
Name | Type | Description |
---|---|---|
optimizedAlpha | int128 | The optimized alpha value. |
max
function max(int128 a, int128 b) internal pure returns (int128);
min
function min(int128 a, int128 b) internal pure returns (int128);
_optimizeForecast
Applies exponential smoothing by combining the weighted average of the historical demand and the adjusted forecasted demand.
This function applies exponential smoothing by combining the weighted average of the historical demand and the adjusted forecasted demand.
function _optimizeForecast(int128 alpha, uint256 _n) internal view returns (int128 forecastError);
Parameters
Name | Type | Description |
---|---|---|
alpha | int128 | The smoothing factor used to adjust the weights of historical and forecasted demand. |
_n | uint256 | The number of historical periods to consider for the forecast. |
Returns
Name | Type | Description |
---|---|---|
forecastError | int128 | The forecast error calculated based on the optimized alpha value. |
_calculateForecastError
Calculates the forecast error based on the forecasted demand and the actual demand.
This function calculates the forecast error based on the forecasted demand and the actual demand.
function _calculateForecastError(int128 _interimForecastedDemand, int128 _actualDemand)
internal
pure
returns (int128 _interimForecastError);
Parameters
Name | Type | Description |
---|---|---|
_interimForecastedDemand | int128 | The forecasted demand value. |
_actualDemand | int128 | The actual demand value. |
Returns
Name | Type | Description |
---|---|---|
_interimForecastError | int128 | The forecast error calculated as a percentage. |
absValue
function absValue(int128 x) public pure returns (int128);
_calculateLinearRegression
Calculates the linear regression parameters (slope and intercept) based on the specified number of periods.
*The function uses the formula for simple linear regression:
- The formula for the slope (m) and intercept (b) in a linear regression model is: m = (NΣXY - ΣXΣY) / (NΣX^2 - (ΣX)^2) b = (ΣY - mΣX) / N
- Where:
- N is the number of historical periods considered for the linear regression
- ΣXY is the sum of the product of X and Y
- ΣX is the sum of X the x-values (indices) of the historical periods.
- ΣY is the sum of Y the y-values (demand) of the historical periods.
- ΣX^2 is the sum of the squares of X
- The slope represents the change in demand per unit change in the index, and the intercept represents the demand when the index is zero.*
function _calculateLinearRegression(uint256 _n) public view returns (int128 slope, int128 intercept);
Parameters
Name | Type | Description |
---|---|---|
_n | uint256 | The number of historical periods to consider for the linear regression. |
Returns
Name | Type | Description |
---|---|---|
slope | int128 | The slope of the linear regression line. slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX) |
intercept | int128 | The intercept of the linear regression line.intercept = (sumY - slope * sumX) / n |
getDemandCount
Returns the total number of demand data entries.
This function returns the total number of demand data entries.
function getDemandCount() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The total number of demand data entries. |
getHistoricalDemand
Returns the demand and cumulative sum for a specific index.
This function returns the demand and cumulative sum for a specific index.
function getHistoricalDemand(uint256 index) external view returns (string memory, string memory);
Parameters
Name | Type | Description |
---|---|---|
index | uint256 | The index of the demand data entry. |
Returns
Name | Type | Description |
---|---|---|
<none> | string | The demand and cumulative sum for the specified index. |
<none> | string |
uintToString
function uintToString(uint256 v) internal pure returns (string memory);
getLatestDemand
Returns the latest demand data entry.
This function returns the latest demand data entry.
function getLatestDemand() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The latest demand data entry. |
getForecastedDemand
Returns the forecasted demand.
This function returns the forecasted demand.
function getForecastedDemand() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The forecasted demand. |
getMaxIterations
Returns the maximum number of iterations for the alpha optimization.
This function returns the maximum number of iterations for the alpha optimization.
function getMaxIterations() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The maximum number of iterations for the alpha optimization. |
getMinAlpha
Returns the minimum alpha value.
This function returns the minimum alpha value.
function getMinAlpha() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The minimum alpha value. |
getMaxAlpha
Returns the maximum alpha value.
This function returns the maximum alpha value.
function getMaxAlpha() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The maximum alpha value. |
getLearningRate
Returns the learning rate.
This function returns the learning rate.
function getLearningRate() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The learning rate. |
getInitialAlpha
Returns the initial alpha value.
This function returns the initial alpha value.
function getInitialAlpha() external view returns (uint256);
Returns
Name | Type | Description |
---|---|---|
<none> | uint256 | The initial alpha value. |
testCalculateMovingAverage
function testCalculateMovingAverage(uint256 _n, int128 _alpha) public;
testOptimizeAlpha
function testOptimizeAlpha(uint256 _n) public view returns (int128);
testOptimizeForecast
function testOptimizeForecast(int128 alpha, uint256 _n) public view returns (int128);
testCalculateForecastError
function testCalculateForecastError(int128 _interimForecastedDemand, int128 _actualDemand)
public
pure
returns (int128);
Errors
INVALID_ENTRY_INDEX
error INVALID_ENTRY_INDEX();
INVALID_NUMBER_OF_PERIODS
error INVALID_NUMBER_OF_PERIODS();
INVALID_ACTUAL_DEMAND
error INVALID_ACTUAL_DEMAND();
NO_DEMAND_DATA
error NO_DEMAND_DATA();
DEMAND_MUST_BE_GREATER_THAN_ZERO
error DEMAND_MUST_BE_GREATER_THAN_ZERO();
Structs
DemandEntry
struct DemandEntry {
int128 demand;
int128 cumulativeSum;
}