SPB Git

spb/wp11_uqo Public

UQO Working Paper No. 11 — Half a million prices, twenty models: a systematic assessment of hedonic specifications.

TeX 54.7% Python 45.2%
4.7 KB

# 🏇 Half a Million Prices, Twenty Models

UQO Working Paper No. 11A Systematic Assessment of Hedonic Specifications and Estimation Methods for the Quebec Housing Market, 2021–2026

Paper Python Data Models Reproducible Institution Author Contact

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

text
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

bash
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 && make

Runtime ≈ 10 minutes on an Apple-silicon laptop (the boosting and forest fits dominate); peak RAM ≈ 8 GB.

# 📝 Citation

bibtex
@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