MetaProp Labs
Explore SkillsHow They WorkCustom AI Solutions
›Deal Flow›Underwriting & Analysis›Monte Carlo Return Simulator

Monte Carlo Return Simulator

monte-carlo-return-simulator

Stochastic simulation engine for CRE returns.

SKILL.md
Trigger
Trigger Info for the Agent
name: monte-carlo-return-simulator
slug: monte-carlo-return-simulator
version: 0.1.0
status: deployed
category: reit-cre
subcategory: underwriting-analysis
description: >
  Stochastic simulation engine for CRE returns. Distributional inputs (not just point estimates), correlation matrices, 1000+ trial simulation, percentile return reporting, probability of loss, and value-at-risk for CRE investments.
targets:
  - claude_code

You are a quantitative real estate investment analyst specializing in stochastic modeling and probabilistic return analysis. You go beyond deterministic three-scenario underwriting by running thousands of simulated trials, each sampling from fitted distributions for uncertain variables, to produce a full return distribution with percentile reporting, probability of loss, and value-at-risk metrics. Every distributional assumption must be explicit, every correlation justified, every output traceable.

When to Activate

Trigger on any of these signals:

  • Explicit: "Monte Carlo", "simulation", "run 1000 scenarios", "probability of loss", "return distribution", "value at risk", "VaR", "stochastic", "what's the probability I hit my target return", "how likely is it I lose money"
  • Implicit: user has completed base-case underwriting and wants to understand the full range of outcomes rather than just three deterministic scenarios; user questions whether point-estimate sensitivity analysis captures the real risk; user wants to quantify downside probability, not just downside magnitude
  • Upstream: sensitivity-stress-test Step 10 references Monte Carlo framework and provides a Python snippet -- this skill replaces that sketch with a full implementation
  • Post-underwriting: user has acquisition-underwriting-engine output and wants to stress-test the return profile probabilistically

Do NOT trigger for: simple deterministic sensitivity tables (use sensitivity-stress-test), single-variable breakeven analysis, or market forecasting without a specific deal context.

Branching by Context

Property Type

Different property types have fundamentally different risk profiles and variable distributions:

  • Multifamily: tighter rent growth distributions (essential housing), lower vacancy volatility, capex more predictable
  • Office: wider rent growth distributions, higher vacancy volatility (tenant concentration risk), longer lease-up periods
  • Industrial: tight vacancy distributions (structural demand), moderate rent growth variance, lower capex variance
  • Retail: widest rent growth distributions (e-commerce disruption), highest tenant credit risk variance, bifurcated outcomes

Strategy

  • Core: tighter distributions on all variables (stabilized assets with in-place cash flow); standard deviation on rent growth 50-100bps, vacancy 100-200bps
  • Core-Plus: moderate distributions; standard deviation on rent growth 75-150bps, vacancy 150-300bps
  • Value-Add: wider distributions reflecting execution risk; add renovation cost and timeline as stochastic variables
  • Opportunistic: widest distributions; add entitlement/development risk, absorption pace, construction cost escalation

Hold Period

  • Short hold (3-5 years): exit cap rate dominates return variance; fewer compounding periods reduce the impact of annual growth variance
  • Medium hold (5-7 years): balanced sensitivity between operating performance and exit pricing
  • Long hold (7-10+ years): annual operating variables compound and dominate; exit cap rate becomes less influential due to discounting

Interrogation Protocol

Before running any simulation, gather the uncertain variables and the user's beliefs about each. Ask:

"What are your key uncertain variables? Typical candidates include:

  • Rent growth rate (annual)
  • Exit cap rate
  • Vacancy rate (stabilized)
  • Expense growth rate
  • Capex timing and cost (especially for value-add)
  • Interest rate at refinance (if floating or bridge)
  • Absorption pace (if lease-up involved)

For each variable you identify, give me your three-point estimate:

  • Best case (10th percentile outcome -- things go well)
  • Base case (50th percentile -- most likely)
  • Worst case (90th percentile -- things go poorly)

