🏇 Half a Million Prices, Twenty Models
UQO Working Paper No. 11 — A Systematic Assessment of Hedonic Specifications and Estimation Methods for the Quebec Housing Market, 2021–2026
TL;DR — A controlled horse race of 20 hedonic models on 514,212 Quebec sales with assessor-grade structural attributes: 6 functional forms × time-FE ladder × spatial-FE ladder × 6 estimation methods, all scored on the same price-level scoreboard (Duan smearing / Box–Cox inversion) under two holdouts (random 80/20 and forward-in-time). Functional form is second-order (±2 pp of MdAPE); spatial controls are first-order (~10 pp) but overfit at ~1 km granularity; gradient boosting wins under random validation (MdAPE ≈ 14.4% vs 16.5% for the best linear model) — but under the forward-in-time split every model degrades and the ML advantage reverses (splines 19.1% vs boosting 21.2%, identical R²_ln): random cross-validation is the wrong experiment for valuation models. Implied price indices and implicit-price profiles agree across forms far more than the accuracy gap suggests.
🎯 The four design axes
| Axis | Models | Question |
|---|---|---|
| A. Functional form | linear, semi-log, log-log, Box–Cox (λ̂ by profile likelihood), quadratics, cubic splines | does curvature matter? |
| B. Time effects | none / year / quarter / month FE | how fine must the time dummies be? |
| C. Spatial controls | none / municipality / ~5.5 km grid / ~1.1 km grid FE | how fine can location FE get before overfitting? |
| D. Estimation method | OLS, ridge (CV), random forest, gradient boosting (± coordinates), spatial k-NN comparables | what do the machines actually buy? |
Every model: same sales, same attributes (floor area, lot, age, storeys, units, class, physical link), metrics on price levels (MdAPE, MAPE, RMSE_ln, R²_ln), municipality-clustered design, and two splits — random 80/20 and train < 2025 / test 2025–26 with carry-forward time effects.
🗂 Repository layout
wp11_uqo/
├── data/raw/ # snapshot (NOT in git — see data/raw/README.md)
├── src/wp11/ # config, sample, models (the harness), plotstyle
├── scripts/
│ ├── 01_build_sample.py # 745,119 → 514,212 sales
│ ├── 02_horserace.py # 20 models × 2 splits + Box–Cox profile
│ ├── 03_extensions.py # indices, implicit-price profiles, learning curves, segments
│ ├── 04_make_figures.py # 9 journal-calibre figures
│ └── 05_make_tables.py # 7 LaTeX tables
├── results/{reproduced,tables}/
├── figures/
└── paper/ # main.tex + sections/ + references.bib → main.pdf🚀 Quick start
cd wp11_uqo
python3 -m pip install -r requirements.txt
# place the parquet snapshot in data/raw/ (not distributed), then:
for s in scripts/0*.py; do python3 "$s"; done
cd paper && makeRuntime ≈ 10 minutes on an Apple-silicon laptop (the boosting and forest fits dominate); peak RAM ≈ 8 GB.
📝 Citation
@techreport{boucher2026horserace,
author = {Boucher, Simon-Pierre},
title = {Half a Million Prices, Twenty Models: A Systematic Assessment
of Hedonic Specifications and Estimation Methods for the
Quebec Housing Market},
institution = {Universit\'e du Qu\'ebec en Outaouais,
D\'epartement des sciences administratives},
type = {Working Paper},
number = {11},
year = {2026},
month = {August}
}👤 Author & contact
Simon-Pierre Boucher — Département des sciences administratives, Université du Québec en Outaouais (UQO), Gatineau, QC. 📧 contact@spboucher.ai