Creare ordini per priorità con le previsioni probabilistiche - Ottimizzazione

Ordinare gli acquisti per priorità economica












Home » Risorse » Qui

Le previsioni probabilistiche consentono di avere una visione dei possibili scenari futuri molto più completa e precisa rispetto ad altri metodi di previsione. In questa pagina vedremo come sfruttarle per migliorare l'intera procedura di ordine e generare una lista di priorità degli acquisti con Lokad. Le liste di priorità degli acquisti, a differenza dei punti di riordino, sono molto flessibili, ci permettono di eliminare i livelli di servizio e si adattano meglio ai vari vincoli di riapprovvigionamento.

La lista di priorità degli acquisti è un esempio di strategia di riordino per priorità. Le strategie di questo tipo, rispetto ai metodi più tradizionali di gestione del magazzino, assicurano prestazioni di livello molto più elevato. Lokad consiglia, quando possibile, il ricorso a metodi di riordino per priorità.

Modello di script per la lista di priorità

Per generare una lista di priorità, è necessario usare un piccolo script Envision (vedi sotto). È possibile creare lo script all'interno dell'account Lokad dal pulsante Create Envision script (crea script Envision). Una volta creato il nuovo progetto, apparirà un editor di codice sorgente. Copiare il codice qui sotto, quindi fare clic su Save (salva).
read "/sample/Lokad_Items.tsv" with 
 Supplier: text
 Category: text
 SubCategory: text
read "/sample/Lokad_Orders.tsv" as Orders
read "/sample/Lokad_PurchaseOrders.tsv" as PO

orderingLeadtime := 7 // 7 giorni

// esclude gli ordini non consegnati
where PO.DeliveryDate > PO.Date 
  Leadtime = forecast.leadtime(
    hierarchy: Category, SubCategory
    present: (max(Orders.Date) by 1) + 1
    leadtimeDate: PO.Date
    leadtimeValue: PO.DeliveryDate - PO.Date + 1)

Demand = forecast.demand(
  horizon: Leadtime +* dirac(orderingLeadtime)
  hierarchy: Category, SubCategory
  present: (max(Orders.Date) by 1) + 1
  demandDate: Orders.Date
  demandValue: Orders.Quantity)

show form "Purchase simulator" a1b3 tomato with Form.budget as "Max budget"

M = SellPrice - BuyPrice
// penalità rottura di stock
S = - 0.25 * SellPrice
// % '0.3' come costo annuo di mantenimento a magazzino
C = - 0.3 * BuyPrice * mean(Leadtime) / 365
// ordine arretrato 
MB = 0.5 * SellPrice 
MBU = MB * uniform(1, Backorder)
// ordine arretrato
SB = 0.5 * SellPrice
SBU = SB * uniform(1, Backorder) 
// opportunità di acquistare più tardi
AM = 0.3 
// % '0.2' come sconto economico annuo
AC = 1 - 0.2 * mean(Leadtime) / 365 

RM = MBU + (stockrwd.m(Demand, AM) * M) >> Backorder
RS = SBU + zoz(stockrwd.s(Demand) * S) >> Backorder
RC = (stockrwd.c(Demand, AC) * C) >> BackOrder
// ricomposizione semplice
R = RM + RS + RC

Stock = StockOnHand + StockOnOrder

DBO = Demand >> BackOrder
table G = extend.distrib(DBO, Stock, LotMultiplier)

where G.Max > Stock
  G.Q = G.Max - G.Min + 1
  // integrale della funzione di rendimento delle scorte
  G.Reward = int(R, G.Min, G.Max)
  G.Score = G.Reward / max(1, BuyPrice * G.Q)

  // prima i punteggi più alti
  // ma mantiene l'ordine delle coppie (Id, G.Max)
  G.Rank = rank(G.Score, Id, -G.Max)
  G.Invest = cumsum(BuyPrice * G.Q) sort [G.Rank]

  where G.Invest < Form.budget + 0
  where exists(G.Q)
    show table "Purchase priority list with $\{Form.budget}" c1g3 tomato with
      Id as "Id"
      Supplier as "Supplier"
      StockOnHand as "OnHand"
      StockOnOrder as "OnOrder"
      sum(G.Q) as "Qty"
      mean(Leadtime) as "Leadtime"
      sum(G.Reward) as "Reward" unit:"$"
      sum(BuyPrice * G.Q) as "Cost" unit:"$"
      group by Id
      order by avg(G.Score) desc

Lo script produrrà un pannello di controllo che contiene una tabella (grande). Nella tabella, ogni articolo apparirà più volte. Mentre si pianifica la logistica, occorrerà acquistare gli articoli suggeriti seguendo l'ordine della lista. Le quantità suggerite tengono conto sia dei riordini, sia del moltiplicatore di partite.

Image