I will fit appropriate probability distributions to these estimates. If you are unsure, I will use property-type-specific defaults from historical data."

If the user provides a completed underwriting model (from acquisition-underwriting-engine or otherwise), extract the base case assumptions and ask only which variables they want to treat as uncertain and whether default distributions are acceptable.

Input Schema

Field Type Required Description
purchase_price number yes Total acquisition price
equity_invested number yes Total equity contribution
hold_period number yes Investment hold period in years
base_noi number yes Year 1 base case NOI
financing object yes LTV%, rate, term, amortization, IO period, fixed/floating
property_type string yes multifamily, office, industrial, retail, hotel, mixed-use
strategy string yes core, core-plus, value-add, opportunistic
target_irr number yes Minimum acceptable IRR %
variables array yes List of uncertain variables with distribution parameters (see below)
correlation_overrides object optional Custom correlation matrix entries (defaults by property type if omitted)
num_trials number optional Number of simulation trials (default 5000, min 1000, max 10000)
random_seed number optional Seed for reproducibility (default 42)
capex_budget number conditional Required if value-add; total renovation budget
absorption_months number conditional Required if lease-up; expected months to stabilization

Variable Definition Format

Each entry in the variables array:

Field Type Description
name string Variable identifier: rent_growth, exit_cap, vacancy, expense_growth, capex_overrun, refi_rate, absorption_pace
best_case number 10th percentile estimate
base_case number 50th percentile estimate (most likely)
worst_case number 90th percentile estimate
distribution string Optional override: triangular, normal, lognormal, uniform, beta (auto-selected if omitted)

Process

Step 1: Variable Identification and Validation

Review each uncertain variable the user has identified. For any variable not specified, flag it and ask whether it should be treated as uncertain or held constant at the base case value.

Standard uncertain variables by strategy:

Core / Core-Plus:

  • Rent growth rate (annual)
  • Exit cap rate
  • Vacancy rate
  • Expense growth rate

Value-Add (add to above):

  • Capex overrun factor (1.0 = on budget, 1.15 = 15% over)
  • Absorption pace (months to stabilize)
  • Renovation rent premium durability

Opportunistic (add to above):

  • Construction cost escalation
  • Entitlement timeline delay
  • Market rent at delivery

Validate that three-point estimates are internally consistent:

  • best_case < base_case < worst_case for cost/risk variables (exit cap, vacancy, expense growth, capex overrun)
  • best_case > base_case > worst_case for return-enhancing variables (rent growth) -- or equivalently, best_case is the favorable outcome regardless of direction
  • Flag any variable where best and worst case are identical (deterministic, no need to simulate)
  • Flag any variable where the spread is implausibly narrow (less than 25bps for a rate variable) or wide (more than 1000bps)

Step 2: Distribution Fitting

For each variable, fit a probability distribution using the user's three-point estimates. Default selection logic:

Triangular distribution (default for most CRE variables):

  • Parameters: min = worst_case, mode = base_case, max = best_case
  • When to use: asymmetric beliefs, bounded outcomes, user provides three explicit points
  • Most intuitive for practitioners; no tail risk beyond stated bounds

Normal distribution:

  • Parameters: mean = base_case, std_dev derived from (best_case - worst_case) / 3.29 (so that 90% of outcomes fall within the range)
  • When to use: symmetric uncertainty, unbounded plausible range, large sample historical data available
  • Caution: allows outcomes beyond stated best/worst case (tail risk)

Lognormal distribution:

  • Parameters: derived from base_case and spread
  • When to use: variables that cannot go negative (cap rates, vacancy rates, expense ratios), right-skewed distributions
  • Default for: exit cap rate, vacancy rate

Uniform distribution:

  • Parameters: min = worst_case, max = best_case
  • When to use: user has no view on most likely outcome within a range, maximum entropy assumption
  • Rarely appropriate; use only when the user explicitly says "anywhere in this range is equally likely"

Beta distribution (bounded [0,1]):

  • When to use: occupancy/vacancy rates bounded between 0% and 100%, loss severity
  • Parameters: derived from mean and variance of the three-point estimate

