← Selected work
Case study · Decision modelling · 2026

Ten thousand years of demand.

A research hub had to decide how to price its work across several markets—before knowing how much work the next year would bring, or how far AI would cut the effort behind it. I built a Monte Carlo model that plays the year out ten thousand times, so every pricing option could be judged against the full range of plausible years rather than a single forecast.

Role
Sole author: specification, modelling, scenarios and recommendations
Context
Research hub · several markets
Stack
R · ggplot2 · openxlsx · Git · Excel inputs
Year
2026
10kSimulated years per run
12Months built per simulated year
<2%Convergence tolerance between half-runs
1Seed: every number reproducible

A price is a bet on next year.

Commercial terms are agreed in advance; demand arrives later. A fixed price per project means the hub carries the risk of projects running larger than planned, of automation gains arriving slower than hoped, and of quiet months with a full team.

A single forecast hides all of that. So the question was never “what will next year look like?” but “across the years that could plausibly happen, which terms keep the team funded and the client fairly charged?”

One year, built month by month.

Each of the ten thousand years is assembled from the same five steps. Where the data could speak, it does; where it could not, the assumption is explicit, named and editable.

  1. 01

    Arrivals

    For every project type and month, the number of new projects is drawn around an expected rate: the historical rate × a seasonal index × a growth multiplier drawn once per year—so a good year is good across the board, as it is in reality.

  2. 02

    Dispersion

    Real monthly counts scatter more than pure chance allows. A negative binomial captures that, with over-dispersion estimated per project type by the method of moments; sparse types borrow a pooled estimate, and types with no excess scatter fall back to Poisson.

  3. 03

    Project size

    Each simulated project copies a real past project of the same type—a bootstrap of actual hours—with an optional small jitter so the future is not limited to exact repeats. Where only totals existed, sizes came from PERT distributions instead.

  4. 04

    Effort after AI

    Automation cuts are drawn per project type and year and reduce production work only. Coordination and leadership effort comes from an activity-level catalogue, so the model knows which hours shrink with automation and which do not.

  5. 05

    Capacity and price

    Worked hours are set against team capacity month by month, and every pricing structure is evaluated on the very same simulated years—common random numbers—so differences between options are real, not noise.

Ranges, not a number.

Each option produces a distribution of outcomes. Three points on it carry most of the decisions:

0 simulated years · seed 1
P20P50P80
Outcome of one simulated year · index, last year = 100Live simulation of an illustrative model, not real figures
P20 · the floor
Exceeded four years in five. It sizes the committed core of the service.
P50 · the centre
The central estimate, used for planning and pricing.
P80 · a busy year
It sizes peak capacity: what the team must absorb in a busy year.

Alongside them: the probability of a loss under each option, the headcount the work needs against the headcount the revenue can carry, and how often a peak month would exceed the team.

Who carries the risk?

Several commercial options were evaluated on the very same simulated years. Last year’s real projects were also replayed under each option—same volume, new terms—the cleanest comparison of old and new.

Two options can earn the same on last year’s volume and still behave very differently over ten thousand simulated years: one holds steady while another moves with every swing in demand. That gap is the risk—and the model shows who holds it.

A bridge decomposes the change from one year to the next into four steps—terms, rate, automation and volume—that add up exactly to the total, so no single number has to carry an unexplained story. Scenarios stress the structure further: a market halving or withdrawing, a seasonal year, or a few large clients coming and going, simulated by resampling the clients themselves.

Decisions need an audit trail.

Assumptions in plain sight
Every input lives in Excel with a description, row by row. Changing an assumption needs no code, and every change is logged with a date and a reason.
Reproducible by design
One seed, version-controlled code, outputs regenerated rather than edited. Anyone can rerun the analysis and get the same numbers.
Checks before charts
The run stops with a list of problems on invalid inputs, warns if the two halves of the simulation disagree by 2% or more, and reconciles the replayed year with what was actually invoiced.
Data stays where it belongs
No client data in the repository—only synthetic example files, so the method can be shared without the numbers.

A decision tool, honestly labelled.

The result is a decision-support tool for the collaboration model and pricing across markets: which terms to offer, what core team they can carry, and how much risk sits with whom.

Its limits are stated as plainly as its results. With one year of project history, seasonality is treated as known; the link between a project’s size and its month is lost in resampling; automation savings are team estimates, not measurements. Each is named in the documentation, together with the data that would remove it.