429. Overview

429.1. Newsvendor

Single-period inventory under uncertain demand: order 𝑄 before seeing demand. After demand realizes, leftover stock is salvaged at 𝑆<𝐶, and unmet demand is lost.

The trade-off:

429.1.1. Assumptions

429.1.2. Setup

Define:

429.1.3. Derive 𝑄∗ via marginal analysis

Imagine we’ve decided to order 𝑄 units. Should we order one more?

The (𝑄+1)-th unit either sells or doesn’t:

Expected marginal profit of ordering one more unit:

Δ(𝑄)=(1−𝐹(𝑄))𝐶𝑢−𝐹(𝑄)𝐶𝑜

Order more units while Δ(𝑄)>0, stop when Δ(𝑄)=0:

(1−𝐹(𝑄∗))𝐶𝑢=𝐹(𝑄∗)𝐶𝑜𝐶𝑢−𝐹(𝑄∗)𝐶𝑢=𝐹(𝑄∗)𝐶𝑜𝐶𝑢=𝐹(𝑄∗)(𝐶𝑢+𝐶𝑜)𝐹(𝑄∗)=𝐶𝑢𝐶𝑢+𝐶𝑜

This ratio is the critical ratio (CR). Read it as: “What probability of not stocking out balances the two costs?”

429.1.4. Inverting 𝐹 to get 𝑄∗

𝑄∗=𝐹−1(CR)=𝐹−1(𝐶𝑢𝐶𝑢+𝐶𝑜)

For any demand distribution, the recipe is the same: compute CR, look up the quantile.

429.1.5. Normal demand specialization

If 𝐷∼𝒩︀(𝜇,𝜎2), write 𝑄∗=𝜇+𝑧∗𝜎 where 𝑧∗=Φ−1(CR) is the standard-normal quantile of CR.

Common 𝑧∗ values:

When 𝐶𝑢≫𝐶𝑜 (stockouts much worse than leftovers), CR →1 and 𝑧∗ pushes you to over-stock. Conversely when 𝐶𝑜≫𝐶𝑢, CR →0 and 𝑧∗<0 (under-stock the median).

Example

Given (newsstand selling newspapers):

  • Sale price: 𝑃 = $3 / unit
  • Purchase cost: 𝐶 = $1 / unit
  • Salvage value: 𝑆 = $0 / unit (unsold papers worthless)
  • Demand: 𝐷∼𝒩︀(𝜇=100,𝜎=20)

Step 1 — underage and overage

𝐶𝑢=𝑃−𝐶=3−1=2(\$/unsold-demand-unit)𝐶𝑜=𝐶−𝑆=1−0=1(\$/leftover)

Step 2 — critical ratio

CR=𝐶𝑢𝐶𝑢+𝐶𝑜=22+1=23≈0.667

Each unit ordered should have a ≈67% chance of selling — overstocking is twice as cheap as stocking out.

Step 3 — quantile lookup

For normal demand, 𝑧∗=Φ−1(0.667)≈0.44:

𝑄∗=𝜇+𝑧∗𝜎=100+0.44⋅20≈109newspapers

Step 4 — interpret

At 𝑄∗≈109: about a 67% chance of selling out (matching CR), 33% chance of leftovers. Sensible because the underage cost (𝐶𝑢=2) is twice the overage cost (𝐶𝑜=1) — the optimum biases toward stocking more than the mean (100).

newsvendor.py
import scipy.stats as stats

P, C, S = 3, 1, 0  # sale price, purchase cost, salvage value
mu, sigma = 100, 20  # demand mean and standard deviation

C_u = P - C  # underage cost
C_o = C - S  # overage cost
CR = C_u / (C_u + C_o)  # critical ratio

z_star = stats.norm.ppf(CR)  # quantile
Q_star = mu + z_star * sigma

429.1.6. Derivation via calculus (integral form)

The marginal argument above has a continuous twin: write expected cost as a function of 𝑄 and minimize directly. With overage 𝐶𝑜 and underage 𝐶𝑢:

𝒞︀(𝑄)=𝐶𝑜⋅𝔼[(𝑄−𝐷)+]+𝐶𝑢⋅𝔼[(𝐷−𝑄)+]

Rewrite the expectations as integrals. Each (⋅)+ clips the integrand to one side of 𝑄:

𝔼[(𝑄−𝐷)+]=∫0𝑄(𝑄−𝑥)𝑓(𝑥)d𝑥,𝔼[(𝐷−𝑄)+]=∫𝑄∞(𝑥−𝑄)𝑓(𝑥)d𝑥𝒞︀(𝑄)=𝐶𝑜∫0𝑄(𝑄−𝑥)𝑓(𝑥)d𝑥+𝐶𝑢∫𝑄∞(𝑥−𝑄)𝑓(𝑥)d𝑥

Differentiate (Leibniz’s rule — the boundary terms vanish because the integrand is 0 at 𝑥=𝑄):

d𝒞︀d𝑄=𝐶𝑜𝐹(𝑄)−𝐶𝑢(1−𝐹(𝑄))

Set to zero and solve:

𝐶𝑜𝐹(𝑄∗)=𝐶𝑢(1−𝐹(𝑄∗))⟹𝐹(𝑄∗)=𝐶𝑢𝐶𝑢+𝐶𝑜

— the same critical ratio. Convexity check: (d2𝒞︀)/(d𝑄2)=(𝐶𝑜+𝐶𝑢)𝑓(𝑄)≥0, so the stationary point is the global minimum.