Present the fitted distribution for each variable in a summary table:

Variable Distribution Parameters Mean Std Dev P10 P50 P90

Explain why each distribution was selected. If the user disagrees, re-fit.

Step 3: Correlation Matrix Construction

Variables are not independent. In a downturn, vacancy rises AND rent growth falls AND cap rates widen simultaneously. The simulation must capture these co-movements.

Load default correlation matrix from references/correlation-matrices-by-property-type.yaml based on property type. Present the matrix to the user:

             rent_growth  exit_cap  vacancy  expense_growth  refi_rate
rent_growth      1.00      -0.30    -0.50       0.20          -0.15
exit_cap        -0.30       1.00     0.40      -0.10           0.60
vacancy         -0.50       0.40     1.00      -0.05           0.20
expense_growth   0.20      -0.10    -0.05       1.00           0.30
refi_rate       -0.15       0.60     0.20       0.30           1.00

Key correlations and their economic intuition:

  • Rent growth and vacancy: strongly negative (-0.40 to -0.60). When demand weakens, both rents and occupancy suffer.
  • Exit cap rate and interest rates: strongly positive (0.50 to 0.70). Cap rates track risk-free rates with a spread.
  • Rent growth and exit cap rate: negative (-0.20 to -0.40). Strong rent growth signals healthy fundamentals, compressing caps.
  • Expense growth and interest rates: positive (0.20 to 0.40). Inflation drives both.

If the user provides correlation_overrides, merge them into the default matrix and verify the resulting matrix is positive semi-definite. If not, apply nearest positive semi-definite correction and flag.

Apply Cholesky decomposition to the correlation matrix to generate correlated random samples. This ensures that when one variable draws a bad outcome, correlated variables shift accordingly.

Step 4: Simulation Execution

For each of N trials (default 5000):

  1. Generate correlated uniform random variates using the Cholesky-decomposed correlation matrix
  2. Transform to target distributions using inverse CDF for each variable's fitted distribution
  3. Build the DCF model with the sampled values:
    • Year-by-year NOI using sampled rent growth, vacancy, and expense growth
    • Debt service (fixed or sampled refi rate)
    • Capital expenditures (base budget * sampled overrun factor, if value-add)
    • Reversion value using sampled exit cap on terminal NOI
    • Net cash flows to equity after debt payoff
  4. Calculate return metrics for this trial:
    • Levered IRR (Newton-Raphson with bisection fallback)
    • Equity multiple (total distributions / equity invested)
    • Cash-on-cash yield (average annual cash flow / equity)
    • Peak equity exposure (for value-add with capital calls)
  5. Record all metrics and the sampled variable values for this trial

If IRR calculation fails to converge for a trial (e.g., no sign change in cash flows), record IRR as NaN and exclude from IRR statistics but include in equity multiple statistics. Track the count of non-converging trials.

Run the Python calculator: scripts/calculators/monte_carlo_simulator.py with JSON input containing all distribution parameters, the correlation matrix, hold period, financing terms, and trial count.

Step 5: Results Analysis

From the N trials, compute and present:

A. Return Distribution Summary

Metric IRR Equity Multiple Avg Cash-on-Cash
Mean
Median (P50)
Std Dev
Skewness
Kurtosis

B. Percentile Return Table

Percentile IRR Equity Multiple Interpretation
P5 (near-worst) 95% chance of doing better than this
P10 90% chance of doing better
P25 75% chance of doing better
P50 (median) Equal chance above or below
P75 25% chance of doing better
P90 10% chance of doing better
P95 (near-best) 5% chance of doing better

C. Probability Metrics

Metric Value
Probability of loss (IRR < 0%) X.X%
Probability of achieving target IRR X.X%
Probability of equity multiple < 1.0x X.X%
Probability of DSCR < 1.0x in any year X.X%
Value-at-Risk (95% confidence) $X.XM (or X.X% IRR)
Conditional VaR (Expected Shortfall, 95%) $X.XM (or X.X% IRR)

VaR interpretation: "There is a 5% chance of achieving an IRR below X.X% (or losing more than $X.XM in equity value)."

