Some assumptions in a plan are uncertain: churn could be 2 % or 5 %, a hire could start in March or in June. The probabilistic mode runs the forecast many times, each time with different values drawn from the ranges a person gave, and reports how likely a goal is (for example "at least 12 months of runway"), the range of outcomes and which assumptions matter most. This page gives the formulas behind those figures, what each symbol means, when they hold and a worked example.
How to read this page. Each formula is shown on its own line, followed by its symbols with their units, the conditions under which it holds, what it says in plain words and a short example. The forecast run in every sample is the ordinary deterministic one (forecast formulas); this page only adds the sampling and the statistics on top.
Notation
| Symbol | Meaning | Unit |
|---|---|---|
| N | Number of samples (forecast runs); 200 by default | runs |
| i | A sample, i = 1, \dots, N | |
| j | An uncertain assumption | |
| x_{ij} | The value drawn for assumption j in sample i | the assumption's unit |
| G | A goal, such as "runway of at least 12 months" | |
| \mathbb{1}[\cdot] | 1 if the condition holds, else 0 |
Draws
For each sample and each uncertain assumption a value is drawn from one random generator seeded with the
simulation's seed, in sample order and then assumption order. Draws are rounded to six decimals and applied as the
override {assumptionKey, operation, value: x, targetId} after the scenario's own overrides.
Uniform
In plain words. Every value between low and high is equally likely. Use it when you only know the bounds.
Triangular
In plain words. Values near the most likely value (mode) are drawn most often, falling off in straight lines to low and high. The mode defaults to the midpoint. Use it when you have a best guess and a range.
Normal, cut to the range
| Symbol | Meaning | Unit |
|---|---|---|
| \sigma | Standard deviation, chosen so that the wider side of the range is the 95th percentile | the assumption's unit |
In plain words. A bell curve around the mode. Values outside the range are set to the nearest bound, so low and high are drawn a little more often than a pure bell curve would.
Example. Mode 200, range 150 to 300: \sigma = \max(100, 50)/1.645 = 60.8.
Outcomes per sample
| Outcome | Definition |
|---|---|
| runway | runwayMonthsForecast, or beyond the horizon when cash never runs out |
| minimum cash | summary.minimumCash |
| ending cash | cash.ending in the last month |
| ending ARR | summary.endingArr |
| break-even | summary.breakEvenMonth |
Goals: runway_months is met when the runway is at least the value or beyond the horizon; minimum_cash when
minimum cash is at least the amount; break_even_by when break-even happens in or before the month; ending_arr
when ending ARR is at least the amount.
Measures
Goal probability
In plain words. The share of samples in which the goal is met.
Valid when. The ranges given describe the real uncertainty and the assumptions are independent of each other (the platform draws them independently). It is an estimate: with more samples it moves less; the interval below says how much.
Example. The goal is met in 140 of 200 samples: \hat P = 0.70.
90 % interval of the probability (Wilson)
In plain words. The range in which the true probability lies with 90 % confidence, given the number of samples. The Wilson interval stays sensible near 0 % and 100 %, where the simpler textbook interval breaks down.
Valid when. Always; it is cut to [0, 1].
Example. 140 of 200: from 0.644 to 0.750, so "about 70 %, between 64 % and 75 %".
Percentiles
| Symbol | Meaning | Unit |
|---|---|---|
| x_{(r)} | The r-th smallest outcome | the outcome's unit |
| Q_p | The value below which a share p of samples fall | the outcome's unit |
In plain words. P10 is a bad but plausible case, P50 the middle case, P90 a good case.
Valid when. Always. Beyond the horizon ranks above every number; a percentile that lands on it is shown as empty, meaning "longer than the forecast". The mean is shown only when every sample has a number.
Example. With 200 samples, P10 is the 20th smallest runway, P50 the 100th and P90 the 180th.
Sensitivity
In plain words. Spearman's rank correlation between the values drawn for one assumption and ending cash: +1 means a higher value always gives more cash, −1 always less, 0 no relation. The assumption with the largest \lvert \rho_s \rvert matters most.
Valid when. Tied values get their average rank; an assumption whose draws are all the same has \rho_s = 0. It measures a monotone relation, not cause and effect when assumptions interact.
Recommended actions
calc/recommend.py (ADR 48). For an action set A the
same draws are used as for the baseline \varnothing (common random numbers), so differences come from the actions,
not from luck:
| Symbol | Meaning | Unit |
|---|---|---|
| \hat P_A(G) | Probability of the goal with the actions A applied | share |
| \Delta_A | Uplift: how much the actions raise the probability | share |
Ranking: by \hat P_A(G) descending, then by the number of actions ascending, then by median ending cash descending. Search: every action alone, then all pairs of the five best single actions, then all triples of the four best, skipping pairs where one action excludes the other. Without uncertain assumptions each option is one forecast and its probability is 0 or 1.
Example. The goal is met in 70 % of samples today and in 85 % when a hire moves three months later: \Delta = +0.15.
Funding eligibility
calc/funding.py (ADR 49). Each eligibility rule of a
programme is a formula-language expression with a true or false result, evaluated with only the facts it names:
| Status | Condition |
|---|---|
| eligible | every rule evaluates to true |
| not eligible | at least one rule evaluates to false |
| needs answers | no rule is false and at least one cannot be evaluated because a fact it names has no value |
The amount is a formula in currency (for example min(funding_need, 125000)), evaluated when the programme is not
ruled out and its facts are known. Missing facts are ranked by how many open programmes they would settle.
Reproducibility
inputHash is the SHA-256 of the canonical JSON of the request (without the seed field) together with the seed
used. The same request and seed on the same engine version give the same result.
For developers
Code: finance_engine/calc/simulation.py (ADR 47):
Uncertainty.draw, _q (percentiles), _band, _wilson, _ranks and _spearman. Every measure is also
returned with the result as LaTeX and a plain explanation. Keep this page in sync with any change there.