Create tactical demand forecasts

- the first notebook runs the tactical-forecasts command
- the second notebook describes the tactical demand forecasting process
  + demand aggregation on a per-pixel level
  + time series generation: horizontal, vertical, and real-time time series
  + STL decomposition into seasonal, trend, and residual components
  + choosing the most promising forecasting model
  + predicting demand with various models
- fix where to re-start the forecasting process after it was interrupted
- enable the heuristic for choosing the most promising model
  to also work for 7 training weeks
This commit is contained in:
Alexander Hess 2021-02-04 23:41:21 +01:00
parent 21d012050c
commit 9d6de9d98c
Signed by: alexander
GPG key ID: 344EA5AB10D868E0
5 changed files with 3480 additions and 4 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -49,9 +49,9 @@ class Config:
TIME_STEPS = [60]
# Training horizons (in full weeks) used to train the forecasting models.
# For now, we only use 8 weeks as that was the best performing in
# For now, we only use 7 and 8 weeks as that was the best performing in
# a previous study (note:4f79e8fa).
TRAIN_HORIZONS = [8]
TRAIN_HORIZONS = [7, 8]
# The demand forecasting methods used in the simulations.
FORECASTING_METHODS = ['hets', 'rtarima']

View file

@ -105,7 +105,12 @@ def tactical_heuristic( # noqa:C901,WPS213,WPS216,WPS231
# Continue with forecasting on the day the last prediction was made ...
last_predict_at = ( # noqa:ECE001
db.session.query(func.max(db.Forecast.start_at))
.join(db.Pixel, db.Forecast.pixel_id == db.Pixel.id)
.join(db.Grid, db.Pixel.grid_id == db.Grid.id)
.filter(db.Forecast.pixel == pixel)
.filter(db.Grid.side_length == side_length)
.filter(db.Forecast.time_step == time_step)
.filter(db.Forecast.train_horizon == train_horizon)
.first()
)[0]
# ... or start `train_horizon` weeks after the first `Order`

View file

@ -542,9 +542,9 @@ class OrderHistory:
pixel_id=pixel_id, predict_day=predict_day, train_horizon=train_horizon,
)
# For now, we only make forecasts with 8 weeks
# For now, we only make forecasts with 7 and 8 weeks
# as the training horizon (note:4f79e8fa).
if train_horizon == 8:
if train_horizon == 7 or train_horizon == 8:
if add >= 25: # = "high demand"
return models.HorizontalETSModel(order_history=self)
elif add >= 10: # = "medium demand"