Moving a model from @RISK, ModelRisk or Analytic Solver
xellstorm opens a workbook built for @RISK, ModelRisk or Analytic Solver without the add-in, reads 164 of their distribution functions, and turns each such formula into an input whose parameters stay linked to your cells. Before you run, it lists what it converted and every formula it left, with the reason.
The 164 functions are 53 of @RISK, 62 of ModelRisk and 49 of Analytic Solver. It also reads 65 forms that give a distribution by its percentiles, along with truncation, output markers, correlation matrices and multi-simulation tables.
What the import finds in a workbook written for @RISK
The example is the building estimate of the project contingency example, written the way a model built for @RISK would be: each cost item is =RiskPert(min, most likely, max, RiskName(label)) on the cells of its row, each risk event is a RiskBernoulli on its probability, the total cost and the overrun are marked with RiskOutput, Structure and MEP are correlated through RiskCorrmat, three budgets sit in one RiskSimtable, and a cell reports RiskMean of the total. A second sheet, “Demonstrations”, holds five separate formulas: two arithmetic forms that do convert and three formulas that do not. We made the file with a script; xellstorm does not need @RISK to read it, and neither do you.
In the app, Import from workbook on the Distributions step lists the formulas it found (the command line’s xellstorm import prints the same list). For this workbook it converts 12 inputs: the 6 cost items, the 4 risk events and 2 arithmetic demonstrations. The cost items and risk events keep their parameters linked to the cells, so editing a min or a probability in the workbook changes the next run, and RiskName(A3) names each input after the text in its row. The two that convert are a Normal draw multiplied by a factor, and one whose mean is calculated from another cell. Neither is used by the estimate’s outputs.
| Cell | Formula in the workbook | Becomes |
|---|---|---|
| E3 | =RiskPert(B3, | Site work: a PERT with min B3 (100), most likely C3 (120), max D3 (170) |
| E4 | =RiskPert(B4, | Foundation: a PERT with min B4 (300), most likely C4 (340), max D4 (460) |
| E5 | =RiskPert(B5, | Structure: a PERT with min B5 (760), most likely C5 (820), max D5 (1,010) |
| E6 | =RiskPert(B6, | MEP: a PERT with min B6 (540), most likely C6 (610), max D6 (780) |
| E7 | =RiskPert(B7, | Finishes: a PERT with min B7 (400), most likely C7 (450), max D7 (560) |
| E8 | =RiskPert(B8, | Equipment: a PERT with min B8 (260), most likely C8 (280), max D8 (330) |
| D11 | =RiskBernoulli(B11, | Ground conditions: a Bernoulli with probability B11 (0.25) |
| D12 | =RiskBernoulli(B12, | Design change: a Bernoulli with probability B12 (0.35) |
| D13 | =RiskBernoulli(B13, | Supplier delay: a Bernoulli with probability B13 (0.2) |
| D14 | =RiskBernoulli(B14, | Severe weather: a Bernoulli with probability B14 (0.3) |
| Demonstrations!B3 | =RiskNormal(100, | a Normal with mean 100 and sd 10, then multiply the draw by 1.1; demonstration only, not used by the estimate |
| Demonstrations!B4 | =RiskNormal(Estimate!C3*1.1, | a Normal with mean Estimate!C3*1.1 (132) and sd 10; demonstration only, not used by the estimate |
The same import reads the rest of the model:
- Outputs. The cells marked
RiskOutput("Total cost")andRiskOutput("Over budget")become outputs with those names. The marker adds 0, as it does in @RISK, so the cells calculate. - Correlation.
RiskCorrmat(Correlation,1)andRiskCorrmat(Correlation,2)put Structure and MEP in the matrix under the name Correlation, a rank correlation of 0.6 (only the lower triangle is filled in; a blank cell is read from its mirror across the diagonal). The value is read from the matrix as the workbook holds it when you import, and the import says so. - Simulations.
RiskSimtable({2900,3000,3100})gives the budget one value per simulation in @RISK. xellstorm holds the budget at 2,900 in the base run and adds the other two as scenarios, which draw the same random numbers as the base run, so they differ only in the budget. - Statistics.
RiskMean, like the other functions that report results back into a cell, is not a distribution, so it is not listed as unconverted. It has no value outside @RISK (the compatibility check names the cell); the mean is in xellstorm’s results.
Formulas that do not convert are listed too. All 3 on the second sheet come with the reason the import gives, and each has a way forward:
| Formula | Reason given | What to do |
|---|---|---|
=RiskBinomial(1, | multiple distributions in one formula are not converted; give each distribution its own input cell | Split it: one cell =RiskBernoulli(0.3) for whether the risk occurs, one =RiskTriang(20,40,80) for its impact, and multiply them in a third, as the estimate’s risk events do. |
=RISKCOMPOUND(RiskPoisson(3), | RISKCOMPOUND has no exact xellstorm equivalent | xellstorm has no compound distribution. Model the count and the sizes in cells of their own, or leave the cell out of the model. |
=RISKPERTALT(10%, | RISKPERTALT has no exact xellstorm equivalent | Enter the PERT’s min, most likely and max (RiskPert), or give the percentiles to RiskTrigen, which converts. |
Running the converted model
Run with the imported setup and 5,000 trials, the average total cost is 2,784.7 (USD thousands), and the exact mean of the same distributions, the PERT means (min + 4 × most likely + max) / 6 plus each risk’s probability times its impact, is 2,784.7; the standard error of the simulated mean is 1.7. Structure and MEP reach a rank correlation of 0.60. The three budgets of the RiskSimtable, run as the base and two scenarios:
| Run | Budget | Chance of going over |
|---|---|---|
| Base run (simulation 1) | 2,900 | 17.7% |
| Simulation 2 | 3,000 | 5.2% |
| Simulation 3 | 3,100 | 0.7% |
A larger budget is exceeded less often, and because the scenarios draw the same numbers as the base run, the differences between the rows come from the budget alone, not from sampling.
Will the results match the add-in?
The model is the same; the random numbers are not. Each rule of the import maps a function to the distribution it describes, with the parameters translated as the vendor documents them, and is tested against the equivalent scipy distribution; the script that makes the test data also checks each mapping’s mean against the vendor’s documented formula. So once every distribution of a workbook converts, its means and percentiles differ from the add-in’s by sampling noise, which shrinks as you run more trials: the standard error above is the size to expect for the mean.
Correlations are rank correlations, as @RISK and Analytic Solver define them, and xellstorm reaches the rank correlation asked for. How the draws are paired to reach it is each tool’s own, so a correlated model can differ a little more in the tails than sampling noise alone explains. The workbook itself is not changed: xellstorm reads the file, and your model still opens in the add-in.
What converts
- Distributions and arithmetic arguments. A distribution can stand alone, or have one positive multiplier followed by at most one added or subtracted offset:
RiskNormal(B1*1.1,B2)*C1+5and5+C1*RiskNormal(B1,B2)convert. Arguments, multipliers and offsets can use numbers, single-cell references, parentheses and+,−,*,/. Defined names that refer to one cell become its address. These expressions stay linked and are evaluated after each scenario’s fixed cells are applied; every reference must be deterministic. Functions marked † in the table still convert with numbers only. - Percentile forms. @RISK’s
…Altand…AltDfunctions and Analytic Solver’s…Altfunctions (those in the table below) give a distribution by its percentiles; xellstorm solves for the distribution exactly when you run and reports an error when no distribution, or more than one, fits them. - Truncation and shift.
RiskTruncate,RiskTruncate2,RiskTruncateP,RiskShift,VoseXBounds,VosePBounds,VoseShift,PsiTruncate,PsiTruncatePandPsiShift, applied in the order each add-in documents. Any multiplier and offset outside the distribution apply afterward and are shown separately in the input’s settings. - Names and locks.
RiskName,PsiNameandVoseInputname the input;RiskLockholds it at one value. The catalog also lists properties that are ignored (Static, Units, Category, Collect, Base, Seed, IsDiscrete, IsDate, Fit, FitInfo, Certify, BaseCase, Library and SixSigma, with the vendor prefix).RiskSeedproduces a warning: its random-stream settings are not preserved, and xellstorm’s simulation seed and input order control its draws. - Outputs.
RiskOutput,VoseOutput,PsiOutputandPsiSimOutputmark outputs; in Analytic Solver a statistic such asPsiMean(B1)also makes B1 an output, and so it does here. - Correlations and simulations.
RiskCorrmat,RiskDepCwithRiskIndepC,PsiCorrMatrix,PsiCorrDepenwithPsiCorrIndep;RiskSimtable,VoseSimTableandPsiSimParam. - Excel’s own formulas.
NORM.INV(RAND(), mean, sd),RANDBETWEEN,IF(RAND() < p, 1, 0)and 18 such forms in all, listed below.
What does not convert
Multiple distributions in one cell, a distribution inside another function or in a denominator, direct division of a distribution, and chains that require changing the order of arithmetic do not convert. For example, (RiskNormal(0,1)+5)*2 and RiskNormal(0,1)*2*3 are left with a reason. RiskNormal(0,1)*(1/C1) does convert when C1 gives a finite positive multiplier, because the formula explicitly calculates the reciprocal before multiplying. Multipliers that work out to zero or less, arguments that call functions or depend on random cells, functions with no exact equivalent (compound distributions, time-series functions, RiskPertAlt and the other two-shape percentile forms), ModelRisk’s U argument and copulas, and properties not in the table also remain unsupported. An unsupported add-in formula cannot be calculated by the engine; the compatibility check names it.
Supported functions
The tables are generated from the importer’s own rule list, so they are exactly what it converts. “Percentiles” marks the forms that give a distribution by its percentiles; † marks the functions that convert with numbers only. Under each distribution is its name in xellstorm specs.
| Distribution (xellstorm name) | @RISK | ModelRisk | Analytic Solver |
|---|---|---|---|
Bernoullibern | RiskBernoulli | VoseBernoulli | PsiBernoulli |
Betabeta | RiskBetaRiskBetaGeneralRiskBetaSubj† | VoseBetaVoseBeta4VoseBetaSubj† | PsiBetaPsiBetaGenPsiBetaSubj† |
Binomialbinom | RiskBinomial | VoseBinomial | PsiBinomial |
Burr XIIburr12 | RiskBurr12 | — | — |
Cauchycauchy | RiskCauchyPercentiles: RiskCauchyAltRiskCauchyAltD | VoseCauchy | — |
Chi-squaredchi2 | RiskChiSqPercentiles: RiskChiSqAltRiskChiSqAltD | VoseChiSq | PsiChiSquarePercentiles: PsiChiSquareAlt |
Chi, Maxwellchi | — | VoseChiVoseMaxwell | — |
Cumulativecumul | RiskCumulRiskCumulD† | VoseCumulAVoseCumulD†VoseOgive† | PsiCumul |
Dagum (Burr III)burr | RiskDagum | VoseDagum | PsiDagum |
Discretecustom | RiskDiscreteRiskDUniform | VoseDiscreteVoseDUniform | PsiDiscretePsiDisUniform |
Exponentialexpon | RiskExponPercentiles: RiskExponAltRiskExponAltD | VoseExponVoseExponential | PsiExponentialPercentiles: PsiExponentialAlt |
Extreme value (max, Gumbel)gumbel_r | RiskExtValuePercentiles: RiskExtValueAltRiskExtValueAltD | VoseExtValueMax | PsiMaxExtremePercentiles: PsiMaxExtremeAlt |
Extreme value (min)gumbel_l | RiskExtValueMinPercentiles: RiskExtValueMinAltRiskExtValueMinAltD | — | PsiMinExtremePercentiles: PsiMinExtremeAlt |
Ff | RiskF | VoseF | PsiFDist |
Fatigue life (Birnbaum–Saunders)fatiguelife | RiskFatigueLifePercentiles: RiskFatigueLifeAltRiskFatigueLifeAltD | VoseFatigue | PsiFatigueLifePercentiles: PsiFatigueLifeAlt |
Fréchetinvweibull | RiskFrechetPercentiles: RiskFrechetAltRiskFrechetAltD | — | PsiFrechetPercentiles: PsiFrechetAlt |
Gamma, Erlanggamma | RiskGammaRiskErlangPercentiles: RiskGammaAltRiskGammaAltD | VoseGammaVoseErlang | PsiGammaPsiErlangPercentiles: PsiGammaAlt |
General (relative weights)general | RiskGeneral | VoseRelative | — |
Generalized Paretogenpareto | — | VoseGPD | — |
Histogramhistogram | RiskHistogrm | VoseHistogram | PsiHistogram |
Hyperbolic secanthypsecant | RiskHypSecantPercentiles: RiskHypSecantAltRiskHypSecantAltD | VoseHS | PsiHypSecant |
Hypergeometrichypergeom | RiskHypergeo | VoseHypergeo | PsiHyperGeo |
Integer uniformrandint | RiskIntUniform | VoseIntUniformVoseStepUniform† | PsiIntUniform |
Inverse Gaussianinvgauss | RiskInvgaussPercentiles: RiskInvgaussAltRiskInvgaussAltD | VoseInvGauss | PsiInvNormal |
Johnson SBjohnsonsb | RiskJohnsonSB | VoseJohnsonB | PsiJohnsonSB |
Johnson SUjohnsonsu | RiskJohnsonSU | VoseJohnsonU | PsiJohnsonSU |
Kumaraswamykumaraswamy | RiskKumaraswamy | VoseKumaraswamyVoseKumaraswamy4 | PsiKumaraswamy |
Laplacelaplace | RiskLaplacePercentiles: RiskLaplaceAltRiskLaplaceAltD | VoseLaplace | — |
Lévylevy | RiskLevyPercentiles: RiskLevyAltRiskLevyAltD | VoseLevy | PsiLevyPercentiles: PsiLevyAlt |
Log-logisticfisk | RiskLogLogisticPercentiles: RiskLogLogisticAltRiskLogLogisticAltD | VoseLogLogistic | PsiLogLogisticPercentiles: PsiLogLogisticAlt |
Logisticlogistic | RiskLogisticPercentiles: RiskLogisticAltRiskLogisticAltD | VoseLogistic | PsiLogisticPercentiles: PsiLogisticAlt |
Lognormallognorm | RiskLognormRiskLognorm2Percentiles: RiskLognormAltRiskLognormAltD | VoseLognormalVoseLognormalE | PsiLogNormalPsiLognormPsiLognorm2Percentiles: PsiLogNormalAlt |
Negative binomial, geometricnbinom | RiskGeometRiskNegbin | VoseGeometricVoseNegBinVoseNegBinomVosePolya† | PsiGeometricPsiNegBinomial |
Normalnorm | RiskNormalRiskErf†Percentiles: RiskNormalAltRiskNormalAltD | VoseNormalVoseErf† | PsiNormalPsiErf†Percentiles: PsiNormalAlt |
Paretopareto | RiskParetoPercentiles: RiskParetoAltRiskParetoAltD | VosePareto | PsiParetoPercentiles: PsiParetoAlt |
Pareto II (Lomax)lomax | RiskPareto2Percentiles: RiskPareto2AltRiskPareto2AltD | VosePareto2 | PsiPareto2Percentiles: PsiPareto2Alt |
Pearson V (inverse gamma)invgamma | RiskPearson5Percentiles: RiskPearson5AltRiskPearson5AltD | VosePearson5 | PsiPearson5Percentiles: PsiPearson5Alt |
Pearson VI (beta prime)betaprime | RiskPearson6 | VosePearson6 | PsiPearson6 |
PERTpert | RiskPert | VosePERTVoseModPERT | PsiPert |
Poissonpoiss | RiskPoisson | VosePoisson | PsiPoisson |
Rayleighrayleigh | RiskRayleighPercentiles: RiskRayleighAltRiskRayleighAltD | VoseRayleigh | PsiRayleighPercentiles: PsiRayleighAlt |
Reciprocal (log-uniform)loguniform | RiskReciprocal | VoseReciprocal | PsiReciprocal |
Student’s tt | RiskStudentPercentiles: RiskStudentAltRiskStudentAltD | VoseStudentVoseStudent3† | PsiStudentPercentiles: PsiStudentAlt |
Triangulartriang | RiskTriang | VoseTriangle | PsiTriangular |
Triangular from percentiles (Trigen)trigen | RiskTrigenPercentiles: RiskTriangAlt | VoseTriangleAlt | PsiTriangGen |
Uniformunif | RiskUniformPercentiles: RiskUniformAltRiskUniformAltD | VoseUniform | PsiUniform |
Weibullweibull_min | RiskWeibullPercentiles: RiskWeibullAltRiskWeibullAltD | VoseWeibullVoseWeibull3 | PsiWeibullPercentiles: PsiWeibullAlt |
| Formula | xellstorm |
|---|---|
=NORM.INV(RAND(), | norm (loc, scale) |
=NORMINV(RAND(), | norm (loc, scale) |
=mean + sd*NORM.S.INV(RAND()) | norm (loc, scale) |
=LOGNORM.INV(RAND(), | lognorm (mu, sigma) |
=LOGINV(RAND(), | lognorm (mu, sigma) |
=GAMMA.INV(RAND(), | gamma (a, scale) |
=GAMMAINV(RAND(), | gamma (a, scale) |
=BETA.INV(RAND(), | beta (a, b) |
=BETA.INV(RAND(), | beta (a, b, min, max) |
=BETAINV(RAND(), | beta (a, b, min, max) |
=BINOM.INV(n, | binom (n, p) |
=CRITBINOM(n, | binom (n, p) |
=RANDBETWEEN(a, | randint (min, max) |
=a + (b - a)*RAND() | unif (min, max) |
=a + s*RAND() | unif (loc, scale) |
=RAND() | unif |
=IF(RAND() < p, | bern (p) |
=IF(RAND() < p,† | custom (x, prob) |
| Function | Add-in | Becomes in xellstorm |
|---|---|---|
RiskTruncate | @RISK | Truncation: truncate_min, truncate_max (before any shift) |
RiskTruncate2 | @RISK | Truncation: truncate_min, truncate_max of the shifted values (moved back by the shift) |
RiskTruncateP | @RISK | Truncation: truncate_pmin, truncate_pmax (percentiles of the distribution) |
RiskShift | @RISK | Shift: shift |
RiskName | @RISK | Name: the input's name |
RiskLock | @RISK | Lock: a fixed value (RiskLock(v), or the RiskStatic value) |
RiskCorrmat | @RISK | Correlation: rank correlations between the inputs of one matrix |
RiskDepC | @RISK | Correlation: a rank correlation with the input of the same pair name |
RiskIndepC | @RISK | Correlation: a rank correlation with the input of the same pair name |
RiskSimtable | @RISK | One value per simulation: a fixed cell in the base run, one scenario per further simulation |
RiskOutput | @RISK | Output: an output, with the name it gives |
VoseXBounds | ModelRisk | Truncation: truncate_min, truncate_max (before any shift) |
VosePBounds | ModelRisk | Truncation: truncate_pmin, truncate_pmax (percentiles of the distribution) |
VoseShift | ModelRisk | Shift: shift |
VoseInput | ModelRisk | Name: the input's name |
VoseSimTable | ModelRisk | One value per simulation: a fixed cell in the base run, one scenario per further simulation |
VoseOutput | ModelRisk | Output: an output, with the name it gives |
PsiTruncate | Analytic Solver | Truncation: type 1 (the default): truncate_min, truncate_max before any shift; -1: of the shifted values; 3: truncate_pmin, truncate_pmax |
PsiTruncateP | Analytic Solver | Truncation: truncate_pmin, truncate_pmax (percentiles of the distribution) |
PsiShift | Analytic Solver | Shift: shift |
PsiName | Analytic Solver | Name: the input's name |
PsiCorrMatrix | Analytic Solver | Correlation: rank correlations between the inputs of one matrix |
PsiCorrDepen | Analytic Solver | Correlation: a rank correlation with the input of the same pair name |
PsiCorrIndep | Analytic Solver | Correlation: a rank correlation with the input of the same pair name |
PsiSimParam | Analytic Solver | One value per simulation: a fixed cell in the base run, one scenario per further simulation |
PsiOutput | Analytic Solver | Output: an output: the cell itself, or the cells it refers to |
PsiSimOutput | Analytic Solver | Output: an output: the cell itself, or the cells it refers to |
PsiMean | Analytic Solver | Statistic: the cell of its first argument becomes an output (as with every Psi statistic of an output) |
Questions
Do I need @RISK, ModelRisk or Analytic Solver installed?
No. xellstorm reads the formulas from the .xlsx file itself and calculates the model with its own engine in your browser, without Excel or the add-in. Save .xls and .xlsb workbooks as .xlsx first.
Does xellstorm change my workbook?
No. The import turns the formulas into inputs of xellstorm’s own setup; the file on your computer is not written, so the model still opens and runs in the add-in.
What happens to a correlation matrix?
Inputs that share a RiskCorrmat or PsiCorrMatrix range get the rank correlations of the matrix, read from its cells when you import; RiskDepC and PsiCorrDepen pair an input with the one of the same name. Pairs that cannot be read (a matrix that is not square, a position outside it, a cell without a number) are named in the import’s notes, and an input that did not convert is listed with its reason and left out of its pairs. If the matrix is not a valid correlation matrix, xellstorm applies the nearest valid one, and the app shows it before the run.
What does a RiskSimtable become?
The first value holds the cell in the base run and each further value becomes a scenario, named Simulation 2, Simulation 3 and so on. Scenarios draw the same random numbers as the base run, so the differences between them come from the table’s values alone.
@RISK, ModelRisk and Analytic Solver are trademarks of their respective owners. xellstorm is not affiliated with them; their function names appear here only to say what xellstorm reads.
Related
- Project cost and schedule
How much contingency does a construction project need?
Worked example: a building estimate’s most likely costs are exceeded in 94.2% of simulated outcomes. Size the construction cost contingency with Monte Carlo. - Guide
Monte Carlo simulation in Excel, with or without add-ins
Three ways to run a Monte Carlo simulation on an Excel model: RAND() and a data table, an add-in, or a browser tool with no add-in. PERT formula included. - Guide
PERT distribution in Excel: formula, mean and when to use it
A PERT is a beta distribution from min to max with mean (min + 4 × likely + max)/6. The Excel BETA.INV formula, and PERT vs triangular.
xellstorm is a browser-based Monte Carlo simulation tool for Excel models: no add-in, and the workbook never leaves your computer.