spb/traite-evaluation-qc
Public
1#!/usr/bin/env python32"""Figure ch42 — valeur de conversion (somme des fractions nette des coûts, des frais, du portage et des délais) selon la rotation annuelle3des locataires, pour trois décotes de vente occupée, comparée à la valeur en bloc (DONNÉES SYNTHÉTIQUES, immeuble fictif de 8 logements).4Sortie : assets/figures/ch42/ch42-fig-bloc-piece.pdf"""5import sys, pathlib6ROOT = pathlib.Path(__file__).resolve().parents[3]7sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))8import numpy as np, matplotlib.pyplot as plt9from traite.style import setup, palette, savefig, LARGEUR, fmt_dollars10import ch42_copro as cas1112def main():13 setup()14 rhos = np.linspace(0.02, 0.40, 39)15 v_bloc = cas.valeur_bloc()["valeur"]16 fig, ax = plt.subplots(figsize=(LARGEUR, 3.7))17 for i, d in enumerate((0.10, 0.20, 0.30)):18 v = [cas.faisabilite(rho, d)["v_conv"] for rho in rhos]19 ax.plot(rhos * 100, v, color=palette.cat[i], lw=1.8, label=f"Attente des départs ; reliquat vendu occupé à l'an 6 avec décote {d:.0%}")20 vo = cas.faisabilite(cas.ROTATION, d, vendre_occupe=True)["v_conv"]21 ax.scatter([cas.ROTATION * 100], [vo], color=palette.cat[i], marker="D", s=22, zorder=5)22 ax.annotate(f"vente occupée dès l'an 1 (δ = {d:.0%})", xy=(cas.ROTATION * 100, vo), xytext=(cas.ROTATION * 100 + 1.5, vo + 6000), fontsize=7, color=palette.ink2)23 ax.axhline(v_bloc, color=palette.ink2, lw=1.2, ls="--")24 ax.text(40, v_bloc + 8000, f"Valeur en bloc (RNE / 5@25 %) : {v_bloc:,.0f} $".replace(",", " ").replace("@", ","), ha="right", fontsize=7.8, color=palette.ink)25 base = cas.faisabilite()26 ax.scatter([cas.ROTATION * 100], [base["v_conv"]], color=palette.ink, s=26, zorder=6)27 ax.annotate(f"cas de base : ρ = 12 %@ δ = 20 % → {base['v_conv']:,.0f} $".replace(",", " ").replace("@", ","), xy=(cas.ROTATION * 100, base["v_conv"]),28 xytext=(cas.ROTATION * 100 + 1.5, base["v_conv"] - 55000), fontsize=7.2, color=palette.ink,29 arrowprops=dict(arrowstyle="-", color=palette.ink2, lw=0.7))30 ax.set_xlabel("Rotation annuelle des locataires ρ (% des logements occupés libérés par année)")31 ax.set_ylabel("Valeur actualisée à 10 % (dollars de 2026)")32 ax.yaxis.set_major_formatter(plt.FuncFormatter(fmt_dollars))33 ax.set_xlim(0, 41)34 ax.legend(loc="upper center", bbox_to_anchor=(0.45, -0.2), ncol=1, fontsize=7.3)35 out = savefig(fig, "ch42/ch42-fig-bloc-piece.pdf"); print("OK", out)3637if __name__ == "__main__":38 main()39