spb/qwhpi Public
QHPI — Quebec Housing Price Index: quality-adjusted, hierarchically pooled housing price indexes.
Python 63.9%
TypeScript 25.4%
CSS 5.5%
TeX 3.5%
SQL 0.8%
Makefile 0.5%
Dockerfile 0.5%
1# =============================================================================2# QWHPI — Quebec Weekly Housing Price Index3# Author : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# File : api/app/schemas.py6# Purpose : Pydantic response schemas (monthly v2.1) — uncertainty and7# reliability are always present, never hidden.8# =============================================================================9"""API response schemas — QHPI monthly."""1011from __future__ import annotations1213from pydantic import BaseModel1415AUTHOR = "Simon-Pierre Boucher"16CONTACT = "contact@spboucher.ai"171819class Credit(BaseModel):20 author: str = AUTHOR21 contact: str = CONTACT222324class Observation(BaseModel):25 period: str26 index: float | None27 index_smoothed: float28 representative_value: float | None29 transactions: int30 effective_sample_size: float | None31 monthly_pct: float | None32 three_month_pct: float | None33 six_month_pct: float | None34 yoy_pct: float | None35 lower_95: float36 upper_95: float37 reliability_grade: str38 shrinkage_weight: float | None39 is_partial_month: bool404142class SeriesResponse(Credit):43 geography: str44 geography_name: str45 geography_level: str46 property_type: str47 frequency: str = "monthly"48 base_period: str = "2021 average = 100"49 model_version: str50 data_vintage: str51 total_observations: int52 offset: int = 053 limit: int | None = None54 observations: list[Observation]555657class LatestResponse(Credit):58 geography: str59 geography_name: str60 property_type: str61 frequency: str = "monthly"62 period: str63 latest_index: float64 latest_index_raw: float | None65 representative_value: float | None66 monthly_change: float | None67 three_month_change: float | None68 yoy_change: float | None69 transactions: int70 effective_sample_size: float | None71 reliability: str72 lower_95: float73 upper_95: float74 is_partial_month: bool75 model_version: str76 data_vintage: str777879class GeographyNode(BaseModel):80 geography_id: str81 geography_name: str82 geography_level: str83 property_types: list[str]848586class GeographiesResponse(Credit):87 data_vintage: str88 published_series: list[GeographyNode]89 coverage_matrix_url: str = "/v1/geographies/coverage"909192class LiquidityPoint(BaseModel):93 period: str94 transactions: int959697class LiquidityResponse(Credit):98 geography: str99 property_type: str100 median_monthly_transactions: float101 observations: list[LiquidityPoint]102103104class MapCell(BaseModel):105 geography_id: str106 geography_name: str107 value: float | None108 reliability_grade: str109 transactions: int110111112class MapResponse(Credit):113 metric: str114 level: str115 property_type: str116 period: str117 cells: list[MapCell]118119120class VintageObservation(BaseModel):121 period: str122 first_release_index_smoothed: float123 current_index_smoothed: float124 first_release_vintage: str125 current_vintage: str126 revision_pct: float127128129class MetaResponse(Credit):130 name: str = "QHPI — Quebec Housing Price Index (monthly)"131 model_version: str132 data_vintage: str133 frequency: str = "monthly"134 base_period: str = "2021 average = 100"135 methodology: str = (136 "Robust monthly architecture: province paths by rolling-time-dummy "137 "hedonic (13-month Huber-IRLS windows, mean splice — revision-free); "138 "liquid cells (≥40 tx/month) estimated directly by local robust "139 "time-dummy with state-space smoothing; thin cells shrunk toward "140 "their parent path via a heteroskedastic local-level Kalman model. "141 "Validated against repeat sales, stratified matched-cell medians, "142 "downsampling and composition-shock simulations."143 )144 methodology_url: str = "/methodology"145 seasonal_adjustment: str = "NSA (no stable monthly seasonality detected)"146 series_count: int147 periods: int148 latest_complete_period: str149