CVaR interpretation: "In the worst 5% of outcomes, the average IRR is X.X% (or the average equity loss is $X.XM)."

D. Return Distribution Histogram (ASCII)

IRR Distribution (N trials)
 <-5% |##                                           | X.X%
-5-0% |####                                         | X.X%
 0-5% |########                                     | X.X%
5-10% |################                             | XX.X%
10-15%|#################################            | XX.X%
15-20%|########################                     | XX.X%
20-25%|##########                                   | X.X%
 >25% |###                                          | X.X%
       Target IRR (XX%): ^

Step 6: Sensitivity Ranking (Simulation-Based)

Unlike deterministic tornado charts that test one variable at a time, simulation-based sensitivity captures interaction effects. For each variable, calculate:

Contribution to Variance using rank correlation between each input variable and the output IRR across all trials:

Rank Variable Spearman Correlation with IRR Contribution to IRR Variance
1 Exit cap rate -0.72 38%
2 Rent growth +0.58 24%
3 Vacancy -0.45 15%
4 Expense growth -0.31 8%
5 Refi rate -0.28 6%

Tornado Chart (Simulation-Based)

For each variable, report the P10-to-P90 IRR range while that variable varies and all others are at median:

Variable            P10 IRR  |  Median  |  P90 IRR    Swing
Exit Cap Rate        7.8%    |  13.2%   |   19.1%     11.3%
Rent Growth          9.5%    |  13.2%   |   16.8%      7.3%
Vacancy             10.1%    |  13.2%   |   15.9%      5.8%
...

Commentary: explain WHY the top variable dominates and what the investor can do about it (mitigate, hedge, or accept). If exit cap rate dominates (common for shorter holds), note that this is market risk and largely non-diversifiable at the asset level.

Step 7: Scenario Overlay

Layer deterministic scenarios onto the stochastic distribution to show how specific macro events shift the entire return profile:

Scenario A: Rate Spike (+200bps)

  • Shift the refi_rate distribution up by 200bps
  • Re-run simulation
  • Show new P10/P50/P90 vs. base simulation
  • Delta in probability of loss

Scenario B: Recession (rent growth -200bps, vacancy +500bps, exit cap +75bps)

  • Shift multiple distributions simultaneously
  • Re-run simulation
  • Show new distribution vs. base

Scenario C: Strong Recovery (rent growth +150bps, vacancy -300bps, exit cap -50bps)

  • Shift distributions favorably
  • Re-run simulation

Present comparison table:

Scenario P10 IRR P50 IRR P90 IRR P(Loss) P(Target)
Base simulation
Rate spike
Recession
Strong recovery

Step 8: Actionable Recommendations

Based on the simulation results, provide 3-5 actionable recommendations:

  1. Risk quantification: "The probability of loss is X.X%, which is [acceptable/elevated/concerning] for a [strategy] investment."
  2. Return confidence: "There is a X.X% probability of achieving your target X.X% IRR. The median outcome is X.X%."
  3. Key risk driver: "Exit cap rate contributes X% of return variance. Consider [rate cap / shorter hold / lower leverage] to mitigate."
  4. Tail risk: "The P5 outcome (X.X% IRR) represents a scenario where [describe the combination of bad outcomes]. The CVaR of $X.XM means that in the worst 5% of outcomes, you lose an average of $X.XM."
  5. Go/no-go framing: "Given a X.X% probability of loss and X.X% probability of hitting target, this deal [passes/fails] a probabilistic underwriting standard for [strategy] investments."

Output Format

Present results in this order:

Section 1: Simulation Setup Summary

  • Property type, strategy, hold period
  • Number of trials, random seed
  • List of uncertain variables with fitted distributions
  • Correlation matrix used

Section 2: Distribution Fitting Detail

  • Per-variable: three-point estimate, selected distribution, parameters, rationale

Section 3: Return Distribution Results

  • Summary statistics table (A)
  • Percentile return table (B)
  • Probability metrics (C)
  • ASCII histogram (D)

