Prévisions intégrées de la demande


Accueil » Ressources » Ici

Les prévisions probabilistes de la demande sont incontournables en matière d’optimisation du stock. Les prévisions de la demande sont dites « intégrées » au délai d'approvisionnement lorsque les valeurs des prévisions correspondent à la demande totale sur toute la période du délai d'approvisionnement. À l’inverse, les prévisions classiques sont périodiques (en général par jour, par semaine ou par mois), sans lien avec le délai d'approvisionnement. Le moteur de prévisions de Lokad fournit des prévisions probabilistes intégrées de la demande à partir de délais d'approvisionnement probabilistes. Il prend en charge les différentes particularités statistiques des données métiers, telles que la saisonnalité, les tendances et le cycle de vie des produits. Les événements qui peuvent avoir un impact sur la demande, comme les ruptures de stock ou les promotions, sont également pris en compte. Les prévisions proposées par Lokad représentent la probabilité associée à chaque unité de la demande future. Dans le présent article, nous détaillons la syntaxe utilisée pour calculer les prévisions intégrées de la demande via Lokad.

Syntaxe générale

Le moteur de prévisions dispose d’une fonction dédiée aux prévisions probabilistes. La syntaxe est la suivante :

Demand = forecast.demand(
category: C1, C2, C3, C4
hierarchy: H1, H2, H3, H4
label: PlainText
demandStartDate: LaunchDate
demandEndDate: EndDate
horizon: Leadtime
offset: 0
present: (max(Orders.Date) by 1) + 1
demandDate: Orders.Date
demandValue: Orders.Quantity
// « SO » pour stock-outs
censoredDemandDate: SO.StartDate, SO.EndDate
inflatedDemandDate: TVAds.StartDate, TVAds.EndDate
// « Promos » pour promotions
promotionDate: Promos.StartDate, Promos.EndDate
promotionDiscount: Pros.Discount
promotionCategory: Promos.Type)

À la différence des fonctions classiques, les fonctions d’appel utilisent des arguments « nommés » et non des arguments « positionnels ». Ces arguments nommés sont plus adaptés aux fonctions complexes car ils rendent le code source plus lisibles, sans trop de verbosité supplémentaire. Ils fonctionnent comme des arguments de fonction normaux et permettent donc d’utiliser les expressions Envision.

La fonction renvoie le vecteur Demande, qui est du type « distribution » (voir également L’algèbre des distributions). Les distributions appartiennent à un type de données avancé qui représente les fonctions $p : \mathbb{Z} \to \mathbb{R}$. Plus spécifiquement, le moteur de prévisions renvoie des « variables aléatoires », c’est à dire des distributions « positives » dont la « masse » est égale à 1. Dans le cas présent, $p(k)$ représente la probabilité une demande de $k$ unité(s). Chaque article, au sens Envision, est associé à sa propre distribution de la demande.

La syntaxe forecast.integral complète comprend de nombreux arguments mais seuls quatre sont obligatoires :

  • present : une valeur de date scalaire ;
  • demandDate : un vecteur de date spécifique à un article ;
  • demandValue : un vecteur numérique spécifique à un article ;
  • horizon : un vecteur de distribution.

La valeur present correspond à la date du premier jour concerné par les prévisions, à condition que les données soient complètes jusqu’au jour précédent. En effet, certaines entreprises ferment le dimanche par exemple et, si la date la plus récente trouvée dans les données est un samedi, les prévisions doivent-elles démarrer le dimanche ou le lundi ? Dans l’exemple ci-dessus, nous utilisons max(Orders.Date) + 1, en faisant l'hypothèse que des commandes sont passées chaque jour et que les dernières données d’entrées datent de la veille.

demandDate et demandValue doivent appartenir à la même table spécifique à un article, ce qui se traduit par [Id, *] dans la terminologie Envision. Les dates correspondent aux moments auxquels la demande a été constatée par le passé. Les valeurs représentent le niveau de la demande, qui est généralement comptabilisé en « unités » ou en « pièces ». Seuls les niveaux de demande entiers sont pris en charge. Cette table contient l'historique de la demande prévue par le moteur de prévisions. Dans l’idéal, l’historique est aussi long que possible même si, en pratique, les avantages sont limités au delà de 5 ans d’historique. Le moteur de prévisions traite indifféremment les historiques longs et courts. Lorsque l’historique est long les points de données les plus anciens disparaissent dans la non-pertinence statistique.

