SPB Git

spb/wp36_uqo

Public
7.6 KB

# WP36 — Preregistered analysis plan (v1.0, 2026-11-01)

This plan was written after the Phase 0 audit and before estimating any main model. Deviations are recorded in DECISIONS.md with a dated amendment. Exploratory analyses are labelled as such in the paper.

# 1. Samples

Sample Definition Used for
S0 full all 273 265 listings in the 2026-11-01 snapshot coverage tables only
S1 hedonic kind = auto, canonical (dup_of IS NULL), 2005 ≤ model year ≤ 2026, 1 000 ≤ km ≤ 400 000, 2 000 ≤ price ≤ 250 000 (first sustained price), make & model non-missing; all sources except uid collisions; sampled portals (autotrader, cargurus) and Kijiji flagged and dropped in the primary specification, kept in a robustness variant H1, H4, Model A/E, Model F price
S2 dynamic S1 ∩ sources in the dynamic set (direct dealer sites, otogo, autousagee, hgregoire, automobileendirect, megacentredeliquidation, clubautozone), entered after 2026-08-13 00:00 UTC and more than 24 h after the source's first non-empty crawl (not left-censored; amendment D-014), not an oscillating uid, source not in the excluded connector list (D-003) H2, H3, H5, AMLI, Model B/C/D
S2L S2 plus the left-censored day-1 stock (entry = first_seen) sensitivity
S3 market panel S2 aggregated to market (region × segment) × day and × ISO week H6

Exclusions are logged row by row in data/processed/exclusions.csv (uid, rule, value).

