ADR-0008 — Decision-making under uncertainty in the Scenario Simulator¶
- Status: Accepted
- Date: 2026-06-04
- Author: Maxime GOURGUECHON
- Related: ADR-0002 (Scenario Simulator),
bmw_sales.simulation.uncertainty
Context¶
The Scenario Simulator (ADR-0002) initially returned a point estimate of projected demand (e.g. "+15.8%"). But the elasticities driving it are themselves uncertain — they are priors taken from the literature, not facts. A point estimate hides that uncertainty and invites false confidence; a strategy team plans against a range, not a single number.
Decision¶
Add bmw_sales.simulation.uncertainty: place Gaussian priors on each
elasticity (ElasticityPriors, mean ± sd) and propagate them through the
constant-elasticity demand model with a seeded Monte-Carlo simulation
(simulate_mc, 5,000 draws). The output is a full predictive distribution
(ScenarioDistribution) exposing 80% and 95% credible intervals.
The dashboard surfaces this directly: the projected-volume and net-change KPIs now carry their 80% CI, and a predictive-distribution chart (with P10 / median / P90 markers) replaces the illusion of a single answer.
Rationale¶
- Honest decision support. Reporting "+15.8% [80% CI +6%, +27%]" is what a real consultancy delivers; it makes the uncertainty an explicit, plan-able quantity rather than hiding it.
- Transparent and reproducible. Priors are explicit and user-adjustable in the UI; sampling is seeded. This is a deliberately lightweight, Bayesian-flavoured treatment — full MCMC (e.g. PyMC) would add a heavy dependency for no extra decision value at this fidelity, so Monte-Carlo propagation of priors was chosen instead.
- Consistent with the project's spine. The simulator is, and remains, explicitly labelled as a what-if tool — never a fit to the (signal-free) data.
Segment-specific priors (luxury ≠ mass market)¶
Generic car elasticities understate the luxury segment, so the priors are
segment-aware (for_segment(premium=...) on both ElasticityAssumptions and
ElasticityPriors), selectable in the UI:
| Prior | Premium / performance | Standard | Why |
|---|---|---|---|
| Own-price εₚ | ≈ -0.3 | ≈ -0.7 | Luxury demand is price-inelastic; Veblen / positional effects push εₚ toward 0 at the top. |
| Income εᵧ | ≈ 2.2 | ≈ 1.3 | Luxury cars are superior/positional goods (εᵧ ≫ 1). |
| Fuel cross-εf | weaker | -0.15 | Fuel cost is a negligible share of TCO for premium buyers. |
This addresses a fair critique: defaulting every model to εₚ ≈ -0.6 / εᵧ ≈ 1.5 ignored the premium dynamic. The values are orders-of-magnitude priors from the automotive-demand and luxury-goods literature, kept explicit and user-overridable.
Consequences¶
- + Outputs are decision-grade ranges with credible intervals.
- + No heavy probabilistic-programming dependency; pure NumPy, fast, seeded.
- − Gaussian priors can in principle yield implausible tail draws; bounded in practice by realistic prior sds and the multiplicative model form.