Le vecteur horizon représente les délais d'approvisionnement probabilistes à utiliser pour prévoir la demande. Les délais d'approvisionnement sont traités comme des données d’entrée du calcul des prévisions intégrées de la demande, bien qu’ils soient eux-même des prévisions. Le moteur de prévisions offre en effet la possibilité de prévoir les délais d'approvisionnement. Les prévisions des délais d'approvisionnement sont découplées des prévisions de la demande, ainsi les distributions des délais d'approvisionnement peuvent être ajustées avant d’être utilisées par le moteur de prévisions.

En plus de ces arguments obligatoires, l’exactitude des prévisions peut être grandement améliorée en fournissant plus de données au moteur de prévisions. La section suivante l’explique en détails.

Définition formelle

Dans cette section, nous présentons rapidement la définition formelle de l’opération statistique effectuée par le moteur de prévisions lors du calcul d’une prévision intégrée de la demande.

$y$ est la fonction qui représente la demande. Cette dernière est connue, car constatée, jusqu’au moment $t_0$. La demande déterministe $D$ associée à la variable aléatoire $\Lambda$ qui représente les délais d'approvisionnement est définie comme suit :

$$\text{D} : (y,\Lambda) \to \int_{0}^{\infty} \left( \int_{t_0}^{t+\lambda} y(t) dt \right) dP\Lambda$$ Le moteur de prévisions calcule $\hat{D}(y, \Lambda)$, une estimation probabiliste de la future demande exprimée par une variable aléatoire.

Catégories, hiérarchie et étiquettes

Les catégories, la hiérarchie et les étiquettes textuelles (label) aident le moteur de prévisions à établir des corrélations entre les articles, contribuant ainsi à l’amélioration de l’exactitude des prévisions. Elles jouent un rôle important lorsque les données sur la demande sont rares. Le fonctionnement des catégories et de la hiérarchie est identique au mode de prévision des délais d'approvisionnement. Consultez cette page pour plus d’informations à ce sujet.

Prévisions associées à un nouveau produit

Du point de vue prévisionnel, un « nouveau produit » est un produit qui n’a encore jamais été vendu. La difficulté consiste alors à établir des prévisions sans données historiques à exploiter. Notre moteur de prévisions permet ce type de prévisions grâce à l’argument demandStartDate. Lorsque le début de l’historique est connu, il est souhaitable de fournir cette donnée au moteur de prévisions afin d’améliorer l’exactitude des prévisions associées à la fois aux anciens et nouveaux produits.

L’argument demandStartDate permet d’indiquer une date pour chaque article. Cette date représente le jour à partir duquel la demande doit être prise en compte pour l’article. Elle est passée pour les articles qui ont déjà été vendus et future pour ceux qui vont être mis en vente.

L’argument demandStartDate présente deux avantages. Bien sûr, le premier est de permettre l’obtention de prévisions associées à un nouveau produit. Dans ce cas, l’argument offset doit aussi être renseigné. En effet, si le décalage reste à zéro — sa valeur par défaut — la période couverte par les prévisions peut ne pas couvrir la période « active » de l’article.

Exemple : aujourd'hui c’est le 1er juillet. L’horizon de prévision est une distribution de Dirac à 7 jours, ce qui représente un délai d'approvisionnement constant de 7 jours. Le produit A est mis en vente le 15 juillet, sa date de lancement. Si les prévisions sont établies aujourd’hui, la distribution pour le produit A est une distribution de Dirac nulle car l’horizon se termine avant la date de lancement du produit. Pour prévoir la première semaine de demande du produit A, le décalage pour ce dernier doit être de 14 jours.

L’argument demandStartDate permet également d’augmenter la précision des prévisions associées à « tous » les articles et pas uniquement à ceux dont le lancement est encore à venir. En effet, une première unité vendue le jour du lancement d’un produit n’a pas la même signification que six mois après ce lancement. Dans le premier cas, les ventes s’annoncent régulières alors que dans le second la demande semble limitée à quelques unités par an. Ainsi, le moteur de prévisions exploite l’argument demandStartDate pour affiner les prévisions associées à « tous » les articles.

Demande limitée et exagérée

Notre objectif est de prévoir la « demande ». Pourtant, souvent, l’historique des données ne fait qu’« approximer » la demande réelle, créant ainsi des déformations (intentionnellement ou non). Par exemple, l’historique des données peut être, en fait, l’historique des ventes. Mais, dans le cas des ruptures de stock, les volumes des ventes chutent alors que la demande peut rester au même niveau. Le moteur de prévisions de Lokad est conçu pour prendre en compte ces déformations à travers les arguments censoredDemandDate et inflatedDemandDate. Ces derniers attendent un vecteur de date spécifique à un article, c’est à dire (Id, Date) en termes Envision.