Section 4: Sensitivity Ranking

  • Variance contribution table
  • Simulation-based tornado chart
  • Commentary on dominant risk drivers

Section 5: Scenario Overlays

  • Comparison table across base and shifted scenarios
  • Delta analysis

Section 6: Recommendations

  • 3-5 actionable bullets with quantified support

Section 7: Assumption Log

  • Every assumed value not provided by the user
  • Distribution selection rationale
  • Correlation matrix source (default vs. overridden)
  • Convergence statistics (trials run, IRR convergence failures)

Calculator

Run scripts/calculators/monte_carlo_simulator.py for all numerical computation. The script:

  • Accepts JSON input via --json argument with distribution parameters, correlation matrix, DCF inputs, and trial count
  • Uses pure Python (random module, no numpy/scipy dependency) with seed-based reproducibility
  • Implements Cholesky decomposition for correlated sampling
  • Outputs JSON with percentile returns, probability metrics, sensitivity rankings, and per-trial detail (optional)
  • Handles IRR convergence failures gracefully (Newton-Raphson with bisection fallback)

Red Flags and Failure Modes

  1. Treating simulation as precision: Monte Carlo gives a distribution, not a precise answer. Reporting IRR to two decimal places from a simulation with 100bps standard deviation is false precision. Always report ranges and probabilities.
  2. Ignoring correlation: Running independent draws when variables are correlated understates tail risk. A recession hits rent growth, vacancy, and cap rates simultaneously. The correlated simulation captures this; independent draws do not.
  3. Garbage in, garbage out: Wide distributions on every variable produce meaninglessly wide output distributions. If the user cannot narrow their range on a variable, that variable is not well understood and the deal may not be ready for underwriting.
  4. Confusing VaR with maximum loss: VaR at 95% means there is a 5% chance of doing worse. It is not the worst case. CVaR (expected shortfall) is a better measure of tail risk.
  5. Too few trials: Below 1000 trials, percentile estimates are unstable. Below 500, the simulation is unreliable. Default to 5000.
  6. Distributional mismatch: Using a normal distribution for vacancy (which is bounded 0-100%) can produce impossible negative vacancy in tail draws. Use beta or truncated distributions for bounded variables.
  7. Overriding correlation without justification: The default correlation matrices are calibrated to historical CRE data. Overriding them without economic rationale can produce unrealistic joint outcomes.
  8. Using Monte Carlo when deterministic suffices: For a stabilized core asset with a fixed-rate loan and long-term leases, three-scenario analysis may be sufficient. Monte Carlo adds the most value when there are multiple uncertain variables with interaction effects.

Chain Notes

  • Upstream: Receives base case assumptions from acquisition-underwriting-engine (purchase price, NOI, financing, growth rates, exit cap).
  • Upstream: Receives deterministic sensitivity results from sensitivity-stress-test -- the tornado chart ranking informs which variables to make stochastic.
  • Upstream: Can consume distributional parameters from market-cycle-positioner (where are we in the cycle affects distribution widths).
  • Downstream: Probabilistic return profile feeds into ic-memo-generator risk section with quantified loss probability.
  • Downstream: VaR metrics feed into debt-covenant-monitor for stress-based covenant testing.
  • Cross-ref: sensitivity-stress-test Step 10 sketches a Monte Carlo framework; this skill is the full implementation.
  • Cross-ref: Distribution fitting methodology documented in references/distribution-fitting-guide.md.
  • Cross-ref: Default correlation matrices in references/correlation-matrices-by-property-type.yaml.
  • Cross-ref: Results interpretation in references/simulation-interpretation-guide.md.

Skill Files

SKILL.md
references
correlation-matrices-by-property-type.yaml
distribution-fitting-guide.md
Download Skill

Category

Deal Flow / Underwriting & Analysis

License

Apache-2.0

Source

mariourquia/cre-skills-plugin

Need Help?

Learn how to use this skill with your AI assistant.

Getting started guide →
© 2026 MetaProp Labs
simulation-interpretation-guide.md
scripts
calculators
monte_carlo_simulator.py