SPB Git
5.9 KB · 87 lines python
1#!/usr/bin/env python32"""Figures du chapitre 41 (DONNÉES SYNTHÉTIQUES du cas 1 ; zonage FICTIF ; hypothèses déclarées dans ch41_phmu.py) :3  ch41-fig-residuel-densite.pdf   — valeur résiduelle du terrain selon le nombre de logements et le niveau des prix ;4  ch41-fig-surface-prix-cout.pdf  — surface de la valeur résiduelle du triplex (prix des unités × coût de construction) ;5  ch41-fig-frontiere-option.pdf   — prime de l'option de redéveloppement et frontière d'exercice selon la volatilité.6Usage : python3 analysis/python/figures/ch41_figures.py"""7import sys, pathlib8ROOT = pathlib.Path(__file__).resolve().parents[3]9sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))10import numpy as np, matplotlib.pyplot as plt11from matplotlib.ticker import FuncFormatter12from traite.style import setup, palette, savefig, LARGEUR13import ch41_phmu as cas1415K = FuncFormatter(lambda x, p: f"{x/1000:.0f}")161718def fig_densite(R):19    df = cas.courbe_densite(R, R["couts"])20    fig, ax = plt.subplots(figsize=(LARGEUR, 3.1))21    for k, f in enumerate(sorted(df.facteur_prix.unique())):22        d = df[df.facteur_prix == f].sort_values("n")23        lab = {0.85: "prix des unités −15 %", 1.0: "prix de base (modèle hédonique)", 1.15: "prix des unités +15 %"}[round(f, 2)]24        ax.plot(d.n, d.v_l, marker="o", color=palette.cat[k], label=lab)25        np_ = d[~d.permis]26        ax.plot(np_.n, np_.v_l, marker="o", linestyle="none", markerfacecolor="white", color=palette.cat[k])27    ax.axhline(R["v_l_marche"], color=palette.ink2, linestyle="--", linewidth=1)28    ax.text(2.55, R["v_l_marche"] + 6000, "valeur du terrain par comparaison (ch. 25) : 277 000 $", fontsize=7.5, color=palette.ink2)29    occ = R["usages"]["U"]["occupant"]["valeur_residuelle"]30    ax.plot([1], [occ], marker="s", color=palette.ink, linestyle="none")31    ax.annotate("maison neuve, convention\n« construction sur commande »\n(266 187 $)", (1, occ), xytext=(1.3, occ - 60000), fontsize=7.5,32                arrowprops=dict(arrowstyle="-", color=palette.ink2, lw=0.8))33    ax.axvspan(3.5, 4.5, color=palette.grid, alpha=0.6, lw=0)34    ax.text(4, 20000, "non permis\n(COS 0,60)", ha="center", fontsize=7.5, color=palette.ink2)35    ax.set_xticks([1, 2, 3, 4]); ax.set_xticklabels(["1 logement\n(maison neuve)", "2 logements\n(duplex)", "3 logements\n(triplex)", "4 logements\n(quadruplex)"])36    ax.set_xlim(0.7, 4.5); ax.set_ylim(0, None)37    ax.yaxis.set_major_formatter(K); ax.set_ylabel("Valeur résiduelle du terrain (milliers de $)")38    ax.legend(loc="lower right", fontsize=7.5, bbox_to_anchor=(0.78, 0.02))39    fig.tight_layout(); savefig(fig, "ch41/ch41-fig-residuel-densite.pdf")404142def fig_surface(R):43    fp, fc, Z = cas.surface_prix_cout(R["usages"]["T"], R["couts"], fp=np.linspace(0.80, 1.55, 76))44    X, Y = fp * 100 - 100, fc * 100 - 10045    fig, ax = plt.subplots(figsize=(LARGEUR, 3.4))46    cf = ax.contourf(X, Y, np.clip(Z, 0, None) / 1000, levels=24, cmap=palette.cmap_seq())47    cb = fig.colorbar(cf, ax=ax, pad=0.02); cb.set_label("Valeur résiduelle du terrain (milliers de $)")48    cs = ax.contour(X, Y, Z, levels=[0, R["v_l_marche"], R["v_act"]], colors=[palette.ink2, palette.ink, palette.ink], linewidths=[0.9, 1.0, 1.4], linestyles=["dotted", "dashed", "solid"])49    ax.clabel(cs, fmt={0: "résidu nul", R["v_l_marche"]: "277 000 $ : terrain au prix du marché", R["v_act"]: "600 000 $ : démolition rentable"}, fontsize=7, inline=True, inline_spacing=6)50    ax.plot([0], [0], marker="o", color=palette.ink, markersize=5)51    ax.annotate("cas de base : 229 265 $", (0, 0), xytext=(-18, -8), fontsize=7.5, color=palette.ink, arrowprops=dict(arrowstyle="-", color=palette.ink, lw=0.7))52    ax.set_xlabel("Variation du prix des unités neuves (%)"); ax.set_ylabel("Variation du coût de construction (%)")53    ax.grid(False)54    fig.tight_layout(); savefig(fig, "ch41/ch41-fig-surface-prix-cout.pdf")555657def fig_frontiere(R):58    O = cas.OPTION; rT = R["usages"]["T"]["promoteur"]; gdv0 = rT["gdv"]59    sigmas = np.linspace(0.03, 0.30, 55)60    fig, (a, b) = plt.subplots(1, 2, figsize=(LARGEUR, 3.1))61    for k, v_act in enumerate((600_000.0, 450_000.0, 300_000.0)):62        aa, bb = cas.coefficients_option(rT, v_act)63        prem = [cas.option_redeveloppement(gdv0, aa, bb, s, O["dt"], O["r"], O["y"], O["n"])["prime_americaine"] for s in sigmas]64        a.plot(sigmas * 100, np.array(prem) / 1000, color=palette.cat[k], label=f"valeur en usage {v_act/1000:.0f} k$")65    a.set_xlabel("Volatilité annuelle du prix des unités σ (%)"); a.set_ylabel("Prime de l'option (milliers de $)")66    a.set_title("(a) valeur de l'attente", loc="left"); a.legend(fontsize=7.5)67    aa, bb = cas.coefficients_option(rT, R["v_act"])68    seuil_van = bb / aa / gdv069    front = [cas.frontiere_exercice_t1(aa, bb, s, O["dt"], O["r"], O["y"]) / gdv0 for s in sigmas]70    b.plot(sigmas * 100, np.array(front), color=palette.cat[0], label="frontière d'exercice (attente optimale au-dessous)")71    b.axhline(seuil_van, color=palette.cat[1], linestyle="--", label="seuil de la règle de la VAN (résidu = valeur en usage)")72    b.axhline(1.0, color=palette.ink2, linestyle=":", linewidth=1); b.text(3.5, 1.02, "produit de vente actuel", fontsize=7.5, color=palette.ink2)73    b.fill_between(sigmas * 100, seuil_van, np.array(front), color=palette.cat[0], alpha=0.12, lw=0)74    b.text(16, (seuil_van + 1.9) / 2, "zone d'attente :\nVAN > 0 mais attendre vaut plus", fontsize=7.5, ha="center", color=palette.ink)75    b.set_xlabel("Volatilité annuelle du prix des unités σ (%)"); b.set_ylabel("Produit de vente / produit actuel")76    b.set_ylim(0.9, 2.6); b.set_title("(b) frontière d'exercice au nœud t = 1", loc="left"); b.legend(fontsize=7, loc="upper left")77    fig.tight_layout(); savefig(fig, "ch41/ch41-fig-frontiere-option.pdf")787980def main():81    setup(); R = cas.exemple_complet()82    fig_densite(R); fig_surface(R); fig_frontiere(R)838485if __name__ == "__main__":86    main()87
Files · 031fae1bd368de12dc60ff542f1be9a8fd73e699
Menu

Theme