TypeScript 90.1%
JavaScript 3.2%
Python 3.2%
CSS 1.8%
HTML 1.8%
1// UQO Éval — modélisation hédonique : spécification (module PUR, partagé client/serveur).23export type Source = "sales" | "listings";4export type AreaMode = "quebec" | "muni" | "radius";5export type DepVar = "price" | "lnprice";6export type TimeFE = "none" | "year" | "quarter" | "month";7export type GeoFE = "none" | "muni" | "arrond" | "voisinage" | "grid1" | "grid2" | "grid5";8export type Method = "ols" | "huber" | "ridge" | "lasso" | "lad" | "sar";9export type SeType = "classic" | "hc1" | "cluster";1011/** Variables explicatives disponibles. */12export type VarKey =13 | "aire" // aire d'étages (m²) — rôle14 | "terrain" // superficie du terrain (m²)15 | "age" // âge au moment de la vente16 | "nb_logements"17 | "nb_etages"18 | "type" // type de propriété (catégoriel)19 | "genre" // genre de construction (plain-pied, à étages…)20 | "lien" // lien physique (détaché, jumelé, en rangée…)21 | "dist_centre" // distance au centroïde de la municipalité (km)22 | "valeur_role" // évaluation municipale (attention : quasi-tautologique)23 | "bedrooms" // annonces seulement24 | "bathrooms" // annonces seulement25 | "trend_xy"; // surface de tendance spatiale (lat, lng, quadratique)2627export interface VarDef {28 key: VarKey;29 fr: string;30 en: string;31 kind: "cont" | "cat" | "block";32 logable: boolean;33 sources: Source[];34 hint: { fr: string; en: string };35}3637export const VARS: VarDef[] = [38 { key: "aire", fr: "Aire d'étages (m²)", en: "Floor area (m²)", kind: "cont", logable: true, sources: ["sales", "listings"], hint: { fr: "Surface brute des étages hors sous-sol (rôle MAMH). La variable hédonique reine.", en: "Gross floor area excl. basement (MAMH roll). The queen hedonic variable." } },39 { key: "terrain", fr: "Superficie du terrain (m²)", en: "Lot area (m²)", kind: "cont", logable: true, sources: ["sales", "listings"], hint: { fr: "Rendement décroissant attendu → forme log recommandée.", en: "Diminishing returns expected → log form recommended." } },40 { key: "age", fr: "Âge du bâtiment (ans)", en: "Building age (years)", kind: "cont", logable: false, sources: ["sales", "listings"], hint: { fr: "Année de la vente − année de construction. Ajoutez âge² pour capter la courbure (vintage).", en: "Sale year − year built. Add age² to capture curvature (vintage effect)." } },41 { key: "nb_logements", fr: "Nombre de logements", en: "Number of dwellings", kind: "cont", logable: false, sources: ["sales", "listings"], hint: { fr: "Pertinent pour les plex.", en: "Relevant for plexes." } },42 { key: "nb_etages", fr: "Nombre d'étages", en: "Storeys", kind: "cont", logable: false, sources: ["sales", "listings"], hint: { fr: "Colinéaire avec le genre de construction.", en: "Collinear with construction style." } },43 { key: "type", fr: "Type de propriété", en: "Property type", kind: "cat", logable: false, sources: ["sales", "listings"], hint: { fr: "Variables indicatrices (base = type le plus fréquent).", en: "Dummy variables (base = most frequent type)." } },44 { key: "genre", fr: "Genre de construction", en: "Construction style", kind: "cat", logable: false, sources: ["sales", "listings"], hint: { fr: "Plain-pied, à étages entiers, niveaux décalés, mansardé…", en: "Bungalow, full storeys, split-level, mansard…" } },45 { key: "lien", fr: "Lien physique", en: "Physical link", kind: "cat", logable: false, sources: ["sales", "listings"], hint: { fr: "Détaché, jumelé, en rangée, intégré.", en: "Detached, semi-detached, row, integrated." } },46 { key: "dist_centre", fr: "Distance au centre (km)", en: "Distance to centre (km)", kind: "cont", logable: true, sources: ["sales", "listings"], hint: { fr: "Distance au centroïde des unités de la municipalité — gradient de rente foncière (Alonso-Muth).", en: "Distance to the municipality's centroid — land-rent gradient (Alonso-Muth)." } },47 { key: "bedrooms", fr: "Chambres (annonce)", en: "Bedrooms (listing)", kind: "cont", logable: false, sources: ["listings"], hint: { fr: "Déclaré par le vendeur.", en: "Declared by the seller." } },48 { key: "bathrooms", fr: "Salles de bain (annonce)", en: "Bathrooms (listing)", kind: "cont", logable: false, sources: ["listings"], hint: { fr: "Déclaré par le vendeur.", en: "Declared by the seller." } },49 { key: "trend_xy", fr: "Surface de tendance spatiale", en: "Spatial trend surface", kind: "block", logable: false, sources: ["sales", "listings"], hint: { fr: "Polynôme quadratique en latitude/longitude (5 termes) — alternative lisse aux effets fixes géo.", en: "Quadratic polynomial in lat/lng (5 terms) — smooth alternative to geo fixed effects." } },50 { key: "valeur_role", fr: "Valeur au rôle ($)", en: "Assessed value ($)", kind: "cont", logable: true, sources: ["sales", "listings"], hint: { fr: "⚠ Quasi-tautologique : le rôle est lui-même une estimation. À utiliser pour une étude de ratios, pas pour un modèle hédonique structurel.", en: "⚠ Quasi-tautological: the roll is itself an estimate. Use for ratio studies, not a structural hedonic model." } },51];5253export interface HedonicSpec {54 source: Source;55 area: { mode: AreaMode; muni?: string; radiusKm?: number };56 types: string[]; // sales : unifamilial | plex | condo | indéterminé ; annonces : mêmes clés (maison→unifamilial)57 period: { from: string; to: string }; // YYYY-MM (ventes) — ignoré pour les annonces58 price: { min: number; max: number; trimPct: number };59 maxN: number;60 seed: number;61 depvar: DepVar;62 vars: VarKey[];63 logVars: VarKey[];64 ageSquared: boolean;65 fe: { time: TimeFE; geo: GeoFE };66 method: Method;67 se: SeType;68 cv: boolean;69 compareLab: boolean;70}7172export const DEFAULT_SPEC: HedonicSpec = {73 source: "sales",74 area: { mode: "muni", muni: "Gatineau" },75 types: ["unifamilial"],76 period: { from: "2021-01", to: "2026-12" },77 price: { min: 50000, max: 3000000, trimPct: 1 },78 maxN: 6000,79 seed: 42,80 depvar: "lnprice",81 vars: ["aire", "terrain", "age", "lien", "genre"],82 logVars: ["aire", "terrain"],83 ageSquared: true,84 fe: { time: "quarter", geo: "none" },85 method: "ols",86 se: "hc1",87 cv: true,88 compareLab: true,89};9091export const METHODS: { key: Method; fr: string; en: string; hint: { fr: string; en: string } }[] = [92 { key: "ols", fr: "Moindres carrés ordinaires (MCO)", en: "Ordinary least squares (OLS)", hint: { fr: "Le point de départ de toute analyse hédonique (Rosen, 1974). Inférence complète.", en: "The starting point of any hedonic analysis (Rosen, 1974). Full inference." } },93 { key: "huber", fr: "Régression robuste (Huber, IRLS)", en: "Robust regression (Huber, IRLS)", hint: { fr: "Réduit l'influence des ventes atypiques (prix hors marché, erreurs de saisie).", en: "Downweights atypical sales (non-market prices, data errors)." } },94 { key: "lad", fr: "Régression quantile — médiane (LAD)", en: "Quantile regression — median (LAD)", hint: { fr: "Modélise le prix médian conditionnel ; insensible aux queues. Sans écarts-types.", en: "Models the conditional median price; tail-insensitive. No standard errors." } },95 { key: "ridge", fr: "Ridge (pénalité L2, λ par validation croisée)", en: "Ridge (L2 penalty, CV λ)", hint: { fr: "Stabilise les coefficients quand les variables sont colinéaires (aire, étages, logements…).", en: "Stabilises coefficients under collinearity (area, storeys, dwellings…)." } },96 { key: "lasso", fr: "LASSO (pénalité L1, λ par validation croisée)", en: "LASSO (L1 penalty, CV λ)", hint: { fr: "Sélectionne automatiquement les variables ; inférence post-LASSO sur les variables retenues.", en: "Automatic variable selection; post-LASSO inference on kept variables." } },97 { key: "sar", fr: "Modèle spatial autorégressif (SAR, 2SLS)", en: "Spatial autoregressive model (SAR, 2SLS)", hint: { fr: "Ajoute le prix des k voisins (ρ·Wy) — dépendance spatiale explicite ; instruments WX, W²X (Kelejian-Prucha).", en: "Adds neighbours' prices (ρ·Wy) — explicit spatial dependence; WX, W²X instruments (Kelejian-Prucha)." } },98];99100export const SE_TYPES: { key: SeType; fr: string; en: string }[] = [101 { key: "classic", fr: "Classiques (homoscédastiques)", en: "Classical (homoskedastic)" },102 { key: "hc1", fr: "Robustes à l'hétéroscédasticité (HC1, White)", en: "Heteroskedasticity-robust (HC1, White)" },103 { key: "cluster", fr: "Groupées par zone géographique (cluster)", en: "Clustered by geographic zone" },104];105106export const TIME_FE: { key: TimeFE; fr: string; en: string }[] = [107 { key: "none", fr: "Aucun", en: "None" },108 { key: "year", fr: "Année", en: "Year" },109 { key: "quarter", fr: "Trimestre", en: "Quarter" },110 { key: "month", fr: "Mois", en: "Month" },111];112113export const GEO_FE: { key: GeoFE; fr: string; en: string }[] = [114 { key: "none", fr: "Aucun", en: "None" },115 { key: "muni", fr: "Municipalité", en: "Municipality" },116 { key: "arrond", fr: "Arrondissement / secteur", en: "Borough / sector" },117 { key: "voisinage", fr: "Unité de voisinage (rôle)", en: "Neighbourhood unit (roll)" },118 { key: "grid1", fr: "Grille 1 km", en: "1 km grid" },119 { key: "grid2", fr: "Grille 2 km", en: "2 km grid" },120 { key: "grid5", fr: "Grille 5 km", en: "5 km grid" },121];122123export const TYPE_OPTIONS: { key: string; fr: string; en: string }[] = [124 { key: "unifamilial", fr: "Unifamiliale", en: "Single-family" },125 { key: "condo", fr: "Condo", en: "Condo" },126 { key: "plex", fr: "Plex", en: "Plex" },127 { key: "indéterminé", fr: "Indéterminé (ventes)", en: "Undetermined (sales)" },128];129130export const LIMITS = { maxN: 25000, minN: 60, maxGeoLevels: 160, maxCols: 320 };131