Quick start
This is a lightweight and simple Julia package for modeling and solving newsvendor problems.
Setup
NewsvendorModel.jl requires an installation of Julia (can be downloaded from the official website). You can install NewsvendorModel.jl like any other Julia package using the REPL as follows:
julia> import Pkg
julia> Pkg.add("NewsvendorModel")
After installation, it can be loaded with the usual command.
julia> using NewsvendorModel
Moreover, you need to load the Distributions.jl package.
julia> using Distributions
Usage
- Define a model with the function
nvm = NVModel(demand, cost, price)
using the following required arguments:demand
distribution, which can be any choosen from the univariate distributions of the Distributions.jl package- unit production
cost
- unit selling
price
- Find the optimal quanitity and obtain key metrics:
q_opt(nvm)
returns the quantity that maximizes the expected profitprofit(nvm, q)
to get the expected profit ifq
is stockedprofit(nvm)
is short for the maximal expected profitprofit(nvm, q_opt(nvm))
solve(nvm)
gives a list of further important metrics (critical fractile as well as expected sales, lost sales, and leftover).
Additional keyword arguments specifying salvage value, backorder penalty, holding cost, substitute value, fixcost, qmin, and qmax can be passed in Step 1. To obtain the unrounded optimal quantity, pass rounded=false
in Step 2.
Example
Consider an example with
- unit
cost
= 5 - unit
price
= 7 demand
that draws from a normal distribution with- mean = 50
- standard deviation = 20
Define the model and store it in the variable nvm
as follows:
julia> nvm = NVModel(demand = Normal(50, 20), cost = 5, price = 7)
Data of the Newsvendor Model
* Demand distribution: Normal{Float64}(μ=50.0, σ=20.0)
* Unit cost: 5.00
* Unit selling price: 7.00
Next, you can solve the model and store the result in the variable res
like so:
julia> res = solve(nvm)
=====================================
Results of maximizing expected profit
* Optimal quantity: 39 units
* Expected profit: 52.41
=====================================
This is a consequence of
* Cost of underage: 2.00
╚ + Price: 7.00
╚ - Cost: 5.00
* Cost of overage: 5.00
╚ + Cost: 5.00
* Critical fractile: 0.29
* Rounded to nearest integer: true
-------------------------------------
Ordering the optimal quantity yields
* Expected sales: 35.34 units
* Expected lost sales: 14.66 units
* Expected leftover: 3.66 units
-------------------------------------
Moreover, you have stored the result in the variable res
. Reading the data from the stored result is straight-forward:
julia> q_opt(res)
39
julia> profit(res)
52.40715617998893
Analogously, underage_cost(res)
, overage_cost(res)
, critical_fractile(res)
, sales(res)
, lost_sales(res)
, leftover(res)
read.
Applying the above functions directly to the model (instead of to the result) is also possible, with the ability to pass a quantity. For instance,
julia> leftover(nvm, 39)
3.656120545715868
An advantage of using the solve
function and then reading the data from the result lies in the fact that the model that was solved can be retrieved with nvmodel(res)
.