← Back to the full chapter
Lesson

9. Build a bounded lab before proposing production

Model demand, separate the causal response, and optimise within supported limits.

3 min readApplied extensionUpdated
Read source ↗

Use synthetic data with a known demand mechanism for the intervention lab. Public retail transactions can teach cleaning and forecasting, but they generally cannot show what a price change would cause. UCI Online Retail has transaction timestamps, quantities, unit prices and cancellations. Its documented schema lacks exposure to unpurchased prices, inventory and randomised price assignment, so do not label a regression on that dataset a validated optimal-price engine.

The simulator below is a specification for you to build; the repository does not include it. Practise first with the reference lab. Its pricing example has one product, three prices and assumed conversion probabilities, written to a price comparison and a pricing figure. It checks only the contribution arithmetic: it estimates no demand and has no confounded prices, stores, seasonality or stockouts.

For the 25-hour project, keep your generator to 20 products, three stores, 140 days and four approved prices per product. Use seeded generation and save the generator configuration. Model isolated products first, and leave assortment and multi-period inventory optimisation as extensions.

  1. Generate exposure and count demand with a known log-price effect, store/product effects and seasonality. Hide the true parameters from the training pipeline. Use ample inventory for the core training, calibration and evaluation experiment, and check that no demand is censored. Observed units then equal demand, so the baseline has a valid uncensored target.
  2. Generate two clearly labelled assignment regimes: randomised approved prices with known probabilities, and manager-chosen prices that depend on a hidden demand shock. The second shows confounding and is not causal training data. Include zero-sales rows and return delays, with some outcomes deliberately incomplete at the final observation date.
  3. Fit the seasonal baseline, log-price GLM and one boosted demand model on forward windows. Keep separate later windows for calibration and testing. Compare observed sales forecasting and identified response estimation separately. Cluster uncertainty at the simulated assignment unit, and document the independence built into the generator.
  4. Implement the price-grid optimiser, then compare its decisions with the simulator's known expected-profit optimum over the same feasible actions. Report simulated regret and abstention, plus matured profit. Score it on independent simulation draws, not on the optimiser's own predictions. Check predictive coverage for the selected actions as well as by price. The simulator supplies those outcomes without claiming observed individual counterfactuals. Freeze model, calibration and policy before the final test.
  5. Run a separate stockout stress scenario with finite inventory and sales observed as min(latent_demand, inventory). Keep those records out of the uncensored baseline's training data, and show that it abstains outside its approved inventory regime. A censor-aware model is an optional extension: it estimates latent demand, and the optimiser applies the inventory cap once. Avoid training on capped sales as if they were demand and then capping that forecast again. In a failure exercise, remove exposure logs or stockout flags and show why validation rejects the data. Request an out-of-support price and change inventory after scoring, to test fallback and execution revalidation.
  6. Serve one recommendation request, save its decision log and replay it from saved versions. Write an experiment memo for replacing synthetic identification with a real approved trial.

Deliver a reproducible generator, feature/data contract, split diagram, comparison table, response curves, interval-calibration report, optimiser, API example and policy card. Label every result “synthetic” or “observational” as appropriate. The simulator's known elasticity says nothing about a real retailer.

Something unclear or out of date? Suggest a correction ↗

Find your next idea

Loading local search…

Search is built from this edition. No account needed.