Ma esaminiamo nel dettaglio il contenuto dello script: le prime 4 righe sono semplicemente istruzioni di lettura del file. Più precisamente, noi abbiamo ipotizzato che il file si trovi nella cartella /hello, ma sarà possibile modificare questo dato a proprio piacimento, indicando la cartella in cui il file si trova realmente. I file Lokad_Items.tsv e Lokad_Orders.tsv contengono i dati storici usati per produrre le previsioni. Le previsioni vere e proprie sono contenute nel file Lokad_Grid.tsv.

Ipotizziamo che il file Lokad_Items.tsv, che dovrà contenere la lista di prodotti o SKU, contenga anche due colonne "speciali":

  • SellPrice: il prezzo unitario di vendita (al netto delle tasse);
  • BuyPrice: il prezzo unitario di acquisto (al netto delle tasse).

Una volta sistemato lo script in modo che estragga i dati dalla cartella di input corretta, ipotizzando che i campi SellPrice e BuyPrice siano disponibili come previsto dalla nostra tecnologia, fare clic sul pulsante Run (Esegui). In questo modo, lo script viene eseguito e crea una grande tabella. Fare clic sulla tabella, in fondo alla schermata, per scaricare la tabella in formato Excel.

L'inizio dello script comprende due chiamate al motore di previsione probabilistica di Lokad, rispettivamente per la previsione del lead time e per la previsione della domanda.

A questo punto, possiamo introdurre le variabili economiche rilevanti per il calcolo della funzione di rendimento delle scorte:
  • M: rendimento (margine lordo) per unità servita dalle scorte.
  • S: penalità, calcolata per unità, quando le scorte non consentono di soddisfare un ordine.
  • C: costo annuo unitario di mantenimento a magazzino.
  • AM: fattore di sconto sulla componente margine.
  • AC: fattore di sconto sulla componente costi di mantenimento.

Alla base della nostra logica c'è il calcolo di G.Reward e G.Score.
  • G.Reward: rappresenta il rendimento economico associato a G.Q ulteriori unità in magazzino (solitamente G.Q è pari a 1).
  • G.Score: rappresenta il coefficiente della quantità di ritorni economici, in dollari, per ogni dollaro investito in scorte.

Il filtro where (dove) esclude tutti i casi in cui il punto di riordino è al di sotto dei livelli di scorte attuali. Escludiamo questi casi perché, per il momento, consideriamo solo gli scenari di acquisto in cui l'obiettivo è quello di aumentare le scorte. In questo blocco, procediamo a una seconda serie di calcoli alla base della classificazione in ordine di priorità:

  • G.Rank: ordina tutte le entrate della tabella secondo il rapporto di ricavo. Per ogni articolo, viene conservato l'ordine del punto di riordino.
  • G.Invest: dimostra come creare un calcolo cumulativo. Qui calcoliamo l'investimento totale (cumulativo) ipotizzando che ogni articolo venga acquistato seguendo l'ordine della lista.

Lo script termina con show table (mostra tabella). Tutte le linee della tabella sono aggregate per Id (identificativo) per fare in modo che ogni articolo appaia una sola volta nella lista.

Rifinire le priorità

Lo script che abbiamo appena visto si basa su assunti piuttosto semplicistici, soprattutto riguardo i costi di mantenimento a magazzino e la massimizzazione del margine lordo. Certo, stimare correttamente costi e benefici è essenziale, ma la lista definitiva viene redatta sulla base di queste prime previsioni.

Rivedere l'intero script potrebbe sembrare a prima vista un compito ingrato, ma abbiamo constatato che questo è il modo migliore per avere tutta la flessibilità che un'attività commerciale richiede. Lo script Envision offre la stessa espressività che si trova di solito in un foglio di calcolo Excel.

Non tutti gli articoli in catalogo saranno soggetti agli stessi costi di mantenimento a magazzino: alcuni potranno essere deperibili, altri molto voluminosi... Per una stima più realistica di tali costi, raccomandiamo di consultare la nostra pagina dedicata ai costi di gestione del magazzino. Abbiamo avuto modo di osservare che la maggioranza delle aziende sottovaluta i costi di magazzino: secondo la nostra esperienza, i costi di magazzino annui dovrebbero essere almeno pari al 25%.

Dal punto di vista del profitto, lo script che abbiamo appena visto favorisce una massimizzazione pura del margine lordo. Questo potrebbe creare problemi se in un'attività sono presenti articoli con un margine inferiore, che però generano molte vendite minori, ma molto più redditizie (ad esempio, un cliente acquista prima uno smartphone con un margine lordo del 2,5%, poi due accessori per smartphone con un margine lordo del 50%). In questo caso, è possibile introdurre un fattore "avviamento" che rappresenti un margine differito da applicare a questo tipo di prodotti.

La nostra esperienza ci insegna che le classificazioni secondo la priorità possono variare molto da un'attività all'altra, e che ognuna di esse riflette le esigenze specifiche del business per cui è stata pensata. Non esitate a per avere maggiore assistenza.