REPRODUCE — end-to-end instructions (UQO WP36)
0. Prerequisites
- macOS or Linux; Python 3.12 managed by
uv(0.11+); TeX Live 2026 (pdflatex,bibtex,latexmk); SQLite ≥ 3.40;zstd. - Hardware used: Apple M5 Max (18 cores, 48 GB). Full pipeline wall time ≈ 45 min (the robustness suite and the 200-replication dealer bootstrap dominate).
- Raw data: owner-authorised snapshot
data/raw/autoka-snapshot-20261101.db(1.35 GB, SHA-25665c3dad229a402f89129c614111a8d6f7b583eb7b46a6014a34e0ebca8de0132; not distributed, restricted fields). Also required:data/raw/registry/sources.jsonandvilles_gps.json(public registry copied from the platform). Operator-only regeneration from the production node:Without the snapshot, the pipeline and all tests run on the clearly labelled synthetic fixture (bashssh M4M64b 'cd ~/auto-ka && sqlite3 data/autoka.db ".backup /tmp/snap.db" && sqlite3 /tmp/snap.db "DROP TABLE IF EXISTS users; VACUUM;" && shasum -a 256 /tmp/snap.db && zstd -T0 -3 /tmp/snap.db' scp M4M64b:/tmp/snap.db.zst data/raw/ && zstd -d data/raw/snap.db.zst -o data/raw/autoka-snapshot-YYYYMMDD.dbpython -m ucml.synthetic→data/synthetic/autoka-synthetic.db; setUCML_SNAPSHOTto that path). Synthetic output is for code validation only and carries no empirical content.
1. Environment
bash
make env # uv venv + editable install (pinned versions in requirements-lock.txt)
make test # 14 unit/pipeline tests (pricepaths, cleaning rules, synthetic end-to-end, prediction helpers)2. Pipeline (in order; each script is idempotent and writes to results/, figures/, paper/tables/)
| Step | Script | Output |
|---|---|---|
| 01 | scripts/01_ingest.py |
data/interim/*.parquet, manifest.json (row counts, time bounds, SHA-256) |
| 02 | scripts/02_clean.py |
data/processed/listings.parquet, price_events.parquet, exclusions.csv, sample_construction.csv, sources_registry.csv, cleaning_stats.json |
| 03 | scripts/03_features.py |
data/processed/risk_set.parquet (listing-days with competitor sets at 10/25/50 km) |
| 04 | scripts/04_hedonic.py |
results/hedonic/ (Models A1–A5, tests, region premia, residuals, surface, grouped CV incl. LightGBM) |
| 05 | scripts/05_descriptives.py |
Figures 1, 3, 4; Tables 1–3; results/descriptives/summary.json |
| 06 | scripts/06_hazards.py |
results/hazards/ (cloglog B/C, Cox with dealer-clustered SEs, AFT, cut size, empirical hazards) |
| 07 | scripts/07_competition.py, 07b_competition_dow.py |
results/competition/ (event studies, placebo, radii, dealer×weekday FE) |
| 08 | scripts/08_prediction.py |
results/prediction/, Figure 10, Table 8 |
| 09 | scripts/09_amli.py 200 |
results/amli/ (indices, weights, validation, dealer bootstrap) |
| 10 | scripts/10_validation.py |
results/validation/exit_validation.json |
| 11 | scripts/11_figures.py |
Figures 2, 5–9 |
| 12 | scripts/12_robustness.py |
results/robustness/, Table 9, Holm-adjusted primary tests |
| 13 | scripts/13_tables.py |
Tables 4–7 |
make all runs everything (make data models tables figures paper). |
3. Paper
bash
cd paper && make # latexmk: pdflatex + bibtex (natbib, aer.bst) -> paper/main.pdfEvery number in the manuscript is traced in CLAIMS_LEDGER.csv to a results file; EXPERIMENTS.md logs each run; DECISIONS.md records amendments to the preregistered plan (research/analysis_plan.md).