# 🏘️ SHARP-HPI: A Spatially Hierarchical, Adaptive and Robust Framework for Quality-Adjusted Housing Price Indices **UQO Working Paper No. 22** — *Monthly municipal indices for Quebec from 770,000 registered sales, 2021–2026* [![Paper](https://img.shields.io/badge/paper-PDF%20(49%20p.)-b31b1b?logo=latex&logoColor=white)](paper/main.pdf) [![Python](https://img.shields.io/badge/python-3.14-3776AB?logo=python&logoColor=white)](requirements.txt) [![Data](https://img.shields.io/badge/data-769%2C995%20registered%20sales%20·%20SQLite%20snapshot-4051b5)](data/raw/README.md) [![Reproducible](https://img.shields.io/badge/reproducible-end--to--end%20pipeline-2e7d32)](scripts/) [![Institution](https://img.shields.io/badge/UQO-D%C3%A9pt.%20des%20sciences%20administratives-16365c)](https://uqo.ca) [![Author](https://img.shields.io/badge/author-Simon--Pierre%20Boucher-16365c)](mailto:simon-pierre.boucher@uqo.ca) > **TL;DR** — A two-stage index estimator for thin housing markets: a robust pooled hedonic regression with fine-scale location fixed effects and drifting quality prices (stage 1), then nested local-level state-space deviations province → region → MRC → municipality whose innovation variances are calibrated by empirical Bayes across cells (stage 2). Applied to an audited snapshot of Quebec land-registry sales (769,995 rows → 632,006 headline sales, January 2021 – 7 October 2026) matched to the assessment roll. Delivers a panel of 2,696 geography × class cells × 69 months with counts, effective sample sizes, local-data weights, 95 % intervals and A–E grades; eleven benchmarks (median → HMTS → repeat sales → QHPI); a 9-scenario Monte Carlo with two deliberate counter-examples; real-time vintages with measured revisions; placebo, composition-shock, bootstrap, Moran, ablation, aggregation and external (Teranet, CREA) checks. --- ## 📌 Status | Item | Value | |---|---| | Version | 1.0 (October 2026) | | SSRN | [7651200](https://ssrn.com/abstract=7651200) — submitted 2026-10-21 (PRELIMINARY_UPLOAD) | | Journal | — | | Code & data | reproducible from `scripts/` (see Quick start); raw microdata not redistributed | ## 🎯 What this paper does The estimand is the quality-constant log price level $L_{g,k,t}$ of geography $g$, class $k$ (house, condominium, plex) and month $t$, normalised to the 2021 average = 100. The model is ``` log P_i = f_k(x_i; θ_t) + α_{ℓ(i)} + μ_{k,t} + δ^R_{r(i),t} + δ^M_{m(i),t} + δ^U_{u(i),t} + ε_i δ_{g,t} = δ_{g,t-1} + η_{g,t}, ȳ_{g,t} = δ_{g,t} + e_{g,t}, Var(e) = σ²_g / n_{g,t}, log τ²_g ~ N(m_level, v_level) ``` Every ingredient exists in the literature (Francke & van de Minne 2017; Ishaak, Ouwehand & Remøy 2024; Fay & Herriot 1979; Hill et al. 2022); the paper tests whether their combination helps, where it does not, and how reliable each cell is. ## 🏆 Headline results | Object | Estimate | |---|---| | Provincial index, Sept. 2026 (2021 avg = 100): houses / condos / plexes | 154.9 / 136.4 / 151.2 | | Municipal house index, Sept. 2026, grades A–C: P10 / median / P90 | 133 / 153 / 174 | | Monte Carlo (baseline, municipalities): RMSE of monthly log change ×100 — SHARP / per-cell state space (QHPI) / cell time dummy / median | 1.58 / 2.91 / 12.52 / 24.28 | | Monte Carlo coverage of 95 % intervals, municipalities: SHARP / without EB calibration | 98 % / 97 % | | Counter-examples | heavy tails: municipal-level location FE wins (2.84 vs 4.62); regional level: QHPI direct local TD wins (1.17 vs 1.40) | | Composition shock (drop smallest 40 % of houses from 2024, Montréal region): median / TD / SHARP shift | +23.4 / -0.5 / +0.3 log pts | | First-release revision of monthly change (houses): province / municipalities (full re-estimation) / municipalities (frozen) | 0.16 / 1.72 / 2.31 log pts | | External: Québec CMQ houses 2021→2026 SHARP / CREA single-family / Teranet | 47.9 / 45.5 / 43.7 log pts | Every number in the manuscript is a generated macro (`paper/tables/numbers.tex`). Key outputs: `data/processed/index_panel.parquet|csv` (schema of protocol §17), `results/panel/reliability_cells.csv`, `results/simulation/summary.csv`, `results/vintages/revisions_by_release*.csv`, `results/validation/*.csv`. ## 🗂 Repository layout ``` sharp-hpi-quebec/ ├── CLAUDE.md # research protocol (as received) ├── data/raw/ # SQLite snapshot + earlier vintages (not committed; README) ├── data/external/ # SDA boundaries (not committed), MAMH register, external indices ├── data/interim|processed/ # parquet layers; index_panel.* and index_vintages.parquet ├── src/sharp_hpi/ # config, io, cleaning, hedonic, estimators, statespace, sharp, qhpi, panel, simulate, plotting ├── scripts/ # 01–06 data · 10–11 benchmarks · 20 Monte Carlo · 30 panel · 40–41 vintages · 50 validation · 60–62 figures/tables/external ├── tests/ # pytest (state space, EB prior, estimators, SHARP, panel invariance) ├── results/ # profile, geo, cleaning, vintages, benchmarks, simulation, panel, validation ├── figures/ # generated figures (copied to paper/figures) ├── docs/ # PLAN, decision_log, data_dictionary, provenance_report, limitations, research_log, literature/ └── paper/ # main.tex, sections/, appendix/, tables/ (generated), references.bib (115 verified entries) ``` ## 🚀 Quick start ```bash python3 -m pip install -r requirements.txt make data # 01 extract (needs data/raw/vraiprix-20261021.db) → 06 provenance report make benchmarks hmts # A–K at province × class and region × class make panel # full SHARP-HPI panel (≈ 1 min) make vintages revisions # real-time vintages (≈ 1 h) and revision statistics make validation external # placebo, composition, bootstrap, Moran, ablation, aggregation, trimming, repeat sales, Teranet/CREA make simulation # Monte Carlo, 80 reps × 9 scenarios (≈ 3.6 h on 12 cores) make figures tables paper # figures, LaTeX tables + macros, PDF make test ``` ## 🗃 Data Production SQLite of Vrai Prix (www.vrai-prix.com), `.backup` taken 2026-10-21 00:30; 769,995 registered sales (Quebec land registry via the Journal de Québec / Journal de Montréal feed) 2021-01-04 → 2026-10-07, geocoded and matched to the MAMH assessment roll (3.75 M units). Four earlier extractions measure the publication lag (10–13 days, no backfill). Boundaries: MRNF SDA V2026-07. External indices: Teranet–National Bank, CREA MLS HPI, Statistics Canada NHPI/RPPI (downloaded 2026-10-21). See `docs/data_dictionary.md` and `docs/provenance_report.md`. ## 🔬 Methodology 1. `cleaning.py` — standardisation, roll-based classification, exclusion ledger. 2. `hedonic.py` — features, nested-grid location partition, Huber-IRLS fixed-effects regression (pyfixest). 3. `estimators.py` — benchmarks A–J (median, stratified median, pooled TD, rolling TD with 3 splices, hedonic imputation L/P/F, GEKS, HMTS, repeat sales BMN/CS, static EB, out-of-time GBM); `qhpi.py` — benchmark K. 4. `statespace.py` — local level / local linear trend Kalman filter & smoother, robust innovations, grid-EM empirical-Bayes prior on log τ². 5. `sharp.py` — stage 1 + nested stage 2, reliability bundle; `panel.py` — schema, normalisation, grades. 6. `simulate.py` — synthetic Quebec-like markets with known latent paths (9 scenarios). ## 🖼 Figures & tables inventory Figures (`figures/*.pdf`): coverage, arrival profile, province methods, region methods, municipal examples, gain vs n, hedonic profiles, municipal map, Monte Carlo RMSE and coverage, revisions, placebo, composition shock, aggregation, Moran. Tables (`paper/tables/*.tex`): exclusions, sample by year, completeness, municipality bands, vintages, stage 1, priors, grades, top municipalities, benchmarks (province, region), Monte Carlo (design, RMSE by level, coverage, bias, lag), revisions, policies, repeat sales, composition, placebo, Moran, bootstrap, aggregation, ablation, trimming, external. ## ⚠️ Limitations See `docs/limitations.md`: single current roll vintage (post-sale characteristics), $50,000 provider floor, no arm's-length / listing / image data, metric-grid location, administrative hierarchy, model-based intervals narrower than a cluster bootstrap for mid-size municipalities, no seasonal adjustment, CMA boundaries unavailable. ## 📝 Citation ```bibtex @techreport{boucher2026sharphpi, author = {Boucher, Simon-Pierre}, title = {SHARP-HPI: A Spatially Hierarchical, Adaptive and Robust Framework for Quality-Adjusted Housing Price Indices}, institution = {Universit\'e du Qu\'ebec en Outaouais, D\'epartement des sciences administratives}, type = {Working Paper}, number = {22}, year = {2026}, month = {October} } ``` ## 👤 Author & contact **Simon-Pierre Boucher** — Département des sciences administratives, Université du Québec en Outaouais (UQO), Gatineau, QC. 📧 [simon-pierre.boucher@uqo.ca](mailto:simon-pierre.boucher@uqo.ca) ## 🗒 Notes - Follows `Recherche-UQO/HARMONISATION.md`; the protocol asked for a folder named `uqo-research`, which does not exist — the series root `Recherche-UQO` is used (decision D0.1). - Transaction-level files (`clean_transactions.parquet`, `analytic_transactions.parquet`, `index_panel.csv`, revision microdata) are git-ignored; aggregates are committed.