import sys, numpy as np, matplotlib.pyplot as plt
sys.path.insert(0,'..')
from engine import ch12
from dataclasses import replaceMFAA Chapter 12 Laboratory
Real Asset Cash-Flow Engine (book §12.9)
Value layered real-asset claims: lease ladders on market-rent dynamics, regime cap rates, development options. ‘Slow numerator, fast denominator.’ Seed 20261200.
1. E1 / Ex 12.10 — Slow numerator, fast denominator (Proposition 12.4)
The rent roll low-passes market rent; g(κℓ) drops from 0.5677 (ℓ=5) to 0.3773 (ℓ=10).
for ell in (5.0, 10.0):
print(f"lease term {ell}y: low-pass ratio g(kappa*ell) = {ch12.lowpass_ratio(0.4, ell):.4f}")
sim = ch12.rent_roll_simulation(ch12.RealAssetParams(M=2000))
t = sim['tgrid']
plt.plot(t, sim['market_rent'].mean(axis=1), label='market rent (mean)')
plt.plot(t, sim['rent_roll'].mean(axis=1), label='rent roll (mean)')
plt.fill_between(t, np.quantile(sim['market_rent'],.05,axis=1), np.quantile(sim['market_rent'],.95,axis=1), alpha=.15)
plt.legend(); plt.title('The ladder low-passes the market'); plt.xlabel('years')lease term 5.0y: low-pass ratio g(kappa*ell) = 0.5677
lease term 10.0y: low-pass ratio g(kappa*ell) = 0.3773
Text(0.5, 0, 'years')

2. The value fan under regime cap rates
Value volatility is dominated by the fast-moving denominator.
vf = ch12.value_fan(ch12.RealAssetParams(M=4000))
t = vf['tgrid']
plt.plot(t, vf['value'].mean(axis=1), 'C0-')
plt.fill_between(t, np.quantile(vf['value'],.05,axis=1), np.quantile(vf['value'],.95,axis=1), alpha=.2)
plt.title('Value fan V = NOI / cap rate'); plt.xlabel('years')
print(f"variance share: numerator {vf['numerator_var_share']:.2f}, denominator {vf['denominator_var_share']:.2f}")variance share: numerator 0.35, denominator 0.65

3. Ex 12.12 — The development option (Proposition 12.6)
β=1.406, V*=3.46K at σ=0.25, ρ=6%, μ=3%. The NPV rule builds too early.
do = ch12.development_option(ch12.RealAssetParams(dev_sigma=0.25, dev_rho=0.06, dev_mu=0.03), V=1.2)
print(f"beta = {do['beta']:.3f}, V* = {do['V_star_over_K']:.2f}K")
print(f"land value at V=1.2K: {do['land_value_over_K']:.3f}K (optimal), NPV rule: {do['npv_rule_value']:.3f}K")
print(f"value lost by NPV rule: {do['value_lost_fraction']*100:.0f}%")beta = 1.406, V* = 3.46K
land value at V=1.2K: 0.555K (optimal), NPV rule: 0.200K
value lost by NPV rule: 64%
4. Validation checks
v = ch12.validation_checks()
for k,d in v.items():
if isinstance(d,dict): print(k, 'PASS' if d['pass_'] else 'FAIL')
print('ALL:', v['all_pass'])V1_lowpass PASS
V2_development PASS
V3_development_mc PASS
V4_lowpass_monotone PASS
V5_hurdle_in_sigma PASS
V6_reproducible PASS
ALL: True