#!/usr/bin/env python3 """Figure ch04 — taux effectif des droits sur les mutations immobilières (droit / base d'imposition) selon la base, barèmes 2026 : barème légal provincial (LDMI art. 2), Montréal, Gatineau (dès le 25 février 2026), Ville de Québec. Calcul de l'auteur (ch04_marches.droits_mutation) à partir des tranches publiées (sources : LégisQuébec, montreal.ca, gatineau.ca, ville.quebec.qc.ca, consultées le 2026-10-31). Sortie : assets/figures/ch04/ch04-fig-mutations.pdf""" import sys, pathlib ROOT = pathlib.Path(__file__).resolve().parents[3] sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases")) import numpy as np, matplotlib.pyplot as plt from matplotlib.ticker import FuncFormatter from traite.style import setup, palette, savefig, LARGEUR import ch04_marches as cas def main(): setup() prix = np.linspace(100000, 3500000, 681) fig, ax = plt.subplots(figsize=(LARGEUR, 3.1)) for i, (nom, bar) in enumerate(cas.BAREMES_2026.items()): te = np.array([cas.droits_mutation(p, bar) / p for p in prix]) * 100 ax.plot(prix / 1000, te, color=palette.cat[i], lw=1.6 if i else 1.2, ls="--" if i == 0 else "-", label=nom) for p, lab, y in [(500000, "500 000 $ : médiane unifamiliale,\nprovince, T3 2026", 0.12), (860500, "860 500 $ : médiane plex,\nRMR Montréal, T3 2026", 0.5)]: ax.axvline(p / 1000, color=palette.ink2, lw=0.6, ls=":"); ax.text(p / 1000 + 25, y, lab, fontsize=6.8, color=palette.ink2) ax.set_xlabel("Base d'imposition (milliers de dollars)"); ax.set_ylabel("Taux effectif (% de la base)") ax.xaxis.set_major_formatter(FuncFormatter(lambda v, p: f"{v:,.0f}".replace(",", " "))); ax.yaxis.set_major_formatter(FuncFormatter(lambda v, p: f"{v:.1f}".replace(".", ","))) ax.set_ylim(0, 3.2); ax.legend(loc="upper left", fontsize=7.5) out = savefig(fig, "ch04/ch04-fig-mutations.pdf"); print("OK", out) if __name__ == "__main__": main()