Lorsqu’une date est signalée « limitée » pour un article par l'argument censoredDemandDate, le moteur de prévisions fait l’hypothèse que la demande réelle était supérieure ou égale à la valeur constatée. Aucune hypothèse de volume n’est posée concernant la demande à cette date puisque la valeur réelle ne peut pas être connue. Pourtant, en identifiant le biais, le moteur peut faire appel à des classes d’optimisation adaptées à ce cas. En pratique, la demande est le plus souvent limitée par des « ruptures de stock » lorsqu’elle est observée à travers les ventes, qui ne comptabilisent pas les clients repartis bredouilles.

De la même façon, la demande peut être exagérée. L'argument inflatedDemandDate offre la possibilité d’identifier les dates et les articles pour lesquelles la demande réelle doit être considérée inférieure ou égale à la demande constatée. Ici encore, la demande réelle reste inconnue mais l’identification du biais est déjà très utile au moteur de prévisions. En pratique, la demande est le plus souvent exagérée lorsque le marché est stimulé par un événement temporaire non récurrent : la victoire d’une équipe de sport locale à un championnat national peut avoir des conséquences positives sur les ventes des supermarchés locaux pendant quelques jours.

Les deux arguments inflatedDemandDate et censoredDemandDate peuvent recevoir un ou deux vecteurs. Si deux vecteurs de dates sont fournis, les couples « (start, end) » définissent des segments inclusifs. La première date est la date de début du segment et la seconde celle de fin. Lorsqu'un seul vecteur de date est fourni, les segments utilisés correspondent une journée : les dates donnent les jours exacts où la demande doit être considérée comme limitée ou exagérée.

Si la limitation de la demande ou son exagération sont récurrentes — par an, par semaine, etc. — il n’est alors pas nécessaire de le signaler car le moteur de prévisions gère ces phénomènes automatiquement.

Prévisions des promotions

Le moteur de prévisions prend en charge les promotions. Les données sur les promotions sont cependant facultatives. Mais, lorsque des données sur les promotions sont fournies, les promotions doivent être indiquées à la fois dans le passé et dans le futur. Il est possible de fournir, a minima, uniquement l’argument promotionDate. Ce dernier est utilisé de la même façon que censoredDemandDate : lorsqu’un seul vecteur de date est fourni, la durée considérée des périodes promotionnelles est d’une journée et, si deux vecteurs sont fournis, le premier représente les dates de début et le second les dates de fin (ces bornes étant incluses dans l’intervalle ainsi défini).

L’argument promotionDiscount est facultatif et peut être fourni afin d’aider le moteur de prévisions à connaître « l’intensité » de la promotion en question. Un vecteur numérique est attendu pour cet argument et le moteur de prévisions traite ces données comme des valeurs « ordinales » : plus la ristourne est importante plus l’impact espéré de la promotion est grand. En pratique, c’est le moteur de prévisions qui calcule l’augmentation de la demande à prévoir à partir des augmentations observées lors de promotions précédentes.

L’argument promotionCategory est également facultatif et peut être fourni afin de classer les événements promotionnels. Lorsqu’il est fourni, il est utilisé par le moteur de prévisions pour tester les affinités entre événements promotionnels et détecter si des événements d’une même catégorie augmentent de la demande dans les mêmes proportions. Cet argument est similaire à l’argument category mais s’applique aux promotions et non aux articles.

Avertissement. Les promotions sont connues pour être difficiles à prévoir, même avec d’excellentes données historiques. Selon notre expérience, la plupart des entreprises ne disposent pas de données « de grande précision » sur leurs promotions. Ceci dit, de telles données peuvent être obtenues grâce une préparation consciencieuse à des étapes ultérieures du projet. D’une manière générale, l’obtention de données d’assez bonne qualité pour réellement améliorer les prévisions nécessite de gros efforts. Si le moteur de prévisions reçoit des données approximatives sur les promotions, les prévisions sont moins précises.

Lorsque des données sur les promotions sont fournies, les périodes de promotion doivent être signalées via l'argument inflatedDemandDate. Le signalement d’une période via les deux arguments promotionDate et inflatedDemandDate a une signification précise : l’augmentation de la demande a été plus importante que prévu et la promotion elle-même doit être considérée comme biaisée.