The forecast module provides the following functionality for representing forecasted future demand:
- A new demand type to model forecasts.
A calendar model is used to divide the time horizon into a number of time buckets. A demand is automatically created for each time bucket.
See the example below. - A forecasting algorithm to extrapolate historical demand data to the future.
The test case forecast_6 contains a benchmark test that demonstrates frePPLe is able to compute a valid forecast that is competitive with other tools in the market.
The following forecasting methods are implemented:- Single exponential smoothing, which is applicable for constant demands
- Double exponential smoothing, which is applicable for trended demands
- Holt-Winter’s exponential smoothing with mutiplicative seasonality, which is applicable for seasonal demands
- Croston’s method, which is applicable for intermittent demand (i.e. demand patterns with a lot of zero demand buckets)
- Moving average, which is applicable when there is little demand history
The forecast method giving the smallest symmetric mean absolute percentage error (aka “sMAPE”-error) will be automatically picked to produce the forecast.
The forecast methods are also implemented to perform sanity checks on their applicability. E.g. It is not reasonable to apply a trending forecast when we only have very few data points. E.g. The seasonal forecast method is only used when a clear cyclical pattern is found in the data.
The algorithm will automatically tune the parameters for the forecasting methods (i.e. alfa for the single exponential smoothing, alfa and gamma for the double exponential smoothing, test for periodicity for seasonal forecast, etc) to their optimal value. The user can specify minimum and maximum boundaries for the parameters and the maximum allowed number of iterations for the algorithm.
- Functionality for distributing / profiling forecast numbers into smaller time buckets.
This functionality allows to translate between different time granularities.
The forecast entered by the sales department could for instance be in monthly buckets, while the manufacturing department requires the forecast to be in weekly or even daily buckets to generate accurate manufacturing and procurement plans.
Another usage is to model a delivery date profile of the customers. Each bucket has a weight that is used to model situations where the demand is not evenly spread across buckets: e.g. when more orders are expected due on a monday than on a friday, or when a peak of orders is expected for delivery near the end of a month.
- A solver for netting orders from the forecast.
As customer orders are being received they need to be deducted from the forecast to avoid double-counting it. The netting solver will for each order search for a matching forecast and reduce the remaining net quantity of the forecast.
This process is referred to as forecast netting or forecast consumption.
For example, assume the forecast for customer A in January is 100 pieces, and we have already received orders of 20 from the customer.
Without the netting algorithm the demand in January will be 120 pieces, which is (very likely) not correct.
The netting solver will deduct the orders of 20 from the forecast. The total demand that is planned in January will then be equal to 100: 80 remaining forecast + 20 orders.
The solver algorithm has logic to match a demand with the most appropriate forecast, and can also consider netting in previous and subsequent time buckets.
- The different functionalities can be used together.
Depending on your business process and needs you can also choose not to use them all.
The module enables the following new objects:
- demand_forecast is a specialized representation of the demand.
- solver_forecast is a solver for performing the forecast netting calculations.
Module configuration
The module support the following configuration parameters:
- DueAtEndOfBucket:
By default forecast demand is due at the start of the forecasting bucket. Since the actual customer demand will come in any time in the bucket this is a conservative setting.
By setting this flag to true, the forecast will be due at the end of the forecast bucket. This more relaxed setting may give more realistic plans in some cases. - Net_CustomerThenItemHierarchy:
As part of the forecast netting a demand is assiociated with a certain forecast. When no matching forecast is found for the customer and item of the demand, frePPLe looks for forecast at higher level customers and items.
This flag allows us to control whether we first search the customer hierarchy and then the item hierarchy, or the other way around.
The default value is true, ie search higher customer levels before searching higher levels of the item. - Net_MatchUsingDeliveryOperation:
Specifies whether or not a demand and a forecast require to have the same delivery operation to be a match.
The default value is true. - Net_NetEarly:
Defines how much time before the due date of an order we are allowed to search for a forecast bucket to net from.
The default value is 0, meaning that we can net only from the bucket where the demand is due. - Net_NetLate:
Defines how much time after the due date of an order we are allowed to search for a forecast bucket to net from.
The default value is 0, meaning that we can net only from the bucket where the demand is due. - Forecast_Iterations:
Specifies the maximum number of iterations allowed for a forecast method to tune its parameters.
Only positive values are allowed and the default value is 10.
Set the parameter to 1 to disable the tuning and generate a forecast based on the user-supplied parameters. - Forecast_smapeAlfa:
Specifies how the sMAPE forecast error is weighted for different time buckets. The sMPAPE value in the most recent bucket is 1.0, and the weight decreases exponentially for earlier buckets.
Acceptable values are in the interval 0.5 and 1.0, and the default is 0.95. - Forecast_Skip:
Specifies the number of time series values used to initialize the forecasting method. The forecast error in these bucket isn’t counted. - Forecast_MovingAverage_buckets
This parameter controls the number of buckets to be averaged by the moving average forecast method. - Forecast_SingleExponential_initialAlfa,
Forecast_SingleExponential_minAlfa,
Forecast_SingleExponential_maxAlfa:
Specifies the initial value and the allowed range of the smoothing parameter in the single exponential forecasting method.
The allowed range is between 0 and 1. Values lower than about 0.05 are not advisable. - Forecast_DoubleExponential_initialAlfa,
Forecast_DoubleExponential_minAlfa,
Forecast_DoubleExponential_maxAlfa:
Specifies the initial value and the allowed range of the smoothing parameter in the double exponential forecasting method.
The allowed range is between 0 and 1. Values lower than about 0.05 are not advisible. - Forecast_DoubleExponential_initialGamma,
Forecast_DoubleExponential_minGamma,
Forecast_DoubleExponential_maxGamma:
Specifies the initial value and the allowed range of the trend smoothing parameter in the double exponential forecasting method.
The allowed range is between 0 and 1. - Forecast_DoubleExponential_dampenTrend
Specifies how the trend is dampened for future buckets.
The allowed range is between 0 and 1, and the default value is 0.8. - Forecast_Seasonal_initialAlfa,
Forecast_Seasonal_minAlfa,
Forecast_Seasonal_maxAlfa:
Specifies the initial value and the allowed range of the smoothing parameter in the seasonal forecasting method.
The allowed range is between 0 and 1. Values lower than about 0.05 are not advisible. - Forecast_Seasonal_initialBeta,
Forecast_Seasonal_minBeta,
Forecast_Seasonal_maxBeta:
Specifies the initial value and the allowed range of the trend smoothing parameter in the seasonal forecasting method.
The allowed range is between 0 and 1. - Forecast_Seasonal_initialGamma,
Forecast_Seasonal_minGamma,
Forecast_Seasonal_maxGamma:
Specifies the initial value and the allowed range of the seasonal smoothing parameter in the seasonal forecasting method.
The allowed range is between 0 and 1. - Forecast_Seasonal_minPeriod,
Forecast_Seasonal_maxPeriod:
Specifies the periodicity of the seasonal cycles to check for.
The interval of cycles we try to detect should be broad enough. For instance, if we expect to find a yearly cycle use a minimum period of 10 and maximum period of 14. - Forecast_Seasonal_dampenTrend
Specifies how the trend is dampened for future buckets.
The allowed range is between 0 and 1, and the default value is 0.8. - Forecast_Croston_initialAlfa,
Forecast_Croston_minAlfa,
Forecast_Croston_maxAlfa:
Specifies the initial value and the allowed range of the smoothing parameter in the Croston forecasting method.
The allowed range is between 0 and 1. Values lower than about 0.05 are not advisable. - Forecast_Croston_minIntermittence:
Minimum intermittence (defined as the percentage of zero demand buckets) before the Croston method is applied.
When the intermittence exceeds this value, only Croston and moving average are considered suitable forecast methods.
The default value is 0.33.
Demand subclass demand_forecast
All fields available on the demand model are allowed on a forecast.
In particular the item and customer field are important, since these are used to match a demand with a certain forecast for netting.
The following fields are available in addition to the demand fields.
Field | Type | Description |
calendar | non-empty string | Name of the calendar used to define time buckets for distributing the forecast numbers. |
discrete | boolean | Specifies whether forecast should be rounded to integer numbers. The default value is true. |
bucket buckets |
xml | Speficies the forecast value for a date range. See example below. |
Method | Description |
timeseries(
, ) |
This method runs the timeseries algorithms on the input historical demand data, and sets the forecasted value in the specified future time buckets. |
Solver solver_forecast
This solver runs the forecast netting calculations.
The solver loops through the demands in order of their priority, and for each demand a matching forecast is searched. When a matching forecast is identified, the solver looks for a time bucket to net from: first in the bucket where it is due, then in earlier buckets within the chosen time window, and finally in later buckets within the chosen time window. The net forecast in the forecast buckets is decreased.
Note the the profiling of the forecast is not handled by this solver. The profiling happens during the data load, i.e. when the forecast demand is read in.
In addition to the regular solver fields, the following fields are available.
Field | Type | Description |
loglevel | 0 – 2 | Amount of logging and debugging messages:
|
Example XML structures
- Forecast input
<plan> <demands> <demand name="Forecast 1" xsi:type="demand_forecast"> <item name="Product 1" /> <customer name="Customer 1" /> <calendar name="planningbuckets" /> <discrete>true</discrete> <buckets> <bucket> <start>2007-01-01T00:00:00</start> <end>2007-02-01T00:00:00</end> <total>200</total> </bucket> <bucket> <start>2007-02-01T00:00:00</start> <end>2007-03-01T00:00:00</end> <total>200</total> </bucket> </buckets> </demand> </demands> </plan>
Example Python code
- Adding or changing a forecast
it = frepple.item(name="item") cust = frepple.customer(name="customer") cal = frepple.calendar(name="planningbuckets") fcst = frepple.demand_forecast(name="My forecast", item=it, customer=cust, calendar=cal)
- Loading the module
frepple.loadmodule("mod_forecast.so", Net_CustomerThenItemHierarchy=True, Net_MatchUsingDeliveryOperation=True, Net_NetEarly="P7D", Net_NetLate="P7D")
- Creating a time series forecast
The first argument is the demand history in previous buckets.
The second argument are the time buckets where we want to create a forecast value.thebuckets = [ i.start for i in thecalendar.buckets ] fcst.timeseries([10,12,9,11,8,15,19,11], thebuckets)
- Netting customer orders from the forecast
frepple_forecast.solver_forecast(name="Netting", loglevel=1).solve()