A full quantitative framework for decomposing commercial real estate cap rates into fundamental components, estimating equilibrium valuations, and forecasting expected returns under macro scenarios.
This project answers a different question than a relative-value ranking tool: instead of "which sector is cheapest right now?", it asks:
"Why is the cap rate where it is? What should it be given the interest rate environment? Where is it going? And what does that imply for expected returns under different macro scenarios?"
These are the core analytical questions in AEW Capital Management's quarterly U.S. Research Perspectives.
Cap Rate Decomposition — Current Readings:
| Sector | Cap Rate | 10Y Treasury | Spread | Implied RP | Valuation |
|---|---|---|---|---|---|
| Apartment | 4.80% | 4.50% | ~30 bps | 2.4% | Cheap |
| Industrial | 4.55% | 4.50% | ~5 bps | 4.7% | Cheap |
| Office | 10.75% | 4.50% | 625 bps | 6.4% | Cheap |
| Retail | 5.62% | 4.50% | ~110 bps | 2.5% | Fair |
NOI Growth Model RMSE (walk-forward out-of-sample):
| Sector | Trailing Avg | Macro OLS | ECM | Ensemble |
|---|---|---|---|---|
| Apartment | 5.4% | 4.4% | 5.2% | 4.7% |
| Industrial | 7.8% | 6.1% | 7.4% | 6.6% |
| Office | 5.6% | 4.8% | 6.1% | 5.0% |
| Retail | 6.9% | 5.8% | 7.1% | 6.1% |
Macro OLS (GDP + unemployment + multifamily starts) consistently outperforms the naive trailing average. Ensemble is second-best in all sectors.
Cap Rate Mean-Reversion Half-Lives (from AR(1) calibration):
- Apartment: ~21 quarters (5.3 years)
- Industrial: ~34 quarters (8.5 years)
- Retail: ~28 quarters (7 years)
- Office: ~34 quarters (8.5 years)
Private real estate cap rates are highly persistent — the equilibrium signal matters over multi-year horizons, not quarters.
Cap Rate = RF + RP − g
→ RP_implied = Cap Rate − RF + g
Three spread signals are computed:
- Spread over 10Y Treasury: compensation over risk-free
- Spread over BAA corporate bonds: incremental property-vs-credit premium
- Property-to-Credit Spread (R − BAA): how much extra vs liquid credit markets
A narrowing property-to-credit spread (R < BAA) is a historically reliable signal of private market overvaluation.
The fair-value cap rate anchors to long-run structural constants:
R_eq(t) = RF(t) + RP_LR − g_LR
Sector-calibrated long-run constants:
| Sector | LR Risk Premium | LR NOI Growth |
|---|---|---|
| Apartment | 180 bps | 2.5% |
| Industrial | 195 bps | 3.2% |
| Retail | 215 bps | 1.8% |
| Office | 235 bps | 1.5% |
The Cap Rate Gap (actual − equilibrium) reverts toward zero with empirically calibrated half-lives of 5–9 years.
| Model | Method | Inputs |
|---|---|---|
| Trailing Average | 4-quarter rolling mean | Past NOI growth |
| Macro OLS | Walk-forward OLS | GDP growth, unemployment, multifamily starts |
| Error-Correction (ECM) | Mean-reversion to equilibrium | Past g, RF change, gap from LR |
An equal-weight ensemble consistently outperforms any single model.
E[R_total_ann] = Cap Rate + g_forecast + κ · Gap
Where:
κ= mean-reversion speed (calibrated per sector, ~0.02–0.03/quarter)Gap= current cap rate minus equilibrium cap rate (positive = tailwind)- Positive gap (cap rate above equilibrium) → partial gap closure → appreciation tailwind
Three macro scenarios applied to each sector:
| Scenario | RF Change | g_NOI Change |
|---|---|---|
| Bull | −100 bps | +50 bps |
| Base | 0 bps | 0 bps |
| Bear | +150 bps | −100 bps |
Implied expected returns under each scenario, by sector.
cap-rate-decomposition/
│
├── run_analysis.py ← CLI entry point
├── requirements.txt
├── setup.py
├── README.md
├── .gitignore
├── LICENSE
│
├── src/
│ └── caprate/
│ ├── data/
│ │ └── loader.py ← NCREIF + FRED + CBRE assembler
│ ├── models/
│ │ ├── decomposition.py ← RF + RP − g decomposition
│ │ ├── noi_growth.py ← Three-model NOI growth forecasting
│ │ └── equilibrium.py ← Equilibrium cap rate + scenarios
│ └── viz/
│ └── charts.py ← 8 publication-quality figures
│
├── data/
│ └── raw/
│ ├── ncreif_npi.csv ← 400 quarters NPI (2000–2024)
│ └── cbre_survey.csv ← CBRE cap rate survey (2019–2024)
│
└── outputs/ ← Generated on run
├── figures/
│ ├── fig1_cap_rate_history.png ← AEW "Figure 7" replication
│ ├── fig2_decomposition_dashboard.png ← Centrepiece figure
│ ├── fig3_implied_risk_premium.png
│ ├── fig4_prop_to_credit_spread.png
│ ├── fig5_equilibrium_and_gap.png
│ ├── fig6_noi_growth_models.png
│ ├── fig7_scenarios.png
│ └── fig8_regime_spreads.png
└── tables/
├── decomposition_latest.csv
├── spread_statistics.csv
├── noi_model_evaluation.csv
├── expected_returns_latest.csv
└── scenarios.csv
git clone https://github.com/YOUR_USERNAME/cap-rate-decomposition.git
cd cap-rate-decomposition
pip install -r requirements.txtNo API key required (demo mode):
python run_analysis.py --no-fredWith live FRED macro data (recommended):
export FRED_API_KEY=your_free_key # fred.stlouisfed.org
python run_analysis.pyQuick outputs:
# Print current decomposition scorecard only
python run_analysis.py --scorecard-only
# Print scenario analysis only
python run_analysis.py --scenarios-onlyUse as a library:
from src.caprate.data.loader import DataLoader
from src.caprate.models.decomposition import CapRateDecomposer
from src.caprate.models.equilibrium import EquilibriumModel
data = DataLoader(fred_api_key="your_key").build_panel()
decomp = CapRateDecomposer(data["panel"]).decompose()
eq = EquilibriumModel(decomp).compute_expected_returns()
scen = EquilibriumModel(decomp).scenarios()| Reference | Applied In |
|---|---|
| AEW U.S. Research Perspectives (2000–2025), Figure 7 | Decomposition framework |
| Gordon (1959) — Dividends, Earnings and Stock Prices | GGM expected return |
| Geltner & Miller (2007) — Commercial Real Estate Analysis | Cap rate theory |
| Campbell & Shiller (1988) — Stock Prices, Earnings, and Expected Dividends | Error-correction model |
| Engle & Granger (1987) — Co-Integration and Error Correction | ECM specification |
This project is the analytical foundation under the AEW Relative Value Index:
| Project | Question | Outputs |
|---|---|---|
| This project | Why is the cap rate here? What should it be? Where is it going? | Decomposition, equilibrium, scenarios |
| AEW RVI Replication | Which sector is cheapest right now? | Composite score, sector ranking |
The two repos are designed to be used together: run this project first to understand the fundamental drivers, then use the RVI to rank sectors for capital allocation.
Not affiliated with or endorsed by AEW Capital Management. All analysis is for educational and research purposes.