# 2. Variable definitions

  • Listing time t: UTC days since 2026-08-12. Listing age a = t − entry day (entry = first_seen).
  • Vehicle age (years) = (observation date − 1 October of (model year − 1)) / 365.25, floored at 0. Mileage in 10 000 km.
  • Sustained price path (D-005): from price_log, drop NULL rows; remove any level of duration < 48 h that reverts to the preceding level; the first remaining level is the entry price; a markdown is a sustained decrease ≥ 1 % and ≥ 100 $; a rise is a sustained increase ≥ 1 %. Uids with ≥ 3 removed transients are oscillating.
  • Exit (D-004): listing inactive at snapshot and last_seen ≤ snapshot − 7 days → exit at last_seen (interval-censored between last_seen and the next crawl of that source; we use last_seen + half the source's median crawl interval). Otherwise right-censored at min(last_seen, snapshot − 7 d).
  • Segments: body type (recovered from body_type, then from a make-model lookup built from non-missing rows, else "unknown"); powertrain = EV / PHEV-hybrid / ICE from fuel + engine strings; price tier.
  • Markets: administrative region (17, recovered from lat/lng when missing via nearest city file); local market for H3 = 25 km radius around the listing's dealer (alternatives 10, 50 km).
  • Competitor set (H2/H3): listings of the same make, model and model year ± 1 within the radius, active on day t, from other dealers. Density = count; price position = log(price) − median log price of the set.
  • Hedonic residual at entry r_i: residual of Model A (estimated on S1 with cohort FE) at the entry price.

# 3. Models (primary specifications)

Model A (H1, H4). log P_i = f(age_i, km_i) + X_i'β + μ_{make-model-cohort} + τ_{entry week} + θ_{source type} + ε_i, f = cubic regression splines (5 knots each) + tensor interaction; variants: (A1) linear age/km, (A2) splines, (A3) splines × powertrain, (A4) model-trim-year FE, (A5) dealer FE (region absorbed → report region effects from A4 with dealer-chain FE instead), (A6) LightGBM. SEs clustered by dealer. Preregistered test: Wald A2 vs A1; 5-fold grouped CV RMSE.

Model B (H2). Discrete-time hazard of first markdown on the listing-day risk set (S2): cloglog(h_{it}) = g(a_{it}) + γ·density_{it} + δ·pricepos_{i,entry} + X_i'β + μ_{segment} + τ_{week} + region FE; g = listing-age dummies (weekly bins). Cox PH with Schoenfeld test as a check; AFT (log-logistic) as alternative. Cut size: OLS of log cut on the same covariates for markdown events. Repeated markdowns: PWP gap-time model (exploratory). SEs clustered by dealer.

Model C (H5). Same risk set; outcome = exit. Covariates add r_i (entry residual), current price position, number of prior cuts, listing age. Competing-risk description: exit vs. still listed at snapshot; relisting at another dealer (VIN) coded separately (exploratory Fine–Gray if ≥ 200 events). Validation: for VINs observed both on a direct site and on otogo, share of exits within ± 3 days on both; relisting rate within 30 days as the lower bound of "not-a-sale".

Model D (H3). For each listing-day in S2 with a defined competitor set: event = any sustained competitor markdown in the set on day t−k (k = −7..+14). cloglog(h_{it}) = Σ_k β_k·CompCut_{i,t−k} + g(a_{it}) + listing-age × segment + μ_{market × week} + μ_{make-model-year × week} + X_i'β. Cluster by market (region) with wild-cluster bootstrap if < 40 clusters. Diagnostics: pretrends (leads), placebo with pseudo-competitors drawn from other regions, selection check (do listings that later get a competitor cut differ at entry?). Interpretation: association only.

Model E (H4). Region effects from A4 (cohort FE, no dealer FE) with 95 % CIs; within make-model-year-trim price dispersion (IQR of log price) by region; border comparison (Outaouais vs Montérégie/Laurentides as a within-Quebec check; Ontario unavailable). Conley spatial HAC SEs (50 km) as a robustness.

Model F (prediction). Targets: log entry price; markdown within 30 days; exit within 30 days. Models: ridge/OLS baseline, LightGBM. Splits: chronological (entry before/after 2026-10-01), dealer holdout (20 % dealers), region holdout (leave-one-region-out). Metrics: MAE/RMSE; log loss, Brier, calibration (reliability bins); C-index for survival. 200-bootstrap CIs.

# 4. AMLI (H6)

Higher AMLI = more liquid market. Components (market m, week w, computed with information available at w): (1) exit intensity = exits / listing-days; (2) staleness = share of active listings with listing age > 30 d (sign reversed); (3) markdown frequency = sustained cuts / listing-days and depth = median cut %; (4) quality-adjusted dispersion = IQR of hedonic residuals among active listings (sign reversed); (5) arrival rate = entries / active stock. Each component standardised across market-weeks (z-score within the panel; robustness: rank). Weights: equal; PCA first component (signed); supervised (ridge on next-week exit intensity using only components 2–5, fitted on weeks 1–6, evaluated weeks 7–11). Missingness: component dropped for a market-week with < 30 listing-days; index requires ≥ 3 components. Sensitivity: leave-one-component-out; geographic aggregation (region vs province); segment (price tier, body). Uncertainty: block bootstrap over dealers (200 reps).

# 5. Inference and multiple testing

Cluster-robust SEs by dealer (A, B, C) and by region with wild-cluster bootstrap (D). Six confirmatory families (H1–H6): primary tests reported with Holm-adjusted p-values across the six primary tests; secondary tests unadjusted and labelled.

# 6. Robustness (mandatory list)

Alternative price filters (1 %, 2 % cut thresholds; 24 h / 72 h transient rule); include sampled portals; include Kijiji; left-censored stock (S2L); exit confirmation 3 / 14 days; radius 10/50 km; cohort vs trim FE; dealer FE; heterogeneity by model year, mileage, brand, EV/ICE, region; placebo events; composition reweighting (entropy balancing to the otogo make-model distribution).

# 7. What will NOT be claimed

Causal competitor contagion; sale prices; sale events; forecasting value of AMLI for external economic variables; representativeness beyond the Auto-Ka registry.

Files · f9bf466deda3bcf4729bb4dc6e4078483843c761
Menu

Theme