Optimisation under uncertainty: planning ad budgets and prices across scenarios
TL;DR
Difficulty: Advanced
Plan for several possible months, not one forecast.
- Write the uncertainty as scenarios with probabilities and score every plan in every scenario.
- Ad returns flatten, so the best split gives every channel the same return on its next euro. That shared number is the shadow price of the budget: with your margin, it says whether more budget pays.
- When stock or capacity caps the upside, planning on the average month overstates the average month.
- Check the quiet month, not just the average, and set a review date to move money once the month shows its hand.
- For prices, maximise profit, not revenue: the best price depends on how price sensitive buyers are, not on how big the market is.
Every budget and every price is set before you know how the month will go. In this article I show how to plan across several possible months instead of one forecast, from scenarios and diminishing returns to the shadow price of budget, the flaw of averages and pricing on profit, worked step by step for an invented candle shop in Galway.
A plan built on one forecast is a plan for a month that will not happen
Most budget plans start with a single number. December will bring this much revenue, so we spend this much on ads and set this price. Then December arrives and is either quieter or busier than the number, and the plan was built for neither.
Stochastic optimisation is the name for planning that admits this up front. "Stochastic" just means random. Instead of one forecast you write down several ways the month could go, give each a probability, and choose the budget split or the price that does best across all of them. It sounds like heavy maths. In practice it is a careful spreadsheet with a few honest columns.
I will use one invented business throughout. Claddagh Candles is a small online candle shop in Galway, run by Aoife, selling at claddaghcandles.example. She advertises on Google search and on Meta (Facebook and Instagram). Nobody real, and every number below is made up so I can show every step.
Write the uncertainty down as scenarios with probabilities
The first step is to stop pretending you know the month. A scenario is one complete story of how it could go: quiet, normal or busy, for example. Each gets a probability, and the probabilities add up to 1, because exactly one story comes true. This is the standard way stochastic programming handles uncertainty in practice: formulate scenarios and assign a probability to each.1
Then the goal changes. You no longer ask "what is best if the forecast is right?". You ask "what is best on average across the stories, weighted by how likely each one is?".
Here is your plan, the list of amounts you spend on each of channels. means "choose the plan that makes what follows as large as possible". The sum runs over the scenarios, is the probability of scenario , (the Greek letter omega) stands for everything that is true in scenario , and is the profit your plan earns if scenario happens. The condition says the spend on all channels together stays within the budget , and says you cannot spend a negative amount. The weighted sum is an expected value, explained from scratch in Foundations: expected value, with the probabilities themselves in Foundations: probability.
Worked example: three ways December could go for Aoife
Aoife looks back at three Christmases and talks to her supplier about the market. She settles on three scenarios for December:
| Scenario | Probability | Google search does | Meta does |
|---|---|---|---|
| Quiet | 25% | 80% of normal | 50% of normal |
| Normal | 50% | as normal | as normal |
| Busy | 25% | 120% of normal | 150% of normal |
So , with , and . They add up to 1, as they must.
Notice that Meta swings much more than search. That matches what I see in the shops I have worked on: search catches people already looking for candles, so it moves with the season, while social ads depend on a creative landing or flopping, so they swing harder in both directions.
Notice too that the averages work out at exactly normal. For search, . For Meta, . I set it up that way on purpose. Later it lets us compare a plan built on the average month with a plan built on all three, fairly.
Advertising returns flatten as you spend more
Before splitting a budget you need to know what each channel returns at each level of spend. The first euro spent on a channel reaches the people most likely to buy. Each further euro reaches people a little less likely to, so the curve rises fast and then flattens. Google's own researchers describe advertising as having diminishing returns, which plain linear models struggle to capture.2
One simple shape for such a curve is this:
Here is the revenue channel brings in when you spend on it. The letter is the ceiling, the most revenue the channel could ever bring however much you spent. The letter is the base of the natural logarithm, about 2.718, and starts at 1 when you spend nothing and shrinks towards 0 as spend grows, so climbs from 0 towards 1. The letter sets how fast the channel saturates: the larger it is, the sooner the curve flattens. The exponential and the logarithm are explained in Foundations: logarithms.
What matters for decisions is not the height of the curve but its slope: the revenue from the next euro. That is the marginal return.
Here is the slope of the curve at spend , the extra revenue one more euro brings, and , and are as above. At zero spend the slope is , and it falls as spend rises. The difference between the next euro and the average euro is set out in Foundations: marginal versus average.
Worked example: Aoife's two curves
From her past campaigns, Aoife estimates the curves for a normal December. For Google search the ceiling is and the saturation rate is (one five thousandth). For Meta the ceiling is and (one eight thousandth).
Spend €5,000 on search: . So €37,927 of revenue.
Now the marginal returns on search. At €0, , so the first euro brings €12. At €5,000 it is . At €10,000 it is .
On Meta the first euro brings , so €5. At €5,000 it is . At €10,000 it is .
The horizontal axis is what Aoife spends on a channel in a month, from nothing to €16,000. The vertical axis is the revenue that spend brings in a normal December. The takeaway is in the shape: the first €2,000 on search brings almost €20,000, while going from €14,000 to €16,000 adds only about €1,200. The same budget can be well spent or wasted depending on where on the curve it lands.
The best split gives every channel the same next euro
With a fixed budget, the question is how to divide it. The answer is a rule that is easy to say: keep moving money to whichever channel returns more from its next euro, until the next euro returns the same everywhere. If search still paid more than Meta at the margin, shifting a euro from Meta to search would raise revenue, so the split was not yet the best.
The maths behind the rule is the Lagrangian, a way of folding the budget limit into the thing you maximise. At the best plan, every channel's marginal return equals one shared number, written .3
Here and are the spend on search and on Meta, , , and are the curve settings from before, so each side is that channel's marginal return. The Greek letter (lambda) is the shared marginal return both channels end up with, and is the total budget. The groundwork is in Foundations: marginal versus average and, for the logarithm used to solve it, Foundations: logarithms.
Worked example: splitting €10,000 for a normal December
Suppose Aoife has €10,000. The rule says with .
Take the natural logarithm of both sides. The logarithm undoes the , so the equation becomes .
Put in the numbers: and , and . So .
Gather the terms on one side: , so and . That leaves .
Check it. On search the next euro returns . On Meta it returns . Equal, as the rule demands, so .
Revenue at this split is . An even split of €5,000 each brings . Same money, €1,306 more revenue, just from putting it where the next euro works harder.
The shadow price says what more budget is worth
That shared number has a second meaning, and it is the most useful number in the whole exercise. It is the shadow price of the budget: roughly how much the best achievable result rises if you loosen the budget by one euro.3 It answers the question every managing director asks and few dashboards answer: is it worth spending more?
Revenue is not profit, though. To turn the shadow price into a decision, multiply it by the gross margin, the share of each euro of revenue left after the cost of the goods.
Here is the gross margin as a fraction, is the revenue the next euro of budget brings at the best split, so is the margin it brings, and the 1 is the euro itself. If the result is above zero, more budget pays. The idea is the same one as in Foundations: marginal versus average.
Worked example: should Aoife spend more than €10,000
Aoife's gross margin is 50%, so . At €10,000 the shadow price is , so the next euro brings , a profit of 62 cent. More budget pays.
How far? Until , so until . On search that happens when , so , so . On Meta, , so . Total: €16,289.
At that spend the normal December brings in revenue. And here the plan runs into the real world. Aoife can pour, pack and post at most €65,000 worth of candles in December. Past that, extra orders are refunded or disappoint. The shadow price was right about the curves and wrong about the shop.
Planning on the average month overstates the average month
So Aoife adds the limit: revenue counts only up to €65,000. The natural next move is to plan for the average December, which here is the normal one, and spend until revenue just reaches €65,000. That is the plan almost every business makes. It has a flaw with a name.
Sam Savage called it the flaw of averages: plans based on average conditions usually go wrong.4 The reason is that a limit cuts off the good months but not the bad ones. A busy month cannot sell more than the cap, while a quiet month can fall as far as it likes. Averaging the inputs first and then working out the result is not the same as working out the result in each scenario and then averaging. Whenever there is a cap, a threshold or a curve, the two differ.
The fix is to score every candidate plan in every scenario. The scenario formula from the start does exactly that. The gap between the plan built on all scenarios and the plan built on the average, both scored across all scenarios, is called the value of the stochastic solution.1
Here is the profit after ad spend in scenario , is the gross margin, is the revenue the ads would bring in scenario , is the capacity limit, means "whichever is smaller", so revenue above the limit does not count, and is the total ad spend. Each scenario's profit is then weighted by its probability, as in Foundations: expected value.
Worked example: the average plan against the scenario plan
The average plan is €7,500 on search and €5,000 on Meta, €12,500 in all. In a normal December search brings and Meta brings , a total of €65,202. Capped at €65,000, the profit is . That is what the plan promises.
Now score the same plan in each scenario. In a quiet month, search does 80% and Meta 50%: , so the profit is . In a normal month, €20,000 as above. In a busy month the ads would bring €83,819, but the cap holds revenue at €65,000, so the profit is again €20,000.
Weighted: . The plan promised €20,000. Its honest expectation is €17,698. The busy month cannot make up for the quiet one, because the cap took its upside away.
Now the scenario plan. I let a spreadsheet try every split in €100 steps, score each one in all three scenarios and keep the best expected profit. It lands on €7,200 on search and €3,600 on Meta, €10,800 in all. In a normal month that brings , so the profit is . In a quiet month, , profit . In a busy month the cap bites again: .
Weighted: .
So the scenario plan spends €1,700 less, earns €181 more on average, and does better in the quiet month. The extra €1,700 of the average plan buys revenue mostly in the busy month, where the cap throws it away.
I want to be honest about the size of this. €181 a month is not a fortune. The bigger gain was the €2,302 gap between what the average plan promised and what it would really deliver. That is the number that stops a business committing to a stock order or a hire on the strength of a profit that was never coming. And without the cap, with only the ceilings uncertain, the average plan would have been exactly right, because the curves scale up and down together. Scenarios earn their keep when something cuts off or bends the outcome: stock, capacity, a minimum order, a contract.
The same average can hide a very different bad month
Expected profit is a long run average. Aoife gets one December a year. Two plans with nearly the same average can leave her in very different places if the quiet month comes, so the next thing to look at is the spread of outcomes. The usual measure is the standard deviation: how far, typically, the result lands from its average.5
Here (sigma) is the standard deviation, is the probability of scenario , is the profit in that scenario, and is the expected profit. Each gap from the average is squared so that gaps above and below do not cancel, weighted by its probability, added up, and the square root brings the answer back into euro. The idea is built up in Foundations: spread and Foundations: distributions.
Worked example: three ways to spend €10,800
For the scenario plan, the gaps from €17,879 are , then , then . Squared: 45,454,564, then 2,134,521, then 14,600,041. Weighted: . The square root is about 4,010, so the standard deviation is about €4,010.
The same steps for two other splits of the same €10,800 give this:
| Split (search, Meta) | Expected profit | Quiet month | Standard deviation |
|---|---|---|---|
| €5,400, €5,400 (even) | €17,329 | €9,958 | €4,414 |
| €7,200, €3,600 (best average) | €17,879 | €11,137 | €4,010 |
| €8,400, €2,400 (careful) | €17,651 | €11,319 | €3,844 |
The even split is worse on every count, which is worth knowing because it is the split a good few people pick when they have not done the sums. The careful split gives up €228 of expected profit to make the quiet month €182 better and the spread smaller, because search swings less than Meta.
Which to choose is not a maths question. It depends on what a quiet December would do to the business. If €11,137 covers January's rent comfortably, take the higher average. If every euro in the quiet month matters, the careful split is a fair price for sleep. I wrote about weighing that trade in decision theory for founders.
Pricing under uncertainty starts with profit, not revenue
The same thinking applies to prices, with one correction first. A common way to set it up, and the way I once set it up myself, is to maximise expected revenue: price times expected demand. With the usual demand curve that goes nowhere useful.
The usual curve is constant elasticity demand, where a 1% rise in price always cuts demand by the same percentage:
Here is the number of units sold at price , (alpha) sets the size of the market, and (beta) is the price elasticity, how sharply demand falls as price rises. Revenue is then . If is above 1, which most retail products are, revenue rises every time you cut the price, all the way down to giving the product away. Elasticity is explained in Foundations: elasticity.
What you want to maximise is profit, price minus unit cost, times units. Do that and a clean rule falls out, the markup rule from any economics course: the best price sits above cost by a margin that depends only on the elasticity.6
Here is the profit maximising price, is the cost of one more unit, and is the elasticity from before, which must be above 1 for the rule to give an answer. Two things follow. The more price sensitive the customers (the larger ), the closer the price sits to cost. And , the size of the market, does not appear at all. The groundwork is in Foundations: elasticity.
That second point matters for uncertainty. If you are unsure only how big December will be, the best price does not move. What moves the best price is uncertainty about how sensitive buyers are.
Worked example: revenue says give it away
Aoife's three candle gift set costs her €12 to make and post. At €24 she expects to sell 1,000 sets, and in a typical year her elasticity is . Revenue at €24 is €24,000. At €20 she would sell sets, for €28,800. At €12 she would sell sets, for €48,000 of revenue and exactly €0 of profit.
Profit tells the truth. The markup rule gives . At €24 the profit is . At €20 it is , lower.
Worked example: pricing when the elasticity is unsure
Aoife is not sure the typical year applies. She writes three scenarios, each selling 1,000 sets at €24: price sensitive buyers (, 25%), typical (, 50%) and loyal (, 25%). The markup rule gives a different best price in each: , then , then .
She can only print one price. So she scores candidate prices in all three, with demand .
At €22, . Price sensitive: , so 1,298 sets and a profit of . Typical: , so 1,190 sets and €11,901. Loyal: , so 1,139 sets and €11,394. Weighted: .
The same steps at the scenario prices: at €18 the expected profit is €11,199, at €24 it is €12,000, and at €36 it is €10,377. Searching in steps of one cent, the best expected profit, €12,051, sits at €22.48.
Two lessons. First, the profit curve is flat near the top: anything from €22 to €24 earns within about €50 of the best. Second, the damage comes from betting on one extreme scenario. Pricing for loyal buyers at €36 costs €1,674 against the best on average, and pricing for bargain hunters at €18 costs €852. The scenarios do not find a magic price. They stop a confident guess at the edge.
Decide now, correct later
So far Aoife fixes the whole December plan on 1 December. Real budgets are not like that. Ad spend can be moved week by week, and stock can be topped up. Stochastic programming calls this recourse: the ability to take corrective action after a random event has taken place.1 You make the first decision now, see what happens, then make the second with better information. Planning that way is called a two stage problem.
The easiest way to see what recourse is worth is the extreme case. Suppose Aoife knew on 1 December which scenario was coming. She would pick the best plan for that scenario alone. Averaging those best results over the probabilities gives the ceiling: no review process, however clever, can beat knowing the future.
Worked example: what a mid December review could be worth
With the same spreadsheet search, the best plan for each scenario alone is: quiet, €7,800 on search and €1,800 on Meta, for €11,372 of profit. Normal, €7,500 and €4,900, for €20,066. Busy, €5,700 and €2,500, for €24,300, because in a busy month a much smaller spend already fills the €65,000 of capacity.
Weighted: .
The scenario plan earns €17,879. So perfect foresight would be worth at most a month. That caps what a weekly review is worth. In my experience a review after the first ten days of December recovers a good share of it, mostly by cutting Meta early in a quiet month and cutting both channels once a busy month is clearly on its way to the capacity limit. If a forecasting tool costs more than €1,072 a month for this decision, the arithmetic has already said no.
What this does not do for you
It does not know your curves. Every number above rests on the response curves and the scenario probabilities, and those are estimates. The honest way to get them is past data plus deliberate tests, which I cover in how much data you actually need and, for prices, in modelling demand and price elasticity with regression. Google's own media mix research notes that with small samples the assumptions you start with strongly shape the answer.2
It does not need heavy machinery either. For two or three channels and a handful of scenarios, a spreadsheet that tries every split in sensible steps is enough. Gradient methods and large solvers matter when there are dozens of channels, thousands of scenarios or daily decisions, and a small shop rarely has those.
And it does not remove risk. Aoife can do every step and still have a quiet December. What the method does is put the quiet December on the page before it happens, price it, and stop the plan from quietly assuming it away.
The diagram is the whole method on one page. It starts with the honest list of how the month could go, adds what each channel does and what the shop can physically handle, and only then compares plans, always scored in every scenario rather than in the average one. The decision step is the risk check from the table of three splits, and the last step is the recourse: no plan is final until the month has shown which scenario it is.
Footnotes
-
NEOS Guide, Stochastic Programming, https://neos-guide.org/guide/types/stochastic/
-
Yuxue Jin, Yueqing Wang, Yunting Sun, David Chan and Jim Koehler, Bayesian Methods for Media Mix Modeling with Carryover and Shape Effects, Google, 2017, https://research.google/pubs/bayesian-methods-for-media-mix-modeling-with-carryover-and-shape-effects/
-
Stephen Boyd and Lieven Vandenberghe, Convex Optimization, sections 5.4.4 (price interpretation and shadow prices) and 5.6.3 (local sensitivity analysis), Cambridge University Press, 2004, https://web.stanford.edu/~boyd/cvxbook/bv_cvxbook.pdf
-
Sam Savage, The Flaw of Averages, Harvard Business Review, November 2002, https://hbr.org/2002/11/the-flaw-of-averages
-
Barbara Illowsky and Susan Dean, Introductory Statistics 2e, section 4.2 Mean or Expected Value and Standard Deviation, OpenStax, Rice University, Houston, 2023, https://openstax.org/books/introductory-statistics-2e/pages/4-2-mean-or-expected-value-and-standard-deviation
-
Robert S. Pindyck, Lecture Notes on Pricing, 15.013 Industrial Economics for Strategic Decisions, MIT Sloan School of Management, August 2010, https://www.mit.edu/~rpindyck/Courses/Pricing_10.pdf