Phase 0: environment, model inventory, source audit, snapshot provenance
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
39 changed files +1,421 −0
added
.gitignore
+43 −0
@@ -0,0 +1,43 @@ | |||||
| 1 | +# Raw & processed data — never committed (see data/raw/README.md for provenance) | ||||
| 2 | +data/raw/* | ||||
| 3 | +!data/raw/README.md | ||||
| 4 | +data/processed/* | ||||
| 5 | +!data/processed/.gitkeep | ||||
| 6 | + | ||||
| 7 | +# Python | ||||
| 8 | +__pycache__/ | ||||
| 9 | +*.pyc | ||||
| 10 | +.pytest_cache/ | ||||
| 11 | +.venv/ | ||||
| 12 | +*.egg-info/ | ||||
| 13 | + | ||||
| 14 | +# LaTeX build artifacts (paper/main.pdf IS committed) | ||||
| 15 | +paper/*.aux | ||||
| 16 | +paper/*.log | ||||
| 17 | +paper/*.out | ||||
| 18 | +paper/*.toc | ||||
| 19 | +paper/*.lof | ||||
| 20 | +paper/*.lot | ||||
| 21 | +paper/*.fls | ||||
| 22 | +paper/*.fdb_latexmk | ||||
| 23 | +paper/*.bbl | ||||
| 24 | +paper/*.blg | ||||
| 25 | +paper/*.spl | ||||
| 26 | +paper/*.synctex.gz | ||||
| 27 | +paper/*.run.xml | ||||
| 28 | +paper/*.bcf | ||||
| 29 | + | ||||
| 30 | +# Logs | ||||
| 31 | +logs/ | ||||
| 32 | +*.log | ||||
| 33 | + | ||||
| 34 | +# macOS | ||||
| 35 | +.DS_Store | ||||
| 36 | +logs/*.log | ||||
| 37 | +data/interim/* | ||||
| 38 | +!data/interim/.gitkeep | ||||
| 39 | +.env | ||||
| 40 | +*.db | ||||
| 41 | +*.db-wal | ||||
| 42 | +*.db-shm | ||||
| 43 | +paper/tex2docx/ | ||||
added
CLAUDE.md
+214 −0
@@ -0,0 +1,214 @@ | |||||
| 1 | +# CLAUDE.md — UQO Working Paper 38 | ||||
| 2 | + | ||||
| 3 | +## Research mandate | ||||
| 4 | + | ||||
| 5 | +You are Claude Code acting as an autonomous, rigorous research team for **UQO WP38**. Produce a submission-ready empirical economics working paper, with reproducible code, verified sources, transparent data provenance, and no fabricated results. | ||||
| 6 | + | ||||
| 7 | +**Provisional title:** *The Economic Geography of Digital Production: Product Diversity, Regional Specialization, and the Hidden Structure of Quebec's Online Economy* | ||||
| 8 | + | ||||
| 9 | +**Primary source:** https://www.fabri-ka.com | ||||
| 10 | + | ||||
| 11 | +**Research question:** Can product-level online catalogues reveal the spatial organization, diversity, specialization, and economic complexity of Quebec's digital retail economy beyond what conventional business counts reveal? | ||||
| 12 | + | ||||
| 13 | +**Important distinction:** Fabri-Ka aggregates products *made, designed, or sold* in Quebec. Never infer Quebec manufacturing from a Quebec retailer's location. Distinguish merchant location, product design location, manufacturing origin, fulfillment location, and unknown provenance. The primary valid object of study is the **observed online retail assortment**, not the complete regional production system. | ||||
| 14 | + | ||||
| 15 | +At initial inspection the public homepage reported approximately 390,456 products, 1,572 online stores and 17 regions. These are unverified, time-specific interface figures, not cleaned research sample sizes. Recheck them, date-stamp the snapshot, and validate against authorized underlying data. | ||||
| 16 | + | ||||
| 17 | +## Non-negotiable scientific rules | ||||
| 18 | + | ||||
| 19 | +1. Do not invent data, references, estimates, p-values, causal effects, findings, figures, or completed experiments. | ||||
| 20 | +2. Distinguish hypotheses, descriptive findings, associations, causal identification, and simulations in every output. | ||||
| 21 | +3. Use only authorized access to Fabri-Ka's database, APIs, exports, or public pages; inspect repository configuration and documentation first. Do not bypass authentication, rate limits, robots restrictions, or access controls. Do not publish secrets, private merchant information, or personal data. | ||||
| 22 | +4. Do not scrape unnecessarily if first-party database exports are available. Never modify the live production database; use read-only access and reproducible snapshots. | ||||
| 23 | +5. Document product duplicates, variants, category errors, missing prices, currencies, merchant attribution, store location accuracy, product availability, and temporal coverage. | ||||
| 24 | +6. Use verified academic references with DOI or publisher links where possible. Do not claim a contribution is novel without an explicit literature comparison. | ||||
| 25 | +7. Prefer statistically defensible uncertainty intervals, out-of-sample tests, falsification checks, and sensitivity analyses over impressive but fragile results. | ||||
| 26 | +8. A disappeared product listing is not evidence of a sale. A catalogue price is not a transaction price. A product count is not a sales, employment, or production measure. | ||||
| 27 | +9. Keep a decision log, experimental registry, data dictionary, and limitations ledger. Mark blocked analyses as blocked rather than manufacturing substitutes. | ||||
| 28 | +10. Work sequentially, validate every phase before continuing, and leave checkpoints and reproducible commands. | ||||
| 29 | + | ||||
| 30 | +## Phase 0 — Environment, model, and source audit | ||||
| 31 | + | ||||
| 32 | +- Inspect the working repository, filesystem, available compute, installed dependencies, network permissions, and source data access. | ||||
| 33 | +- Inventory the available OpenAI and Anthropic API model IDs and permissions using official provider endpoints where configured. Run tiny, inexpensive test requests only with authorized keys; log model ID, response status, latency, context limits if verified, and approximate cost. Never assume a model exists or works. Avoid unnecessary calls. | ||||
| 34 | +- Identify the Fabri-Ka data source: database schema, exports, public website, API, crawler metadata, historical snapshots, and merchant metadata. Use read-only credentials if provided; never print them. | ||||
| 35 | +- Produce `reports/00_source_audit.md` documenting actual fields, row counts, timestamp, permission scope, provenance, missingness, and feasibility. If data access is blocked, stop empirical claims and produce a precise access checklist plus a clearly labeled methodological protocol. | ||||
| 36 | + | ||||
| 37 | +## Phase 1 — Literature review and contribution map | ||||
| 38 | + | ||||
| 39 | +Systematically review and verify scholarship on: | ||||
| 40 | +- Economic geography, regional specialization, and agglomeration. | ||||
| 41 | +- Economic complexity, product space, revealed comparative advantage, and diversification. | ||||
| 42 | +- Online retail, platform visibility, long-tail product assortments, and seller concentration. | ||||
| 43 | +- Regional inequality, rural digital access, and e-commerce adoption. | ||||
| 44 | +- Product matching, hedonic price analysis, and geographic price dispersion. | ||||
| 45 | +- Measurement error, selection bias, and representativeness of online marketplace data. | ||||
| 46 | + | ||||
| 47 | +Search academic indexes and publisher sites where permitted. Build `literature/references.bib` and `literature/evidence_matrix.csv` with verified bibliographic metadata, methodology, identification, data, findings, and precise gaps. Compare this paper with the closest empirical precedents. | ||||
| 48 | + | ||||
| 49 | +## Phase 2 — Construct the research database | ||||
| 50 | + | ||||
| 51 | +Build a documented product–merchant–region dataset with, when available: | ||||
| 52 | + | ||||
| 53 | +- Stable product identifier, merchant identifier, category and subcategory. | ||||
| 54 | +- Product title, brand, description, variant, SKU/GTIN, image and canonical URL. | ||||
| 55 | +- Listed price, currency, compare-at price, availability, observed date and historical changes. | ||||
| 56 | +- Merchant city, Quebec administrative region, geocoding quality, merchant size proxies. | ||||
| 57 | +- Verified manufacturing origin, design origin, or unknown origin; never guess from retailer location. | ||||
| 58 | +- First and last observed date, product variants, bundles, duplicate indicators, seller-platform indicators. | ||||
| 59 | + | ||||
| 60 | +Normalize prices and units when feasible; remove or flag placeholders, suspicious prices, and incomparable variants. Deduplicate both exact listings and likely identical products across merchants, preserving uncertainty. Maintain raw immutable snapshots, transformation scripts, schema tests, and data-quality reports. | ||||
| 61 | + | ||||
| 62 | +Recommended structure: | ||||
| 63 | + | ||||
| 64 | +``` | ||||
| 65 | +wp38/ | ||||
| 66 | + CLAUDE.md | ||||
| 67 | + README.md | ||||
| 68 | + config/ | ||||
| 69 | + data/raw/ # excluded from git where sensitive | ||||
| 70 | + data/interim/ | ||||
| 71 | + data/processed/ | ||||
| 72 | + literature/ | ||||
| 73 | + src/ingest/ | ||||
| 74 | + src/clean/ | ||||
| 75 | + src/features/ | ||||
| 76 | + src/models/ | ||||
| 77 | + src/validation/ | ||||
| 78 | + experiments/ | ||||
| 79 | + figures/ | ||||
| 80 | + tables/ | ||||
| 81 | + reports/ | ||||
| 82 | + paper/main.tex | ||||
| 83 | + paper/sections/ | ||||
| 84 | + paper/references.bib | ||||
| 85 | + tests/ | ||||
| 86 | + requirements.txt | ||||
| 87 | + Makefile | ||||
| 88 | +``` | ||||
| 89 | + | ||||
| 90 | +## Phase 3 — Research hypotheses | ||||
| 91 | + | ||||
| 92 | +**H1 — Regional specialization:** Online assortment composition differs systematically across Quebec regions beyond what merchant counts alone imply. | ||||
| 93 | + | ||||
| 94 | +**H2 — Digital diversity and regional scale:** Regional online product diversity is associated with local population, economic scale, and urban accessibility after suitable controls. | ||||
| 95 | + | ||||
| 96 | +**H3 — Concentration and the long tail:** Product visibility and merchant catalogue size follow highly skewed distributions, with a small number of merchants accounting for disproportionate listing shares. | ||||
| 97 | + | ||||
| 98 | +**H4 — Related diversification:** Regions with similar product-category portfolios are more likely to diversify into related categories in subsequent snapshots, if sufficient historical data exist. | ||||
| 99 | + | ||||
| 100 | +**H5 — Price dispersion:** Identical or closely matched products show geographically and competitively structured differences in listed prices after accounting for merchant and product effects. | ||||
| 101 | + | ||||
| 102 | +**H6 — Local-origin premium:** Products with *independently verified* Quebec manufacturing or design provenance may exhibit price premia, conditional on quality and category; absent provenance, do not estimate this hypothesis. | ||||
| 103 | + | ||||
| 104 | +**H7 — Digital economic complexity:** A carefully validated category–region bipartite network can produce a digital-assortment complexity indicator; test whether it adds information beyond regional income, population, and business counts. Do not call it a production complexity index without production-origin evidence. | ||||
| 105 | + | ||||
| 106 | +Preregister primary hypotheses, outcomes, specifications, exclusions, and multiplicity corrections before fitting final models. | ||||
| 107 | + | ||||
| 108 | +## Phase 4 — Core econometric framework | ||||
| 109 | + | ||||
| 110 | +### A. Regional revealed assortment advantage | ||||
| 111 | + | ||||
| 112 | +For region r and category c, define: | ||||
| 113 | + | ||||
| 114 | +`RAA_rc = (N_rc / sum_c N_rc) / (sum_r N_rc / sum_rc N_rc)` | ||||
| 115 | + | ||||
| 116 | +where N_rc is a clearly defined count of unique observed product listings or matched products. Evaluate robustness to merchant weighting, category granularity, duplicated variants, and merchant-size concentration. Distinguish this metric from export-based RCA. | ||||
| 117 | + | ||||
| 118 | +### B. Diversity and concentration | ||||
| 119 | + | ||||
| 120 | +Calculate Shannon entropy, normalized entropy, Herfindahl–Hirschman indices, Gini concentration, effective category counts, and merchant-weighted diversity. Report bootstrap uncertainty where justified and finite-sample sensitivity. | ||||
| 121 | + | ||||
| 122 | +### C. Regional product network | ||||
| 123 | + | ||||
| 124 | +Construct a region–category bipartite network and relatedness graph. Test community detection stability and compute an experimental digital-assortment complexity index. Validate against random graph nulls and merchant-count-preserving permutations. Never interpret arbitrary eigenvectors as economically meaningful without validation. | ||||
| 125 | + | ||||
| 126 | +### D. Hedonic price dispersion | ||||
| 127 | + | ||||
| 128 | +For matched product i, merchant m, region r and observation t: | ||||
| 129 | + | ||||
| 130 | +`log(P_imrt) = alpha_i + gamma_r + delta_t + beta'Z_mt + epsilon_imrt` | ||||
| 131 | + | ||||
| 132 | +Include matched-product effects, temporal controls, and appropriate clustered standard errors. Examine identification where merchant and region effects are collinear. Restrict to genuine comparable prices, shipping/taxes if available, and product-condition consistency. | ||||
| 133 | + | ||||
| 134 | +### E. Dynamic diversification (only if historical panel exists) | ||||
| 135 | + | ||||
| 136 | +Estimate entry into previously absent product categories using lagged relatedness, regional controls, and fixed effects. Carefully separate catalogue onboarding from genuine economic entry. Do not claim causal effects from observational correlations. | ||||
| 137 | + | ||||
| 138 | +## Phase 5 — Identification and external validation | ||||
| 139 | + | ||||
| 140 | +- Use Statistics Canada, Institut de la statistique du Québec, and other authoritative public sources for region population, employment, business establishments, industry composition, income, and geography; record data vintage and geographic concordance. | ||||
| 141 | +- Audit selection: e-commerce adoption, coverage differences across regions, platform/merchant size, catalogue ingestion practices, and product-category representation. | ||||
| 142 | +- Compare Fabri-Ka merchant distributions against external business counts where definitions permit. | ||||
| 143 | +- Run merchant-equal weighting, category reclassification, exclusion of the largest merchants, alternative matching thresholds, geographic uncertainty restrictions, and bootstrap-by-merchant tests. | ||||
| 144 | +- Treat causal questions as exploratory unless a defensible quasi-experiment with clear assumptions is available. Document pretrends, placebo tests, and sensitivity if attempted. | ||||
| 145 | +- Use holdout regions, holdout merchants, and temporal holdouts where applicable; prevent duplicate products from leaking between train and test. | ||||
| 146 | + | ||||
| 147 | +## Phase 6 — Signature scientific contribution | ||||
| 148 | + | ||||
| 149 | +Develop the **Quebec Digital Assortment and Complexity Index (QDACI)**, an experimental family of indicators rather than an arbitrarily combined headline score: | ||||
| 150 | + | ||||
| 151 | +1. Regional assortment diversity. | ||||
| 152 | +2. Region–category specialization. | ||||
| 153 | +3. Product-relatedness complexity. | ||||
| 154 | +4. Merchant concentration and coverage. | ||||
| 155 | +5. Cross-region price dispersion for matched products. | ||||
| 156 | + | ||||
| 157 | +Publish component definitions and uncertainty separately. If constructing a composite index, compare transparent weighting alternatives (equal weights, PCA, validated predictive weights), quantify instability, and show why aggregation improves interpretation. Clearly state that the index describes **observed online catalogues**, not total Quebec manufacturing or economic output. | ||||
| 158 | + | ||||
| 159 | +## Phase 7 — Experiments and reproducible outputs | ||||
| 160 | + | ||||
| 161 | +Produce actual empirical outputs only from verified observations: | ||||
| 162 | + | ||||
| 163 | +- Map of merchants and catalogue coverage across all 17 regions. | ||||
| 164 | +- Region-by-category heatmap of RAA. | ||||
| 165 | +- Product diversity and concentration distributions. | ||||
| 166 | +- Long-tail merchant catalogue rank-size plot. | ||||
| 167 | +- Product-category network and robust community analysis. | ||||
| 168 | +- Matched-product geographic price dispersion distributions. | ||||
| 169 | +- Complexity-versus-regional-development comparisons with uncertainty. | ||||
| 170 | +- Historical diversification/event-study figures only where history supports them. | ||||
| 171 | +- Robustness coefficient plots and transparent sample attrition diagram. | ||||
| 172 | + | ||||
| 173 | +Every figure must be generated by a script with labeled units, sample size, time period, source, and reproducible data transformations. Every table should include standard errors or uncertainty, specification details, and limitations. | ||||
| 174 | + | ||||
| 175 | +## Phase 8 — Manuscript | ||||
| 176 | + | ||||
| 177 | +Write a professional English research article in LaTeX with: | ||||
| 178 | + | ||||
| 179 | +1. Title page, author placeholders, UQO affiliation (verify exact wording), date, abstract, keywords, JEL codes. | ||||
| 180 | +2. Introduction with measured contribution and no inflated novelty claims. | ||||
| 181 | +3. Literature review and positioning. | ||||
| 182 | +4. Institutional setting and Fabri-Ka coverage. | ||||
| 183 | +5. Data collection, cleaning, sampling, provenance, and representativeness. | ||||
| 184 | +6. Conceptual framework and preregistered hypotheses. | ||||
| 185 | +7. Empirical methods and identification limits. | ||||
| 186 | +8. Main results with real tables and figures. | ||||
| 187 | +9. Robustness, alternative specifications, and external validation. | ||||
| 188 | +10. Economic interpretation, policy relevance, and limitations. | ||||
| 189 | +11. Conclusion, references, appendices, data dictionary, reproducibility statement. | ||||
| 190 | + | ||||
| 191 | +Use a polished journal-style layout, vector figures, consistent notation, readable tables, and a verified BibTeX bibliography. Compile `paper/main.pdf` and inspect the output. Never write results sections in the past tense unless the experiments have actually run. If blocked, provide a manuscript skeleton with explicit TODO markers rather than fictional findings. | ||||
| 192 | + | ||||
| 193 | +## Phase 9 — Independent adversarial review | ||||
| 194 | + | ||||
| 195 | +Perform three distinct reviews: econometric referee, economic geography referee, and data-engineering/reproducibility referee. Each must identify the most serious threats, attempted falsification tests, unresolved limitations, and a prioritized remediation plan. Re-run relevant experiments after corrections. Maintain `reports/referee_responses.md`. | ||||
| 196 | + | ||||
| 197 | +## Completion requirements | ||||
| 198 | + | ||||
| 199 | +Deliver: | ||||
| 200 | + | ||||
| 201 | +- `paper/main.tex` and compiled `paper/main.pdf` when supported by actual data. | ||||
| 202 | +- Complete runnable analysis pipeline and pinned dependencies. | ||||
| 203 | +- `reports/00_source_audit.md`, data dictionary, sample-flow table, quality metrics. | ||||
| 204 | +- Verified literature matrix and references. | ||||
| 205 | +- Hypothesis registry and model specifications. | ||||
| 206 | +- Actual figures and tables with source provenance. | ||||
| 207 | +- Robustness and validation reports. | ||||
| 208 | +- Independent referee critiques and response log. | ||||
| 209 | +- `README.md` with one-command reproduction and exact access requirements. | ||||
| 210 | +- Clear statement of which hypotheses are supported, rejected, inconclusive, or untestable. | ||||
| 211 | + | ||||
| 212 | +## Execution instruction | ||||
| 213 | + | ||||
| 214 | +Start immediately with Phase 0. Do not skip directly to writing the paper. Work autonomously within authorized resources, validate every stage, and record blockers precisely. Aim for an original, defensible research contribution suitable for serious peer review, not merely a polished-looking PDF. | ||||
added
config/settings.yaml
+46 −0
@@ -0,0 +1,46 @@ | |||||
| 1 | +# WP38 — global settings (single source of truth for paths, seeds, snapshot identity) | ||||
| 2 | +project: wp38-uqo | ||||
| 3 | +snapshot: | ||||
| 4 | + id: fabrika-snapshot-20261101 | ||||
| 5 | + path: data/raw/fabrika-snapshot-20261101/fabrika-snapshot-20261101.db | ||||
| 6 | + sha256: 8d963ba9f1f7a7b73a0d8177f6017b1ea53c2bd455aef7b5ef4814dedc0d98fb | ||||
| 7 | + taken_utc: "2026-11-01T17:38:30Z" | ||||
| 8 | + fabrika_commit: 689c7bb1e2befc4ae532854ba3af3037d007a323 | ||||
| 9 | + stores_registry: data/raw/fabrika-snapshot-20261101/stores.json | ||||
| 10 | + stores_registry_sha256: 4d5674e1d50bdfb2b9e161c231bbdd5ac31b94b31605cfda079de8a95237d552 | ||||
| 11 | + taxonomy: data/raw/fabrika-snapshot-20261101/collections_taxonomy.json | ||||
| 12 | + dropped_tables: [users, inscriptions, products_fts, sqlite_stat1] | ||||
| 13 | +seed: 20261101 | ||||
| 14 | +timezone_display: America/Toronto | ||||
| 15 | +paths: | ||||
| 16 | + interim: data/interim | ||||
| 17 | + processed: data/processed | ||||
| 18 | + figures: paper/figures | ||||
| 19 | + tables: paper/tables | ||||
| 20 | + logs: logs | ||||
| 21 | + reports: reports | ||||
| 22 | + experiments: experiments | ||||
| 23 | +# Observation window actually present in the snapshot (products.first_seen / sync_log.ts, UTC) | ||||
| 24 | +panel: | ||||
| 25 | + start: "2026-08-12" | ||||
| 26 | + end: "2026-11-01" | ||||
| 27 | + sync_cadence_hours_median: 6.3 | ||||
| 28 | + store_onboarding_weeks: ["2026-W32", "2026-W33"] # 1 594 of 1 609 stores first observed in these two weeks | ||||
| 29 | +regions: # 17 Quebec administrative regions, canonical spelling used by Fabri-Ka | ||||
| 30 | + - Bas-Saint-Laurent | ||||
| 31 | + - Saguenay–Lac-Saint-Jean | ||||
| 32 | + - Capitale-Nationale | ||||
| 33 | + - Mauricie | ||||
| 34 | + - Estrie | ||||
| 35 | + - Montréal | ||||
| 36 | + - Outaouais | ||||
| 37 | + - Abitibi-Témiscamingue | ||||
| 38 | + - Côte-Nord | ||||
| 39 | + - Nord-du-Québec | ||||
| 40 | + - Gaspésie–Îles-de-la-Madeleine | ||||
| 41 | + - Chaudière-Appalaches | ||||
| 42 | + - Laval | ||||
| 43 | + - Lanaudière | ||||
| 44 | + - Laurentides | ||||
| 45 | + - Montérégie | ||||
| 46 | + - Centre-du-Québec | ||||
added
data/interim/.gitkeep
+0 −0
added
data/processed/.gitkeep
+0 −0
added
data/raw/README.md
+16 −0
@@ -0,0 +1,16 @@ | |||||
| 1 | +# data/raw — provenance (not committed) | ||||
| 2 | + | ||||
| 3 | +`fabrika-snapshot-20261101/` is an **owner-authorised, read-only research copy** of the Fabri-Ka production database | ||||
| 4 | +(`M4M64a:~/fabri-ka/data/fabrika.db`, application commit `689c7bb1e2befc4ae532854ba3af3037d007a323`), taken with | ||||
| 5 | +`sqlite3.Connection.backup()` on 2026-11-01T17:38:30Z. Tables `users` and `inscriptions` (personal data) and the derived | ||||
| 6 | +`products_fts` index were dropped before the copy left the node; nothing in production was modified. | ||||
| 7 | + | ||||
| 8 | +| file | sha256 | notes | | ||||
| 9 | +|---|---|---| | ||||
| 10 | +| `fabrika-snapshot-20261101.db` | `8d963ba9f1f7a7b73a0d8177f6017b1ea53c2bd455aef7b5ef4814dedc0d98fb` | 1 244 692 480 bytes; tables `stores` (4 082), `products` (465 388), `sync_log` (577 773) | | ||||
| 11 | +| `stores.json` | `4d5674e1d50bdfb2b9e161c231bbdd5ac31b94b31605cfda079de8a95237d552` | discovery registry (sources, evidence, geo) | | ||||
| 12 | +| `collections_taxonomy.json` | `509f5985da4fa7caae8ed1af4e604a091a9029f0ead44ff05a249d6f58aed207` | collection → category hints | | ||||
| 13 | +| `manifest.json` | — | written by the snapshot script on the node | | ||||
| 14 | + | ||||
| 15 | +External public datasets (Statistics Canada, ISQ, Données Québec) are downloaded by `src/ingest/external.py` into | ||||
| 16 | +`data/raw/external/` with their URL, licence and retrieval date recorded in `data/raw/external/manifest.json`. | ||||
added
paper/.gitignore
+35 −0
@@ -0,0 +1,35 @@ | |||||
| 1 | +# Raw & processed data — never committed (see data/raw/README.md for provenance) | ||||
| 2 | +data/raw/* | ||||
| 3 | +!data/raw/README.md | ||||
| 4 | +data/processed/* | ||||
| 5 | +!data/processed/.gitkeep | ||||
| 6 | + | ||||
| 7 | +# Python | ||||
| 8 | +__pycache__/ | ||||
| 9 | +*.pyc | ||||
| 10 | +.pytest_cache/ | ||||
| 11 | +.venv/ | ||||
| 12 | +*.egg-info/ | ||||
| 13 | + | ||||
| 14 | +# LaTeX build artifacts (paper/main.pdf IS committed) | ||||
| 15 | +paper/*.aux | ||||
| 16 | +paper/*.log | ||||
| 17 | +paper/*.out | ||||
| 18 | +paper/*.toc | ||||
| 19 | +paper/*.lof | ||||
| 20 | +paper/*.lot | ||||
| 21 | +paper/*.fls | ||||
| 22 | +paper/*.fdb_latexmk | ||||
| 23 | +paper/*.bbl | ||||
| 24 | +paper/*.blg | ||||
| 25 | +paper/*.spl | ||||
| 26 | +paper/*.synctex.gz | ||||
| 27 | +paper/*.run.xml | ||||
| 28 | +paper/*.bcf | ||||
| 29 | + | ||||
| 30 | +# Logs | ||||
| 31 | +logs/ | ||||
| 32 | +*.log | ||||
| 33 | + | ||||
| 34 | +# macOS | ||||
| 35 | +.DS_Store | ||||
added
paper/.latexmkrc
+5 −0
@@ -0,0 +1,5 @@ | |||||
| 1 | +$pdf_mode = 1; | ||||
| 2 | +$pdflatex = 'pdflatex -interaction=nonstopmode -halt-on-error -synctex=1 %O %S'; | ||||
| 3 | +$bibtex_use = 2; | ||||
| 4 | +$clean_ext = 'synctex.gz run.xml bbl bcf fdb_latexmk fls log aux out toc lof lot blg'; | ||||
| 5 | +@default_files = ('main.tex'); | ||||
added
paper/Makefile
+11 −0
@@ -0,0 +1,11 @@ | |||||
| 1 | +.PHONY: all clean distclean | ||||
| 2 | + | ||||
| 3 | +all: | ||||
| 4 | + latexmk | ||||
| 5 | + | ||||
| 6 | +clean: | ||||
| 7 | + latexmk -c | ||||
| 8 | + | ||||
| 9 | +distclean: | ||||
| 10 | + latexmk -C | ||||
| 11 | + rm -f *.synctex.gz *.run.xml *.bbl *.bcf | ||||
added
paper/README.md
+109 −0
@@ -0,0 +1,109 @@ | |||||
| 1 | +<!-- Author: Simon-Pierre Boucher — simon-pierre.boucher@uqo.ca --> | ||||
| 2 | +# <Emoji> <Title> | ||||
| 3 | + | ||||
| 4 | +**UQO Working Paper No. <N>** — *<Subtitle, or one-line description>* | ||||
| 5 | + | ||||
| 6 | +[-b31b1b?logo=latex&logoColor=white)](paper/main.pdf) | ||||
| 7 | +[](requirements.txt) | ||||
| 8 | +[](data/raw/README.md) | ||||
| 9 | +[](scripts/) | ||||
| 10 | +[](https://uqo.ca) | ||||
| 11 | +[](mailto:simon-pierre.boucher@uqo.ca) | ||||
| 12 | + | ||||
| 13 | +> **TL;DR** — Three to six lines: question, data (size, period), method, headline numbers, takeaway. | ||||
| 14 | + | ||||
| 15 | +--- | ||||
| 16 | + | ||||
| 17 | +## 📌 Status | ||||
| 18 | + | ||||
| 19 | +| Item | Value | | ||||
| 20 | +|---|---| | ||||
| 21 | +| Version | <x.y> (<Month YYYY>) | | ||||
| 22 | +| SSRN | <abstract ID + link> / not yet submitted | | ||||
| 23 | +| Journal | <target or submission status> / — | | ||||
| 24 | +| Code & data | reproducible from `scripts/` (see Quick start); raw data not redistributed | | ||||
| 25 | + | ||||
| 26 | +## 🎯 What this paper does | ||||
| 27 | + | ||||
| 28 | +Two or three paragraphs: research question, why it matters, what is new. Core equation if any: | ||||
| 29 | + | ||||
| 30 | +``` | ||||
| 31 | +y_i = α + x_i'β + ε_i | ||||
| 32 | +``` | ||||
| 33 | + | ||||
| 34 | +## 🏆 Headline results | ||||
| 35 | + | ||||
| 36 | +| Object | Estimate | | ||||
| 37 | +|---|---| | ||||
| 38 | +| … | … | | ||||
| 39 | + | ||||
| 40 | +## 🗂 Repository layout | ||||
| 41 | + | ||||
| 42 | +``` | ||||
| 43 | +<repo>/ | ||||
| 44 | +├── data/ | ||||
| 45 | +│ ├── raw/ # <source snapshot> (see data/raw/README.md) — not committed | ||||
| 46 | +│ └── processed/ # built by step 01 | ||||
| 47 | +├── src/<pkg>/ # reusable package | ||||
| 48 | +├── scripts/ # the pipeline, in order | ||||
| 49 | +│ ├── 01_….py | ||||
| 50 | +│ └── … | ||||
| 51 | +├── results/ # CSV / JSON emitted by the scripts | ||||
| 52 | +├── figures/ # publication figures | ||||
| 53 | +└── paper/ # main.tex + sections/ + references.bib → main.pdf | ||||
| 54 | +``` | ||||
| 55 | + | ||||
| 56 | +## 🚀 Quick start | ||||
| 57 | + | ||||
| 58 | +```bash | ||||
| 59 | +python3 -m pip install -r requirements.txt | ||||
| 60 | +python3 scripts/01_….py | ||||
| 61 | +… | ||||
| 62 | +cd paper && make # latexmk → main.pdf | ||||
| 63 | +``` | ||||
| 64 | + | ||||
| 65 | +Runtime and memory on an Apple-silicon laptop. | ||||
| 66 | + | ||||
| 67 | +## 🗃 Data | ||||
| 68 | + | ||||
| 69 | +Provenance, extraction date, number of observations, filters (sample cascade), how to obtain the raw snapshot. | ||||
| 70 | + | ||||
| 71 | +## 🔬 Methodology | ||||
| 72 | + | ||||
| 73 | +Numbered list of the estimation steps, each pointing to the module that implements it. | ||||
| 74 | + | ||||
| 75 | +## 🖼 Figures & tables inventory | ||||
| 76 | + | ||||
| 77 | +| Figure | Content | | ||||
| 78 | +|---|---| | ||||
| 79 | +| `fig_…` | … | | ||||
| 80 | + | ||||
| 81 | +Tables (`paper/tables/*.tex`): …. | ||||
| 82 | + | ||||
| 83 | +## ⚠️ Limitations | ||||
| 84 | + | ||||
| 85 | +- … | ||||
| 86 | + | ||||
| 87 | +## 📝 Citation | ||||
| 88 | + | ||||
| 89 | +```bibtex | ||||
| 90 | +@techreport{boucher2026<key>, | ||||
| 91 | + author = {Boucher, Simon-Pierre}, | ||||
| 92 | + title = {<Title>: <Subtitle>}, | ||||
| 93 | + institution = {Universit\'e du Qu\'ebec en Outaouais, D\'epartement des sciences administratives}, | ||||
| 94 | + type = {Working Paper}, | ||||
| 95 | + number = {<N>}, | ||||
| 96 | + year = {2026}, | ||||
| 97 | + month = {<Month>} | ||||
| 98 | +} | ||||
| 99 | +``` | ||||
| 100 | + | ||||
| 101 | +## 👤 Author & contact | ||||
| 102 | + | ||||
| 103 | +**Simon-Pierre Boucher** — Département des sciences administratives, | ||||
| 104 | +Université du Québec en Outaouais (UQO), Gatineau, QC. | ||||
| 105 | +📧 [simon-pierre.boucher@uqo.ca](mailto:simon-pierre.boucher@uqo.ca) | ||||
| 106 | + | ||||
| 107 | +## 🗒 Notes | ||||
| 108 | + | ||||
| 109 | +- Numbering history / deviations from `Recherche-UQO/HARMONISATION.md`, if any. | ||||
added
paper/appendix/appendix.tex
+93 −0
@@ -0,0 +1,93 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% Appendix | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\newpage | ||||
| 5 | +\begin{appendices} | ||||
| 6 | + | ||||
| 7 | +\renewcommand{\thetable}{A\arabic{table}} | ||||
| 8 | +\renewcommand{\thefigure}{A\arabic{figure}} | ||||
| 9 | +\setcounter{table}{0} | ||||
| 10 | +\setcounter{figure}{0} | ||||
| 11 | + | ||||
| 12 | +\section{Additional Tables and Figures} | ||||
| 13 | +\label{app:tables} | ||||
| 14 | + | ||||
| 15 | +% --- Appendix Table: Sub-sample Analysis --- | ||||
| 16 | +\begin{table}[htbp] | ||||
| 17 | + \centering | ||||
| 18 | + \begin{threeparttable} | ||||
| 19 | + \caption{Sub-sample Analysis} | ||||
| 20 | + \label{tab:app_subsample} | ||||
| 21 | + \begin{tabular}{@{}lccc@{}} | ||||
| 22 | + \toprule | ||||
| 23 | + & (1) & (2) & (3) \\ | ||||
| 24 | + & Full Sample & Pre-2008 & Post-2008 \\ | ||||
| 25 | + \midrule | ||||
| 26 | + $X_{i,t}$ & 0.172$^{***}$ & 0.195$^{***}$ & 0.148$^{***}$ \\ | ||||
| 27 | + & (0.033) & (0.048) & (0.041) \\[6pt] | ||||
| 28 | + \midrule | ||||
| 29 | + Controls & Yes & Yes & Yes \\ | ||||
| 30 | + Firm FE & Yes & Yes & Yes \\ | ||||
| 31 | + Time FE & Yes & Yes & Yes \\[3pt] | ||||
| 32 | + Observations & 125{,}400 & 58{,}200 & 67{,}200 \\ | ||||
| 33 | + Adjusted $R^2$ & 0.190 & 0.175 & 0.203 \\ | ||||
| 34 | + \bottomrule | ||||
| 35 | + \end{tabular} | ||||
| 36 | + \begin{tablenotes}[flushleft] | ||||
| 37 | + \footnotesize | ||||
| 38 | + \item \textit{Notes:} This table reports sub-sample results. Column~(1) reproduces the baseline estimate from Table~\ref{tab:regression}, Column~(4). Columns~(2) and~(3) split the sample before and after January~2008. All specifications include the full set of controls and firm and time fixed effects. Standard errors clustered at the firm level are in parentheses. $^{***}$, $^{**}$, and $^{*}$ denote significance at the 1\%, 5\%, and 10\% levels. | ||||
| 39 | + \end{tablenotes} | ||||
| 40 | + \end{threeparttable} | ||||
| 41 | +\end{table} | ||||
| 42 | + | ||||
| 43 | +% --- Appendix Table: Robustness Checks --- | ||||
| 44 | +\begin{table}[htbp] | ||||
| 45 | + \centering | ||||
| 46 | + \begin{threeparttable} | ||||
| 47 | + \caption{Robustness Checks} | ||||
| 48 | + \label{tab:app_robustness} | ||||
| 49 | + \begin{tabular}{@{}lccc@{}} | ||||
| 50 | + \toprule | ||||
| 51 | + & (1) & (2) & (3) \\ | ||||
| 52 | + & Alt.\ Dep.\ Var. & Alt.\ Controls & Winsorized 5\% \\ | ||||
| 53 | + \midrule | ||||
| 54 | + $X_{i,t}$ & 0.165$^{***}$ & 0.178$^{***}$ & 0.169$^{***}$ \\ | ||||
| 55 | + & (0.036) & (0.034) & (0.032) \\[6pt] | ||||
| 56 | + \midrule | ||||
| 57 | + Controls & Yes & Yes & Yes \\ | ||||
| 58 | + Firm FE & Yes & Yes & Yes \\ | ||||
| 59 | + Time FE & Yes & Yes & Yes \\[3pt] | ||||
| 60 | + Observations & 125{,}400 & 125{,}400 & 119{,}800 \\ | ||||
| 61 | + Adjusted $R^2$ & 0.185 & 0.192 & 0.195 \\ | ||||
| 62 | + \bottomrule | ||||
| 63 | + \end{tabular} | ||||
| 64 | + \begin{tablenotes}[flushleft] | ||||
| 65 | + \footnotesize | ||||
| 66 | + \item \textit{Notes:} This table reports robustness checks. Column~(1) uses an alternative dependent variable. Column~(2) includes additional control variables. Column~(3) winsorizes all continuous variables at the 5th and 95th percentiles. All specifications include firm and time fixed effects. Standard errors clustered at the firm level are in parentheses. $^{***}$, $^{**}$, and $^{*}$ denote significance at the 1\%, 5\%, and 10\% levels. | ||||
| 67 | + \end{tablenotes} | ||||
| 68 | + \end{threeparttable} | ||||
| 69 | +\end{table} | ||||
| 70 | + | ||||
| 71 | +\section{Variable Definitions} | ||||
| 72 | +\label{app:variables} | ||||
| 73 | + | ||||
| 74 | +\begin{table}[htbp] | ||||
| 75 | + \centering | ||||
| 76 | + \caption{Variable Definitions} | ||||
| 77 | + \label{tab:app_variables} | ||||
| 78 | + \begin{tabular}{@{}p{3.5cm}p{10cm}@{}} | ||||
| 79 | + \toprule | ||||
| 80 | + Variable & Definition \\ | ||||
| 81 | + \midrule | ||||
| 82 | + $r_{i,t}$ & Monthly log return of firm $i$ in month $t$, computed as $\ln(P_{i,t}/P_{i,t-1})$. \\[4pt] | ||||
| 83 | + $\sigma_{i,t}$ & Monthly realized volatility of firm $i$, computed as the standard deviation of daily returns within month $t$, annualized by multiplying by $\sqrt{252}$. \\[4pt] | ||||
| 84 | + $X_{i,t}$ & Main explanatory variable. [Provide specific definition.] \\[4pt] | ||||
| 85 | + Size & Natural logarithm of market capitalization (in millions of USD) at the end of month $t-1$. \\[4pt] | ||||
| 86 | + Book-to-Market & Ratio of book equity to market equity, using the most recent fiscal year-end book value and the market value at the end of June. Updated annually following \citet{fama1993common}. \\[4pt] | ||||
| 87 | + Leverage & Total debt divided by total assets, measured at the most recent fiscal year-end. \\[4pt] | ||||
| 88 | + ROA & Return on assets, defined as net income divided by total assets. \\ | ||||
| 89 | + \bottomrule | ||||
| 90 | + \end{tabular} | ||||
| 91 | +\end{table} | ||||
| 92 | + | ||||
| 93 | +\end{appendices} | ||||
added
paper/figures/main_figure.tex
+20 −0
@@ -0,0 +1,20 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% Figure: Main Result | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\begin{figure}[htbp] | ||||
| 5 | + \centering | ||||
| 6 | + % --- Replace placeholder with actual figure file --- | ||||
| 7 | + % \includegraphics[width=0.85\textwidth]{figures/main_result.pdf} | ||||
| 8 | + % | ||||
| 9 | + % Placeholder box (remove when replacing with actual figure) | ||||
| 10 | + \fbox{\parbox{0.85\textwidth}{\centering\vspace{4cm} | ||||
| 11 | + \textit{[Insert figure here: figures/main\_result.pdf]} | ||||
| 12 | + \vspace{4cm}}} | ||||
| 13 | + % | ||||
| 14 | + \caption{Main Result --- Effect of $X$ on $Y$ Over Time} | ||||
| 15 | + \label{fig:main_result} | ||||
| 16 | + \begin{minipage}{0.85\textwidth} | ||||
| 17 | + \vspace{0.3cm} | ||||
| 18 | + \footnotesize\textit{Notes:} This figure plots \ldots{} over the sample period January~1990 to December~2023. The solid line represents \ldots{} The shaded area indicates the 95\% confidence interval. The dashed vertical line marks \ldots{} | ||||
| 19 | + \end{minipage} | ||||
| 20 | +\end{figure} | ||||
added
paper/main.tex
+143 −0
@@ -0,0 +1,143 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% UQO Working Paper Template — Economics / Finance | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\documentclass[12pt,letterpaper]{article} | ||||
| 5 | + | ||||
| 6 | +% --- Encoding & Language --- | ||||
| 7 | +\usepackage[utf8]{inputenc} | ||||
| 8 | +\usepackage[T1]{fontenc} | ||||
| 9 | +\usepackage[english]{babel} | ||||
| 10 | + | ||||
| 11 | +% --- Page Layout --- | ||||
| 12 | +\usepackage[ | ||||
| 13 | + letterpaper, | ||||
| 14 | + top=1in, | ||||
| 15 | + bottom=1in, | ||||
| 16 | + left=1in, | ||||
| 17 | + right=1in | ||||
| 18 | +]{geometry} | ||||
| 19 | + | ||||
| 20 | +% --- Typography --- | ||||
| 21 | +\usepackage{mathptmx} % Times-like font (text + math) | ||||
| 22 | +\usepackage{microtype} % Improved typographic refinements | ||||
| 23 | +\usepackage{setspace} | ||||
| 24 | +\onehalfspacing % 1.5 line spacing | ||||
| 25 | + | ||||
| 26 | +% --- Math --- | ||||
| 27 | +\usepackage{amsmath,amssymb,amsthm} | ||||
| 28 | + | ||||
| 29 | +% --- Tables --- | ||||
| 30 | +\usepackage{booktabs} | ||||
| 31 | +\usepackage{tabularx} | ||||
| 32 | +\usepackage{multirow} | ||||
| 33 | +\usepackage{threeparttable} | ||||
| 34 | +\usepackage{siunitx} | ||||
| 35 | +\sisetup{ | ||||
| 36 | + input-symbols = {()}, | ||||
| 37 | + table-format = -1.3, | ||||
| 38 | + parse-numbers = false | ||||
| 39 | +} | ||||
| 40 | + | ||||
| 41 | +% --- Figures --- | ||||
| 42 | +\usepackage{graphicx} | ||||
| 43 | +\usepackage{subcaption} | ||||
| 44 | +\usepackage{float} | ||||
| 45 | + | ||||
| 46 | +% --- Colors & Links --- | ||||
| 47 | +\usepackage[dvipsnames]{xcolor} | ||||
| 48 | +\usepackage[ | ||||
| 49 | + colorlinks = true, | ||||
| 50 | + linkcolor = NavyBlue, | ||||
| 51 | + citecolor = NavyBlue, | ||||
| 52 | + urlcolor = NavyBlue, | ||||
| 53 | + breaklinks = true | ||||
| 54 | +]{hyperref} | ||||
| 55 | + | ||||
| 56 | +% --- Bibliography --- | ||||
| 57 | +\usepackage[authoryear,round,semicolon]{natbib} | ||||
| 58 | +\bibliographystyle{aer} | ||||
| 59 | + | ||||
| 60 | +% --- Captions --- | ||||
| 61 | +\usepackage[ | ||||
| 62 | + font = small, | ||||
| 63 | + labelfont = bf, | ||||
| 64 | + labelsep = period, | ||||
| 65 | + justification = justified, | ||||
| 66 | + singlelinecheck = false | ||||
| 67 | +]{caption} | ||||
| 68 | + | ||||
| 69 | +% --- Headers & Footers --- | ||||
| 70 | +\usepackage{fancyhdr} | ||||
| 71 | +\pagestyle{fancy} | ||||
| 72 | +\fancyhf{} | ||||
| 73 | +\renewcommand{\headrulewidth}{0pt} | ||||
| 74 | +\fancyfoot[C]{\thepage} | ||||
| 75 | + | ||||
| 76 | +% --- Section Formatting --- | ||||
| 77 | +\usepackage{titlesec} | ||||
| 78 | +\titleformat{\section}{\large\bfseries}{\thesection.}{0.5em}{} | ||||
| 79 | +\titleformat{\subsection}{\normalsize\bfseries}{\thesubsection.}{0.5em}{} | ||||
| 80 | +\titleformat{\subsubsection}{\normalsize\itshape}{\thesubsubsection.}{0.5em}{} | ||||
| 81 | + | ||||
| 82 | +% --- Appendix Support --- | ||||
| 83 | +\usepackage[toc,page]{appendix} | ||||
| 84 | + | ||||
| 85 | +% --- Misc --- | ||||
| 86 | +\usepackage{enumitem} | ||||
| 87 | +\setlist{nosep,leftmargin=*} | ||||
| 88 | + | ||||
| 89 | +% ============================================================================ | ||||
| 90 | +% METADATA — Edit these fields for each working paper | ||||
| 91 | +% ============================================================================ | ||||
| 92 | +\newcommand{\WPnumber}{XX} | ||||
| 93 | +\newcommand{\WPtitle}{Your Working Paper Title Here} | ||||
| 94 | +\newcommand{\WPsubtitle}{} % Leave empty if no subtitle | ||||
| 95 | +\newcommand{\WPdate}{\today} | ||||
| 96 | +\newcommand{\WPversion}{1.0} | ||||
| 97 | +\newcommand{\WPabstract}{% | ||||
| 98 | + This paper examines \ldots{} | ||||
| 99 | + We find that \ldots{} | ||||
| 100 | + Our results suggest \ldots{} | ||||
| 101 | + These findings contribute to the literature on \ldots{} | ||||
| 102 | +} | ||||
| 103 | +\newcommand{\WPkeywords}{Keyword 1, Keyword 2, Keyword 3, Keyword 4} | ||||
| 104 | +\newcommand{\WPjel}{G12, G14, C58} | ||||
| 105 | + | ||||
| 106 | +% --- Author --- | ||||
| 107 | +\newcommand{\WPauthor}{Simon-Pierre Boucher} | ||||
| 108 | +\newcommand{\WPaffiliation}{% | ||||
| 109 | + Département des sciences administratives\\ | ||||
| 110 | + Université du Québec en Outaouais% | ||||
| 111 | +} | ||||
| 112 | +\newcommand{\WPemail}{simon-pierre.boucher@uqo.ca} | ||||
| 113 | +\newcommand{\WPaddress}{% | ||||
| 114 | + Gatineau -- Pavillon Alexandre-Taché\\ | ||||
| 115 | + 283, boulevard Alexandre-Taché\\ | ||||
| 116 | + Gatineau, Québec, Canada J9A 1L8% | ||||
| 117 | +} | ||||
| 118 | + | ||||
| 119 | +% ============================================================================ | ||||
| 120 | +% DOCUMENT | ||||
| 121 | +% ============================================================================ | ||||
| 122 | +\begin{document} | ||||
| 123 | + | ||||
| 124 | +% --- Title Page --- | ||||
| 125 | +\input{sections/titlepage} | ||||
| 126 | + | ||||
| 127 | +% --- Main Body --- | ||||
| 128 | +\input{sections/introduction} | ||||
| 129 | +\input{sections/literature} | ||||
| 130 | +\input{sections/data} | ||||
| 131 | +\input{sections/methodology} | ||||
| 132 | +\input{sections/results} | ||||
| 133 | +\input{sections/robustness} | ||||
| 134 | +\input{sections/conclusion} | ||||
| 135 | + | ||||
| 136 | +% --- References --- | ||||
| 137 | +\newpage | ||||
| 138 | +\bibliography{references} | ||||
| 139 | + | ||||
| 140 | +% --- Appendix --- | ||||
| 141 | +\input{appendix/appendix} | ||||
| 142 | + | ||||
| 143 | +\end{document} | ||||
added
paper/references.bib
+61 −0
@@ -0,0 +1,61 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% References — BibTeX Database | ||||
| 3 | +% ============================================================================ | ||||
| 4 | + | ||||
| 5 | +@article{fama1993common, | ||||
| 6 | + author = {Fama, Eugene F. and French, Kenneth R.}, | ||||
| 7 | + title = {Common Risk Factors in the Returns on Stocks and Bonds}, | ||||
| 8 | + journal = {Journal of Financial Economics}, | ||||
| 9 | + volume = {33}, | ||||
| 10 | + number = {1}, | ||||
| 11 | + pages = {3--56}, | ||||
| 12 | + year = {1993} | ||||
| 13 | +} | ||||
| 14 | + | ||||
| 15 | +@article{bollerslev1986generalized, | ||||
| 16 | + author = {Bollerslev, Tim}, | ||||
| 17 | + title = {Generalized Autoregressive Conditional Heteroskedasticity}, | ||||
| 18 | + journal = {Journal of Econometrics}, | ||||
| 19 | + volume = {31}, | ||||
| 20 | + number = {3}, | ||||
| 21 | + pages = {307--327}, | ||||
| 22 | + year = {1986} | ||||
| 23 | +} | ||||
| 24 | + | ||||
| 25 | +@article{newey1987simple, | ||||
| 26 | + author = {Newey, Whitney K. and West, Kenneth D.}, | ||||
| 27 | + title = {A Simple, Positive Semi-Definite, Heteroskedasticity and Autocorrelation Consistent Covariance Matrix}, | ||||
| 28 | + journal = {Econometrica}, | ||||
| 29 | + volume = {55}, | ||||
| 30 | + number = {3}, | ||||
| 31 | + pages = {703--708}, | ||||
| 32 | + year = {1987} | ||||
| 33 | +} | ||||
| 34 | + | ||||
| 35 | +@article{white1980heteroskedasticity, | ||||
| 36 | + author = {White, Halbert}, | ||||
| 37 | + title = {A Heteroskedasticity-Consistent Covariance Matrix Estimator and a Direct Test for Heteroskedasticity}, | ||||
| 38 | + journal = {Econometrica}, | ||||
| 39 | + volume = {48}, | ||||
| 40 | + number = {4}, | ||||
| 41 | + pages = {817--838}, | ||||
| 42 | + year = {1980} | ||||
| 43 | +} | ||||
| 44 | + | ||||
| 45 | +@book{cochrane2005asset, | ||||
| 46 | + author = {Cochrane, John H.}, | ||||
| 47 | + title = {Asset Pricing}, | ||||
| 48 | + edition = {Revised}, | ||||
| 49 | + publisher = {Princeton University Press}, | ||||
| 50 | + year = {2005} | ||||
| 51 | +} | ||||
| 52 | + | ||||
| 53 | +@article{petersen2009estimating, | ||||
| 54 | + author = {Petersen, Mitchell A.}, | ||||
| 55 | + title = {Estimating Standard Errors in Finance Panel Data Sets: Comparing Approaches}, | ||||
| 56 | + journal = {Review of Financial Studies}, | ||||
| 57 | + volume = {22}, | ||||
| 58 | + number = {1}, | ||||
| 59 | + pages = {435--480}, | ||||
| 60 | + year = {2009} | ||||
| 61 | +} | ||||
added
paper/sections/conclusion.tex
+12 −0
@@ -0,0 +1,12 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Conclusion} | ||||
| 3 | +\label{sec:conclusion} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +This paper investigates \ldots{} Using data from \ldots{} over the period \ldots{}, we find that \ldots{} | ||||
| 7 | + | ||||
| 8 | +Our results contribute to the literature in several ways. First, \ldots{} Second, \ldots{} Third, \ldots{} | ||||
| 9 | + | ||||
| 10 | +These findings have important implications for \ldots{} From a policy perspective, \ldots{} For practitioners, \ldots{} | ||||
| 11 | + | ||||
| 12 | +Several limitations of the present study suggest directions for future research. First, \ldots{} Second, \ldots{} We leave these questions for future work. | ||||
added
paper/sections/data.tex
+32 −0
@@ -0,0 +1,32 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Data} | ||||
| 3 | +\label{sec:data} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +\subsection{Data Sources} | ||||
| 7 | +\label{subsec:data_sources} | ||||
| 8 | + | ||||
| 9 | +We obtain data from \ldots{} Our sample spans the period from January~1990 to December~2023, covering \ldots{} We exclude \ldots{} consistent with standard practice in the literature \citep{fama1993common}. | ||||
| 10 | + | ||||
| 11 | +\subsection{Variable Construction} | ||||
| 12 | +\label{subsec:variables} | ||||
| 13 | + | ||||
| 14 | +Our dependent variable is \ldots{} defined as: | ||||
| 15 | +% | ||||
| 16 | +\begin{equation} | ||||
| 17 | + r_{i,t} = \ln\!\left(\frac{P_{i,t}}{P_{i,t-1}}\right), | ||||
| 18 | + \label{eq:returns} | ||||
| 19 | +\end{equation} | ||||
| 20 | +% | ||||
| 21 | +where $P_{i,t}$ denotes the adjusted closing price of asset~$i$ at time~$t$. | ||||
| 22 | + | ||||
| 23 | +The main explanatory variables include \ldots{} | ||||
| 24 | + | ||||
| 25 | +\subsection{Summary Statistics} | ||||
| 26 | +\label{subsec:summary_stats} | ||||
| 27 | + | ||||
| 28 | +Table~\ref{tab:summary_stats} presents the descriptive statistics for our key variables. | ||||
| 29 | + | ||||
| 30 | +\input{tables/summary_stats} | ||||
| 31 | + | ||||
| 32 | +Several patterns emerge from the summary statistics. First, \ldots{} Second, \ldots{} The standard deviations indicate \ldots{} | ||||
added
paper/sections/introduction.tex
+14 −0
@@ -0,0 +1,14 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Introduction} | ||||
| 3 | +\label{sec:introduction} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +The question of \ldots{} has attracted considerable attention in the finance and economics literature. Despite the growing body of evidence, the mechanisms underlying \ldots{} remain poorly understood. This paper contributes to this line of research by \ldots{} | ||||
| 7 | + | ||||
| 8 | +The motivation for this study is threefold. First, \ldots{} Second, \ldots{} Third, \ldots{} | ||||
| 9 | + | ||||
| 10 | +Our main findings can be summarized as follows. We show that \ldots{} Furthermore, we document that \ldots{} Finally, our robustness checks confirm that \ldots{} | ||||
| 11 | + | ||||
| 12 | +This paper relates to several strands of the literature. First, it contributes to the literature on \ldots{} \citep{fama1993common}. Second, it builds on the work of \citet{bollerslev1986generalized} by \ldots{} Third, our methodological approach draws on \citet{newey1987simple}. | ||||
| 13 | + | ||||
| 14 | +The remainder of the paper is organized as follows. Section~\ref{sec:literature} reviews the related literature. Section~\ref{sec:data} describes the data. Section~\ref{sec:methodology} presents the empirical methodology. Section~\ref{sec:results} reports the main results. Section~\ref{sec:robustness} provides robustness checks. Section~\ref{sec:conclusion} concludes. | ||||
added
paper/sections/literature.tex
+21 −0
@@ -0,0 +1,21 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Literature Review} | ||||
| 3 | +\label{sec:literature} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +This section reviews the main theoretical and empirical contributions related to our research question. | ||||
| 7 | + | ||||
| 8 | +\subsection{Theoretical Framework} | ||||
| 9 | +\label{subsec:theory} | ||||
| 10 | + | ||||
| 11 | +The theoretical foundations of \ldots{} were established by \citet{cochrane2005asset}. In their framework, \ldots{} | ||||
| 12 | + | ||||
| 13 | +\subsection{Empirical Evidence} | ||||
| 14 | +\label{subsec:empirical_evidence} | ||||
| 15 | + | ||||
| 16 | +A growing body of empirical literature examines \ldots{} \citet{fama1993common} document that \ldots{} More recently, \citet{petersen2009estimating} show that \ldots{} | ||||
| 17 | + | ||||
| 18 | +\subsection{Contribution to the Literature} | ||||
| 19 | +\label{subsec:contribution} | ||||
| 20 | + | ||||
| 21 | +Our paper departs from the existing literature in several important ways. First, \ldots{} Second, \ldots{} Third, \ldots{} | ||||
added
paper/sections/methodology.tex
+44 −0
@@ -0,0 +1,44 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Methodology} | ||||
| 3 | +\label{sec:methodology} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +\subsection{Empirical Model} | ||||
| 7 | +\label{subsec:model} | ||||
| 8 | + | ||||
| 9 | +To test our hypotheses, we estimate the following baseline specification: | ||||
| 10 | +% | ||||
| 11 | +\begin{equation} | ||||
| 12 | + y_{i,t} = \alpha + \beta_1 X_{i,t} + \beta_2 Z_{i,t} + \gamma_i + \delta_t + \varepsilon_{i,t}, | ||||
| 13 | + \label{eq:baseline} | ||||
| 14 | +\end{equation} | ||||
| 15 | +% | ||||
| 16 | +where $y_{i,t}$ is the dependent variable for firm~$i$ in period~$t$, $X_{i,t}$ is the main variable of interest, $Z_{i,t}$ is a vector of control variables, $\gamma_i$ represents firm fixed effects, $\delta_t$ captures time fixed effects, and $\varepsilon_{i,t}$ is the error term. | ||||
| 17 | + | ||||
| 18 | +Our coefficient of interest is $\beta_1$. Under the null hypothesis that \ldots{}, we expect $\beta_1 = 0$. A positive (negative) estimate of $\beta_1$ would indicate \ldots{} | ||||
| 19 | + | ||||
| 20 | +\subsection{Identification Strategy} | ||||
| 21 | +\label{subsec:identification} | ||||
| 22 | + | ||||
| 23 | +The main identification challenge arises from \ldots{} To address potential endogeneity concerns, we employ \ldots{} | ||||
| 24 | + | ||||
| 25 | +We cluster standard errors at the firm level to account for within-firm serial correlation, following \citet{petersen2009estimating}. | ||||
| 26 | + | ||||
| 27 | +\subsection{Extended Specifications} | ||||
| 28 | +\label{subsec:extended} | ||||
| 29 | + | ||||
| 30 | +We extend the baseline model in several directions. First, we allow for nonlinear effects: | ||||
| 31 | +% | ||||
| 32 | +\begin{equation} | ||||
| 33 | + y_{i,t} = \alpha + \beta_1 X_{i,t} + \beta_2 X_{i,t}^2 + \boldsymbol{\beta}_3' \mathbf{Z}_{i,t} + \gamma_i + \delta_t + \varepsilon_{i,t}. | ||||
| 34 | + \label{eq:nonlinear} | ||||
| 35 | +\end{equation} | ||||
| 36 | + | ||||
| 37 | +Second, we examine heterogeneous effects by interacting $X_{i,t}$ with \ldots{}: | ||||
| 38 | +% | ||||
| 39 | +\begin{equation} | ||||
| 40 | + y_{i,t} = \alpha + \beta_1 X_{i,t} + \beta_2 D_{i,t} + \beta_3 (X_{i,t} \times D_{i,t}) + \boldsymbol{\beta}_4' \mathbf{Z}_{i,t} + \gamma_i + \delta_t + \varepsilon_{i,t}, | ||||
| 41 | + \label{eq:interaction} | ||||
| 42 | +\end{equation} | ||||
| 43 | +% | ||||
| 44 | +where $D_{i,t}$ is an indicator variable equal to one if \ldots{} The coefficient $\beta_3$ captures the differential effect of $X$ for \ldots{} | ||||
added
paper/sections/results.tex
+27 −0
@@ -0,0 +1,27 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Results} | ||||
| 3 | +\label{sec:results} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +\subsection{Baseline Results} | ||||
| 7 | +\label{subsec:baseline_results} | ||||
| 8 | + | ||||
| 9 | +Table~\ref{tab:regression} presents the estimation results of our baseline model specified in Equation~\eqref{eq:baseline}. Column~(1) reports the OLS estimates without fixed effects. Columns~(2)--(4) progressively add firm and time fixed effects and the full set of controls. | ||||
| 10 | + | ||||
| 11 | +\input{tables/regression} | ||||
| 12 | + | ||||
| 13 | +The coefficient on $X_{i,t}$ is positive and statistically significant at the 1\% level across all specifications. The point estimate in our preferred specification (Column~4) implies that a one-standard-deviation increase in $X$ is associated with a \ldots{} increase in $y$. | ||||
| 14 | + | ||||
| 15 | +\subsection{Graphical Evidence} | ||||
| 16 | +\label{subsec:graphical} | ||||
| 17 | + | ||||
| 18 | +Figure~\ref{fig:main_result} provides graphical evidence supporting our main findings. | ||||
| 19 | + | ||||
| 20 | +\input{figures/main_figure} | ||||
| 21 | + | ||||
| 22 | +The figure illustrates \ldots{} The upward trend in \ldots{} is consistent with the regression estimates reported in Table~\ref{tab:regression}. | ||||
| 23 | + | ||||
| 24 | +\subsection{Sub-sample Analysis} | ||||
| 25 | +\label{subsec:subsample} | ||||
| 26 | + | ||||
| 27 | +To explore potential heterogeneity, we re-estimate Equation~\eqref{eq:baseline} across sub-samples defined by \ldots{} The results, available in Table~\ref{tab:app_subsample} of Appendix~\ref{app:tables}, indicate that \ldots{} | ||||
added
paper/sections/robustness.tex
+26 −0
@@ -0,0 +1,26 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +\section{Robustness Checks} | ||||
| 3 | +\label{sec:robustness} | ||||
| 4 | +% ============================================================================ | ||||
| 5 | + | ||||
| 6 | +We conduct several robustness tests to assess the sensitivity of our baseline results. | ||||
| 7 | + | ||||
| 8 | +\subsection{Alternative Variable Definitions} | ||||
| 9 | +\label{subsec:alt_definitions} | ||||
| 10 | + | ||||
| 11 | +We first verify that our results are not driven by the specific construction of the dependent variable. Table~\ref{tab:app_robustness} in Appendix~\ref{app:tables} reports estimates using \ldots{} as alternative measures. The coefficient on $X_{i,t}$ remains statistically significant and economically meaningful across all specifications. | ||||
| 12 | + | ||||
| 13 | +\subsection{Alternative Estimation Methods} | ||||
| 14 | +\label{subsec:alt_estimation} | ||||
| 15 | + | ||||
| 16 | +We re-estimate the model using \ldots{} to address potential concerns about \ldots{} The results are qualitatively unchanged. | ||||
| 17 | + | ||||
| 18 | +\subsection{Placebo Tests} | ||||
| 19 | +\label{subsec:placebo} | ||||
| 20 | + | ||||
| 21 | +As a falsification exercise, we replace the main explanatory variable with \ldots{} If our baseline results reflect a genuine economic relationship rather than spurious correlation, we expect the placebo coefficients to be statistically insignificant. Consistent with this expectation, none of the placebo estimates are significant at conventional levels. | ||||
| 22 | + | ||||
| 23 | +\subsection{Sensitivity to Sample Period} | ||||
| 24 | +\label{subsec:sample_period} | ||||
| 25 | + | ||||
| 26 | +We examine whether our results are sensitive to the sample period by \ldots{} The estimates remain stable across sub-periods, suggesting that our findings are not driven by a specific time window. | ||||
added
paper/sections/titlepage.tex
+77 −0
@@ -0,0 +1,77 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% Title Page | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\thispagestyle{empty} | ||||
| 5 | + | ||||
| 6 | +\begin{center} | ||||
| 7 | + | ||||
| 8 | +% --- Logo --- | ||||
| 9 | +\includegraphics[width=3.5cm]{uq_logo.jpg} | ||||
| 10 | + | ||||
| 11 | +\vspace{0.6cm} | ||||
| 12 | + | ||||
| 13 | +{\footnotesize\textsc{Université du Québec en Outaouais}}\\[0.15cm] | ||||
| 14 | +{\footnotesize\textsc{Département des sciences administratives}} | ||||
| 15 | + | ||||
| 16 | +\vspace{0.8cm} | ||||
| 17 | + | ||||
| 18 | +{\footnotesize\textsc{Working Paper No.~\WPnumber}} | ||||
| 19 | + | ||||
| 20 | +\vspace{1.2cm} | ||||
| 21 | + | ||||
| 22 | +% --- Title --- | ||||
| 23 | +{\LARGE\bfseries \WPtitle\par} | ||||
| 24 | + | ||||
| 25 | +\ifx\WPsubtitle\empty\else | ||||
| 26 | + \vspace{0.3cm} | ||||
| 27 | + {\large\itshape \WPsubtitle\par} | ||||
| 28 | +\fi | ||||
| 29 | + | ||||
| 30 | +\vspace{1.2cm} | ||||
| 31 | + | ||||
| 32 | +% --- Author --- | ||||
| 33 | +{\large \WPauthor}\\[0.3cm] | ||||
| 34 | +{\normalsize \WPaffiliation}\\[0.15cm] | ||||
| 35 | +{\normalsize \href{mailto:\WPemail}{\WPemail}}\\[0.15cm] | ||||
| 36 | +{\small \WPaddress} | ||||
| 37 | + | ||||
| 38 | +\vspace{0.8cm} | ||||
| 39 | + | ||||
| 40 | +% --- Date & Version --- | ||||
| 41 | +{\normalsize \WPdate}\\[0.1cm] | ||||
| 42 | +{\small Version~\WPversion} | ||||
| 43 | + | ||||
| 44 | +\end{center} | ||||
| 45 | + | ||||
| 46 | +\vfill | ||||
| 47 | + | ||||
| 48 | +\newpage | ||||
| 49 | + | ||||
| 50 | +% ============================================================================ | ||||
| 51 | +% Abstract Page | ||||
| 52 | +% ============================================================================ | ||||
| 53 | +\thispagestyle{empty} | ||||
| 54 | + | ||||
| 55 | +\vspace*{1cm} | ||||
| 56 | + | ||||
| 57 | +\noindent\rule{\textwidth}{0.4pt} | ||||
| 58 | +\vspace{0.3cm} | ||||
| 59 | + | ||||
| 60 | +\noindent\textbf{Abstract} | ||||
| 61 | + | ||||
| 62 | +\vspace{0.15cm} | ||||
| 63 | + | ||||
| 64 | +\noindent\WPabstract | ||||
| 65 | + | ||||
| 66 | +\vspace{0.4cm} | ||||
| 67 | + | ||||
| 68 | +\noindent\textbf{Keywords:} \WPkeywords | ||||
| 69 | + | ||||
| 70 | +\vspace{0.15cm} | ||||
| 71 | + | ||||
| 72 | +\noindent\textbf{JEL Classification:} \WPjel | ||||
| 73 | + | ||||
| 74 | +\vspace{0.3cm} | ||||
| 75 | +\noindent\rule{\textwidth}{0.4pt} | ||||
| 76 | + | ||||
| 77 | +\newpage | ||||
added
paper/sections/titlepage_anon.tex
+53 −0
@@ -0,0 +1,53 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% ANONYMOUS TITLE PAGE — for double-anonymized journal submission | ||||
| 3 | +% Used by paper/main_anon.tex (same macros as main.tex, no author block, | ||||
| 4 | +% no institution, no logo). Abstract/keywords/JEL page identical to titlepage.tex. | ||||
| 5 | +% ============================================================================ | ||||
| 6 | +\thispagestyle{empty} | ||||
| 7 | +\begin{center} | ||||
| 8 | + | ||||
| 9 | +\vspace*{3cm} | ||||
| 10 | + | ||||
| 11 | +{\LARGE\bfseries \WPtitle\par} | ||||
| 12 | + | ||||
| 13 | +\ifx\WPsubtitle\empty\else | ||||
| 14 | + \vspace{0.3cm} | ||||
| 15 | + {\large\itshape \WPsubtitle\par} | ||||
| 16 | +\fi | ||||
| 17 | + | ||||
| 18 | +\vspace{1.5cm} | ||||
| 19 | + | ||||
| 20 | +{\normalsize [Author identity withheld for review]} | ||||
| 21 | + | ||||
| 22 | +\vspace{0.8cm} | ||||
| 23 | + | ||||
| 24 | +{\normalsize \WPdate} | ||||
| 25 | + | ||||
| 26 | +\end{center} | ||||
| 27 | + | ||||
| 28 | +\vfill | ||||
| 29 | + | ||||
| 30 | +\newpage | ||||
| 31 | +\thispagestyle{empty} | ||||
| 32 | +\vspace*{1cm} | ||||
| 33 | + | ||||
| 34 | +\noindent\rule{\textwidth}{0.4pt} | ||||
| 35 | +\vspace{0.3cm} | ||||
| 36 | + | ||||
| 37 | +\noindent\textbf{Abstract} | ||||
| 38 | +\vspace{0.15cm} | ||||
| 39 | + | ||||
| 40 | +\noindent\WPabstract | ||||
| 41 | + | ||||
| 42 | +\vspace{0.4cm} | ||||
| 43 | + | ||||
| 44 | +\noindent\textbf{Keywords:} \WPkeywords | ||||
| 45 | + | ||||
| 46 | +\vspace{0.15cm} | ||||
| 47 | + | ||||
| 48 | +\noindent\textbf{JEL Classification:} \WPjel | ||||
| 49 | + | ||||
| 50 | +\vspace{0.3cm} | ||||
| 51 | +\noindent\rule{\textwidth}{0.4pt} | ||||
| 52 | + | ||||
| 53 | +\newpage | ||||
added
paper/tables/regression.tex
+37 −0
@@ -0,0 +1,37 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% Table: Regression Results | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\begin{table}[htbp] | ||||
| 5 | + \centering | ||||
| 6 | + \begin{threeparttable} | ||||
| 7 | + \caption{Baseline Regression Results} | ||||
| 8 | + \label{tab:regression} | ||||
| 9 | + \begin{tabular}{@{}lcccc@{}} | ||||
| 10 | + \toprule | ||||
| 11 | + & (1) & (2) & (3) & (4) \\ | ||||
| 12 | + \midrule | ||||
| 13 | + $X_{i,t}$ & 0.245$^{***}$ & 0.198$^{***}$ & 0.183$^{***}$ & 0.172$^{***}$ \\ | ||||
| 14 | + & (0.042) & (0.038) & (0.035) & (0.033) \\[6pt] | ||||
| 15 | + Size & & & $-$0.032$^{**}$ & $-$0.028$^{**}$ \\ | ||||
| 16 | + & & & (0.014) & (0.013) \\[6pt] | ||||
| 17 | + Book-to-Market & & & 0.051$^{***}$ & 0.047$^{***}$ \\ | ||||
| 18 | + & & & (0.018) & (0.017) \\[6pt] | ||||
| 19 | + Leverage & & & & $-$0.089$^{**}$ \\ | ||||
| 20 | + & & & & (0.041) \\[6pt] | ||||
| 21 | + ROA & & & & 0.015$^{*}$ \\ | ||||
| 22 | + & & & & (0.008) \\[6pt] | ||||
| 23 | + \midrule | ||||
| 24 | + Firm FE & No & Yes & Yes & Yes \\ | ||||
| 25 | + Time FE & No & No & Yes & Yes \\ | ||||
| 26 | + Controls & No & No & Yes & Yes \\[3pt] | ||||
| 27 | + Observations & 125{,}400 & 125{,}400 & 125{,}400 & 125{,}400 \\ | ||||
| 28 | + $R^2$ & 0.032 & 0.148 & 0.215 & 0.228 \\ | ||||
| 29 | + Adjusted $R^2$ & 0.031 & 0.112 & 0.178 & 0.190 \\ | ||||
| 30 | + \bottomrule | ||||
| 31 | + \end{tabular} | ||||
| 32 | + \begin{tablenotes}[flushleft] | ||||
| 33 | + \footnotesize | ||||
| 34 | + \item \textit{Notes:} This table reports OLS estimates of Equation~\eqref{eq:baseline}. The dependent variable is $y_{i,t}$. $X_{i,t}$ is the main explanatory variable. Control variables include firm size, book-to-market ratio, leverage, and return on assets. Standard errors clustered at the firm level are reported in parentheses. $^{***}$, $^{**}$, and $^{*}$ denote statistical significance at the 1\%, 5\%, and 10\% levels, respectively. | ||||
| 35 | + \end{tablenotes} | ||||
| 36 | + \end{threeparttable} | ||||
| 37 | +\end{table} | ||||
added
paper/tables/summary_stats.tex
+29 −0
@@ -0,0 +1,29 @@ | |||||
| 1 | +% ============================================================================ | ||||
| 2 | +% Table: Summary Statistics | ||||
| 3 | +% ============================================================================ | ||||
| 4 | +\begin{table}[htbp] | ||||
| 5 | + \centering | ||||
| 6 | + \begin{threeparttable} | ||||
| 7 | + \caption{Summary Statistics} | ||||
| 8 | + \label{tab:summary_stats} | ||||
| 9 | + \begin{tabular}{@{}lcccccc@{}} | ||||
| 10 | + \toprule | ||||
| 11 | + Variable & $N$ & Mean & Std.\ Dev. & $p_{25}$ & Median & $p_{75}$ \\ | ||||
| 12 | + \midrule | ||||
| 13 | + \multicolumn{7}{@{}l}{\textit{Panel A: Dependent Variables}} \\[3pt] | ||||
| 14 | + $r_{i,t}$ (\%) & 125{,}400 & 0.82 & 4.35 & $-$1.92 & 0.65 & 3.48 \\ | ||||
| 15 | + $\sigma_{i,t}$ (\%) & 125{,}400 & 2.14 & 1.87 & 0.98 & 1.65 & 2.78 \\[6pt] | ||||
| 16 | + \multicolumn{7}{@{}l}{\textit{Panel B: Explanatory Variables}} \\[3pt] | ||||
| 17 | + $X_{i,t}$ & 125{,}400 & 0.45 & 0.32 & 0.21 & 0.40 & 0.65 \\ | ||||
| 18 | + Size (log) & 125{,}400 & 7.23 & 1.85 & 5.92 & 7.15 & 8.47 \\ | ||||
| 19 | + Book-to-Market & 125{,}400 & 0.68 & 0.54 & 0.30 & 0.56 & 0.91 \\ | ||||
| 20 | + Leverage & 125{,}400 & 0.34 & 0.21 & 0.17 & 0.32 & 0.48 \\ | ||||
| 21 | + ROA (\%) & 125{,}400 & 3.15 & 8.42 & 0.52 & 3.28 & 6.74 \\ | ||||
| 22 | + \bottomrule | ||||
| 23 | + \end{tabular} | ||||
| 24 | + \begin{tablenotes}[flushleft] | ||||
| 25 | + \footnotesize | ||||
| 26 | + \item \textit{Notes:} This table reports summary statistics for the main variables used in the analysis. The sample covers the period January~1990 to December~2023. $r_{i,t}$ is the monthly return of firm~$i$. $\sigma_{i,t}$ is the realized volatility computed from daily returns within the month. $X_{i,t}$ is the main explanatory variable. Size is the natural logarithm of market capitalization. Book-to-Market is the ratio of book equity to market equity. Leverage is total debt over total assets. ROA is return on assets. All continuous variables are winsorized at the 1st and 99th percentiles. | ||||
| 27 | + \end{tablenotes} | ||||
| 28 | + \end{threeparttable} | ||||
| 29 | +\end{table} | ||||
added
paper/uq_logo.jpg
+0 −0
Binary file not shown.
added
pyproject.toml
+34 −0
@@ -0,0 +1,34 @@ | |||||
| 1 | +[project] | ||||
| 2 | +name = "wp38-uqo" | ||||
| 3 | +version = "0.1.0" | ||||
| 4 | +description = "WP38 — The Economic Geography of Digital Production (Quebec online assortments, Fabri-Ka): reproducible research pipeline" | ||||
| 5 | +requires-python = ">=3.12,<3.13" | ||||
| 6 | +dependencies = [ | ||||
| 7 | + "pandas>=2.2,<3", | ||||
| 8 | + "numpy>=1.26,<3", | ||||
| 9 | + "scipy>=1.13", | ||||
| 10 | + "statsmodels>=0.14", | ||||
| 11 | + "pyfixest>=0.25", | ||||
| 12 | + "scikit-learn>=1.5", | ||||
| 13 | + "networkx>=3.3", | ||||
| 14 | + "python-louvain>=0.16", | ||||
| 15 | + "matplotlib>=3.9", | ||||
| 16 | + "geopandas>=1.0", | ||||
| 17 | + "shapely>=2.0", | ||||
| 18 | + "pyproj>=3.6", | ||||
| 19 | + "duckdb>=1.0", | ||||
| 20 | + "pyyaml>=6.0", | ||||
| 21 | + "pytest>=8.0", | ||||
| 22 | + "requests>=2.32", | ||||
| 23 | + "rapidfuzz>=3.9", | ||||
| 24 | + "openai>=1.50", | ||||
| 25 | + "anthropic>=0.40", | ||||
| 26 | + "tqdm>=4.66", | ||||
| 27 | + "pyarrow>=16", | ||||
| 28 | + "python-dotenv>=1.0", | ||||
| 29 | + "bibtexparser>=1.4,<2", | ||||
| 30 | +] | ||||
| 31 | +[tool.setuptools.packages.find] | ||||
| 32 | +include = ["src*"] | ||||
| 33 | +[tool.pytest.ini_options] | ||||
| 34 | +testpaths = ["tests"] | ||||
added
reports/00_source_audit.md
+99 −0
@@ -0,0 +1,99 @@ | |||||
| 1 | +# Phase 0 — Environment, model and source audit (WP38) | ||||
| 2 | + | ||||
| 3 | +*Written 2026-11-01. All figures below were measured on the authorised snapshot or on the production node with read-only queries; nothing was modified in production.* | ||||
| 4 | + | ||||
| 5 | +## 0.1 Environment | ||||
| 6 | + | ||||
| 7 | +| Item | Value | | ||||
| 8 | +|---|---| | ||||
| 9 | +| Working directory | `~/Desktop/UQO/Recherche/Recherche-UQO/economie/economic-geography-digital-production` (git, local `main`; remote to be created on spbgit as `wp38_uqo.git`) | | ||||
| 10 | +| Laptop | Apple Silicon, 18 cores, 48 GB RAM, 1.0 TB free; macOS 27 | | ||||
| 11 | +| Cluster | MacLustr (29 Macs, 401 cores) reachable over SSH; only M4M64a (Fabri-Ka host) was used in Phase 0 | | ||||
| 12 | +| Python | `uv` venv `.venv`, Python 3.12, pinned via `pyproject.toml` (pandas, pyfixest, statsmodels, networkx, geopandas, duckdb, rapidfuzz, …) | | ||||
| 13 | +| LaTeX | TeX Live (`latexmk`, `pdflatex`), `pandoc` | | ||||
| 14 | +| Network | Outbound HTTPS allowed. Crossref, Statistics Canada WDS, ISQ and Données Québec are reachable | | ||||
| 15 | +| API keys | `.env` (git-ignored) holds one OpenAI key and one Anthropic key inherited from WP37; never printed | | ||||
| 16 | + | ||||
| 17 | +### 0.1.1 Model inventory (official provider endpoints, tiny test calls) | ||||
| 18 | + | ||||
| 19 | +See `reports/model_inventory.md` / `logs/model_inventory.json` (checked 2026-11-01T17:42Z). OpenAI `GET /v1/models` lists 140 IDs; `gpt-5.5`, `gpt-5` and `gpt-5-mini` answered 200 (8-token budget fully consumed by reasoning, so empty text — expected for reasoning models with a tiny budget); `gpt-5.1` returned 400 ("could not finish the message" under the 8-token budget). Anthropic lists 14 IDs; `claude-fable-5-1`, `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5` all answered "OK" in about 1 s. Total cost of the inventory: below 0.002 USD. LLMs will be used only for (a) second annotation of a product-matching validation sample and (b) optional category-reclassification audit; every call will be logged in `logs/run_ledger.jsonl` with its cost. No empirical result depends on an LLM. | ||||
| 20 | + | ||||
| 21 | +## 0.2 Source identification: Fabri-Ka | ||||
| 22 | + | ||||
| 23 | +Fabri-Ka (www.fabri-ka.com) is an aggregator built and operated by the author (Groupe Ka). It **does not sell**: it discovers Quebec online stores from certification registries, sector associations, regional agri-food brands and marketplaces (`deliverables/research_report.md`), verifies each domain, classifies the *store* by origin class A–E with retained textual evidence, and then syncs each store's **public catalogue endpoint** (Shopify `/products.json`, WooCommerce Store API, Wix GraphQL, Squarespace `?format=json`, Square, Votresite, generic JSON-LD) roughly every 6 hours (PM2 process `fabri-ka-sync`). Compliance per source is documented in `docs/CONFORMITE.md` (reviewed 2026-08-19/21): public endpoints only, nothing behind authentication, polite rates, removal on request. | ||||
| 24 | + | ||||
| 25 | +### 0.2.1 Access and authorisation | ||||
| 26 | + | ||||
| 27 | +- **Authorised access:** the author owns the platform and the database. The research copy is a first-party export; no scraping of fabri-ka.com and no use of its `/api/` (which `robots.txt` disallows for crawlers) beyond **one** control request to `/api/stats` on 2026-11-01T17:37Z to date-stamp the public counters (products 390 108, stores_live 1 569, stores_registry 4 082, regions 17). The mandate's "approximately 390 456 products, 1 572 stores" was therefore an interface figure from a slightly earlier moment; the counts drift by a few hundred per 6-hour cycle. | ||||
| 28 | +- **Snapshot:** `sqlite3.Connection.backup()` of `M4M64a:~/fabri-ka/data/fabrika.db` on **2026-11-01T17:38:30Z**, application commit `689c7bb1…`; tables `users` (2 rows) and `inscriptions` (1 row) — the only personal data — and the derived FTS index were dropped on the node before transfer. SHA-256 `8d963ba9…98fb`, 1.24 GB, stored in `data/raw/` (git-ignored). The discovery registry `stores.json` and `collections_taxonomy.json` were copied with checksums (`data/raw/README.md`). | ||||
| 29 | +- **Production untouched:** all queries used `mode=ro`; the WAL file was not modified. | ||||
| 30 | + | ||||
| 31 | +### 0.2.2 Schema (three tables kept) | ||||
| 32 | + | ||||
| 33 | +| table | rows | key fields | | ||||
| 34 | +|---|---|---| | ||||
| 35 | +| `stores` | 4 082 (1 569 enabled with ≥ 1 published product; 132 enabled with 0; 2 381 disabled = directory-only or dead) | `id` (canonical domain), `name`, `platform`, `city`, `region` (17 canonical names or blank), `origin_class` A/C/E, `origin_confidence`, `origin_evidence` (text), `categories` (JSON), `discovery_sources` (JSON), `language`, `postal_prefix` (RTA/FSA), `lat`,`lng` (FSA centroid via zippopotam/GeoNames, precision "fsa"), `store_kind` (revendeur/collectif/blank), `certifications` (JSON: Aliments du Québec, Les Produits du Québec, CARTV bio…), `product_count`, `fail_streak`, `presumed_closed`, `shipping_info` | | ||||
| 36 | +| `products` | 465 388 (390 108 `active=1 ∧ listing_status='published'`) | `uid` (20-hex hash of store+external id), `store_id`, `external_id`, `url`, `title`, `description`, `price` (min variant), `price_max`, `compare_at_price`, `currency`, `images` (JSON), `category` (20 canonical keys, inferred by keyword rules `fabrika/schema.py::infer_category` from product type, tags, title and option names), `product_type` (merchant's own), `tags` (JSON), `vendor` (merchant's brand field), `available`, `content_hash`, `first_seen`, `last_seen`, `active`, `miss_count`, `details` (JSON: variants with price/sku/grams/available, options, attributes, categories), `listing_status` (published / excluded:{carte_cadeau, atelier_cours, abonnement, billet, test} / quarantine:{prix_hors_bornes, titre_vide}), `price_on_request` | | ||||
| 37 | +| `sync_log` | 577 773 (ok 572 749, error 4 972, presumed_closed 52) | one row per store per sync: `ts`, `store_id`, `found`, `added`, `updated`, `removed`, `status`, `message` | | ||||
| 38 | + | ||||
| 39 | +**There is no price-history table.** The database upserts by `content_hash` and keeps only the current price per listing; `sync_log` records counts, not prices. Consequently every price analysis in WP38 is **cross-sectional at the snapshot date**; temporal analysis is limited to listing entry/exit (`first_seen`/`last_seen`) and store-level sync counts. | ||||
| 40 | + | ||||
| 41 | +### 0.2.3 Temporal coverage | ||||
| 42 | + | ||||
| 43 | +- `first_seen` runs 2026-08-12 → 2026-11-01 (81 days). 291 125 listings carry `first_seen` = 2026-08-12 (initial load) and a further 48 820 + 30 173 on 2026-08-19/23 (expansion waves); 1 266 stores were onboarded in ISO week 32 and 328 in week 33; only 15 stores were first observed later. Hence **store onboarding ended by 2026-08-24**, and product-level entry after that date reflects merchant catalogue changes (new listings, connector fixes) rather than platform expansion — this is the only usable "dynamic" margin and it must be audited connector by connector before any H4 statement. | ||||
| 44 | +- Sync cadence: median 6.3 h between successive syncs of a store (p10 1.2 h, p90 8.8 h; 200-store sample, last 30 days). A listing becomes `active=0` after 2 consecutive misses (`MISS_GRACE = 2`, ≈ 12 h). 73 618 published listings are inactive at the snapshot (last seen Aug 6 970, Sep 31 642, Oct 35 222). A disappearance is **not** a sale (sold-out products usually stay listed with `available=0`: 48 997 active listings). | ||||
| 45 | + | ||||
| 46 | +### 0.2.4 Field-level quality and missingness (active published listings, N = 390 108) | ||||
| 47 | + | ||||
| 48 | +| issue | measurement | | ||||
| 49 | +|---|---| | ||||
| 50 | +| Price missing | 14 786 (3.8 %) `price IS NULL` (all flagged `price_on_request`); 31 quarantined `prix_hors_bornes` (> 100 000 CAD) excluded upstream | | ||||
| 51 | +| Currency | CAD 389 378; USD 578 (8 stores); EUR 112; GBP 40 — non-CAD stores to be excluded from price analyses (12 stores) | | ||||
| 52 | +| Price distribution | p1 1.32, p25 12.95, median 25.00, p75 69.00, p95 766, p99 3 745 CAD; max 95 999.99 | | ||||
| 53 | +| Variants | `price_max > price` for 57 728 listings (14.8 %) — the listing price is the **minimum variant price**; `details.variants` carries per-variant prices for Shopify/WooCommerce | | ||||
| 54 | +| Compare-at (strike-through) price | 33 311 listings (8.5 %) have `compare_at_price > price` (on-sale indicator, merchant-declared) | | ||||
| 55 | +| Availability | available = 1: 336 038; = 0: 48 997; NULL: 5 073 | | ||||
| 56 | +| Category | 20 keys; `autre` = 46 094 (11.8 %); rule-based inference, no manual validation yet → WP38 will audit a stratified sample and report category precision | | ||||
| 57 | +| Brand / vendor | `vendor` non-empty for 290 827 (74.5 %); it is the merchant's own brand field (often the store name) | | ||||
| 58 | +| Product type / tags / description / images | non-empty for 305 860 / 261 421 / 339 265 / 360 508 | | ||||
| 59 | +| SKU / GTIN | SKU present inside `details` for Shopify/Woo variants; **no GTIN/UPC field** → cross-merchant matching must rely on vendor + normalised title (+ SKU where present) | | ||||
| 60 | +| Within-store duplicate titles | 7 411 (store, title) pairs with > 1 listing (variants listed as separate products, colour/format) | | ||||
| 61 | +| Cross-store identical titles (len > 15) | 2 595 distinct titles covering 5 961 listings — first candidate pool for H5 | | ||||
| 62 | +| `external_id` collisions across stores | 15 033 — platform-local integer IDs, **not** product identity (ignored) | | ||||
| 63 | + | ||||
| 64 | +### 0.2.5 Merchant-level quality | ||||
| 65 | + | ||||
| 66 | +| issue | measurement | | ||||
| 67 | +|---|---| | ||||
| 68 | +| Region | **346 of 1 569 live stores (22 %) have a blank region, carrying 159 096 listings (41 %)**, including the four largest catalogues (qublivre.ca 24 946 books; ici-la.co 21 412 souvenirs; remorquetrailer.com 19 482; beteaunaturel.com 9 910). Of these 346, 117 have an FSA centroid (`lat/lng`) → region recoverable by point-in-polygon against the official administrative-region layer; 229 have no geographic field at all → to be resolved from `stores.json` (`qc_postal`, `city` mentions) or left as "unknown region" and excluded from regional analyses (sensitivity: included as an 18th pseudo-region) | | ||||
| 69 | +| Region provenance | assigned by (1) regional directory source (certain), (2) regions mentioned on the site, (3) FSA → region map; coordinates = FSA centroid (neighbourhood precision), **never the civic address** | | ||||
| 70 | +| Origin class | A 1 526 stores (322 007 listings), C 12 (63 885), E 31 (4 216); B and D unused. Class is a **store-level prior from the discovery source** (e.g. PPAQ maple producer = A 0.95; Les Produits du Québec retailer = C 0.75) adjusted by site signals; `origin_evidence` text retained. Many A entries read "aucun signal de localisation québécoise détecté sur le site (à vérifier)". It is **not** product-level manufacturing provenance | | ||||
| 71 | +| Certifications | 718 live stores carry at least one structured certification (Aliments du Québec, Les Produits du Québec, CARTV organic, …) — third-party **store/enterprise** certification, usable as a store-level provenance indicator with its own caveats | | ||||
| 72 | +| Platform | shopify 696 (273 504 listings), woocommerce 498 (91 100), wix 244 (8 798), votresite 42, square 36, squarespace 23, generic 20, lightspeed 5, others ≤ 2 | | ||||
| 73 | +| Catalogue size | median 36 listings per store, p90 324, p99 3 997; top-10 stores hold 139 735 listings (36 %) | | ||||
| 74 | +| Store kind | revendeur 23, collectif 3 (marketplaces such as epipresto.ca), hors_mission 1, blank 1 542 | | ||||
| 75 | +| Sync health | 26 stores with an error status in the last 7 days; `stores.product_count` equals the live published count for all 1 569 stores (consistency check passed) | | ||||
| 76 | + | ||||
| 77 | +### 0.2.6 Known selection mechanisms (from the platform's own documentation) | ||||
| 78 | + | ||||
| 79 | +Discovery favours certified, association-member and search-indexed businesses; under-represents CMAQ artisans, industrial manufacturers selling direct, Instagram/Facebook-only micro-shops, Nord-du-Québec, Etsy sellers (excluded by Etsy ToS), ASC farms; Wix stores were only connected in a later wave; Ecwid storefronts cannot be connected; Montréal was deliberately topped-up via a dedicated source (`acheterquebecois_mtl`, `modemtl`). Connector caps (`max_pages` 200) truncate the very largest catalogues. These mechanisms are region- and category-correlated and are central to the representativeness audit (Phase 5). | ||||
| 80 | + | ||||
| 81 | +## 0.3 Feasibility verdict by hypothesis | ||||
| 82 | + | ||||
| 83 | +| hypothesis | feasible with this source? | conditions | | ||||
| 84 | +|---|---|---| | ||||
| 85 | +| H1 regional specialization (RAA) | **Yes** | after region recovery; merchant-weighted and largest-merchant-excluded variants mandatory | | ||||
| 86 | +| H2 diversity vs regional scale | **Yes** (n = 17 regions → low power; report as descriptive association with bootstrap CIs) | external population/business counts from ISQ/StatCan | | ||||
| 87 | +| H3 concentration / long tail | **Yes** | rank-size of merchant catalogues, listing shares | | ||||
| 88 | +| H4 related diversification (dynamic) | **Partially / exploratory only** | no store onboarding after week 33; only within-store listing entry over ~10 weeks; no cross-snapshot category entry at region level beyond a handful of events → mark as exploratory, likely inconclusive | | ||||
| 89 | +| H5 price dispersion of matched products | **Yes, cross-sectional only** | no price history; matched products via vendor + title + variant; merchant/region collinearity: one merchant = one region → region effect identified only across merchants | | ||||
| 90 | +| H6 local-origin premium | **Not testable at product level** (no product provenance) | store-level certification contrast reported as a descriptive, clearly-labelled proxy, not as H6 | | ||||
| 91 | +| H7 digital-assortment complexity | **Yes** (17 × 20 matrix; small) | null models and merchant-preserving permutations required; eigenvector interpretation guarded | | ||||
| 92 | + | ||||
| 93 | +## 0.4 Blockers and decisions carried forward | ||||
| 94 | + | ||||
| 95 | +1. No price history → temporal price analysis blocked (recorded in `reports/limitations.md`). A prospective collection plan is written but not executed. | ||||
| 96 | +2. Region unknown for 22 % of live stores → Phase 2 region-recovery procedure with quality flags; all regional results reported with and without recovered stores. | ||||
| 97 | +3. Origin class is store-level → wording throughout: "online assortment of Quebec-based merchants", never "Quebec production". | ||||
| 98 | +4. Category labels are rule-based → stratified audit (manual + LLM second annotation, logged cost) to estimate confusion rates and propagate uncertainty. | ||||
| 99 | +5. Public counters vs cleaned sample: 390 108 published active listings at the snapshot; the research sample will be smaller after exclusions (non-CAD, missing price, unknown region, duplicates) and the full attrition is reported in `reports/sample_flow.md`. | ||||
added
reports/model_inventory.md
+27 −0
@@ -0,0 +1,27 @@ | |||||
| 1 | +# Model inventory (Phase 0) — checked 2026-11-01T17:42:21Z | ||||
| 2 | + | ||||
| 3 | +Tiny test requests only (max 8 output tokens). Keys read from `.env`, never printed. | ||||
| 4 | + | ||||
| 5 | +## openai | ||||
| 6 | +- `GET /v1/models` status: 200 — 140 model IDs listed | ||||
| 7 | +- IDs: `babbage-002`, `chat-latest`, `chatgpt-image-latest`, `davinci-002`, `gpt-3.5-turbo`, `gpt-3.5-turbo-0125`, `gpt-3.5-turbo-1106`, `gpt-3.5-turbo-16k`, `gpt-3.5-turbo-instruct`, `gpt-3.5-turbo-instruct-0914`, `gpt-4`, `gpt-4-0613`, `gpt-4-turbo`, `gpt-4-turbo-2024-04-09`, `gpt-4.1`, `gpt-4.1-2025-04-14`, `gpt-4.1-mini`, `gpt-4.1-mini-2025-04-14`, `gpt-4.1-nano`, `gpt-4.1-nano-2025-04-14`, `gpt-4o`, `gpt-4o-2024-05-13`, `gpt-4o-2024-08-06`, `gpt-4o-2024-11-20`, `gpt-4o-mini`, `gpt-4o-mini-2024-07-18`, `gpt-4o-mini-search-preview`, `gpt-4o-mini-search-preview-2025-03-11`, `gpt-4o-mini-transcribe`, `gpt-4o-mini-transcribe-2025-03-20`, `gpt-4o-mini-transcribe-2025-12-15`, `gpt-4o-mini-tts`, `gpt-4o-mini-tts-2025-03-20`, `gpt-4o-mini-tts-2025-12-15`, `gpt-4o-search-preview`, `gpt-4o-search-preview-2025-03-11`, `gpt-4o-transcribe`, `gpt-4o-transcribe-diarize`, `gpt-5`, `gpt-5-2025-08-07`, `gpt-5-chat-latest`, `gpt-5-codex`, `gpt-5-mini`, `gpt-5-mini-2025-08-07`, `gpt-5-nano`, `gpt-5-nano-2025-08-07`, `gpt-5-pro`, `gpt-5-pro-2025-10-06`, `gpt-5-search-api`, `gpt-5-search-api-2025-10-14`, `gpt-5.1`, `gpt-5.1-2025-11-13`, `gpt-5.1-chat-latest`, `gpt-5.1-codex`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`, `gpt-5.2`, `gpt-5.2-2025-12-11`, `gpt-5.2-chat-latest`, `gpt-5.2-codex`, `gpt-5.2-pro`, `gpt-5.2-pro-2025-12-11`, `gpt-5.3-chat-latest`, `gpt-5.3-codex`, `gpt-5.4`, `gpt-5.4-2026-03-05`, `gpt-5.4-mini`, `gpt-5.4-mini-2026-03-17`, `gpt-5.4-nano`, `gpt-5.4-nano-2026-03-17`, `gpt-5.4-pro`, `gpt-5.4-pro-2026-03-05`, `gpt-5.5`, `gpt-5.5-2026-04-23`, `gpt-5.5-pro`, `gpt-5.5-pro-2026-04-23`, `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-6-astra`, `gpt-6-luna`, `gpt-6-sol`, `gpt-6.1-sol`, `gpt-6.1-terra`, `gpt-audio`, `gpt-audio-1.5`, `gpt-audio-2025-08-28`, `gpt-audio-mini`, `gpt-audio-mini-2025-10-06`, `gpt-audio-mini-2025-12-15`, `gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-flare`, `gpt-image-2.5-flare-2026-09-08`, `gpt-image-2.5-sunburst`, `gpt-image-2.5-sunburst-2026-09-08`, `gpt-live-1`, `gpt-live-transcribe`, `gpt-realtime`, `gpt-realtime-1.5`, `gpt-realtime-2`, `gpt-realtime-2.1`, `gpt-realtime-2.1-mini`, `gpt-realtime-2025-08-28`, `gpt-realtime-mini`, `gpt-realtime-mini-2025-12-15`, `gpt-realtime-translate`, `gpt-realtime-whisper`, `gpt-transcribe`, `o1`, `o1-2024-12-17`, `o1-pro`, `o1-pro-2025-03-19`, `o3`, `o3-2025-04-16`, `o3-deep-research`, `o3-deep-research-2025-06-26`, `o3-mini`, `o3-mini-2025-01-31`, `o3-pro`, `o3-pro-2025-06-10`, `o4-mini`, `o4-mini-2025-04-16`, `o4-mini-deep-research`, `o4-mini-deep-research-2025-06-26`, `omni-moderation-2024-09-26`, `omni-moderation-latest`, `sora-2`, `sora-2-pro`, `text-embedding-3-large`, `text-embedding-3-small`, `text-embedding-ada-002`, `tts-1`, `tts-1-1106`, `tts-1-hd`, `tts-1-hd-1106`, `whisper-1` | ||||
| 8 | + | ||||
| 9 | +| model | status | latency (s) | usage | approx. cost (USD) | reply | | ||||
| 10 | +|---|---|---|---|---|---| | ||||
| 11 | +| `gpt-5.5` | 200 | 1.79 | {"prompt_tokens": 13, "completion_tokens": 8, "total_tokens": 21, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "completion_tokens_details": {"reasoning_tokens": 8, "audio_tokens": 0, "accepted_prediction_tokens": 0, "rejected_prediction_tokens": 0}} | — | | | ||||
| 12 | +| `gpt-5.1` | 400 | 0.76 | {} | — | { | ||||
| 13 | + "error": { | ||||
| 14 | + "message": "Could not finish the message | | ||||
| 15 | +| `gpt-5` | 200 | 0.78 | {"prompt_tokens": 13, "completion_tokens": 8, "total_tokens": 21, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "completion_tokens_details": {"reasoning_tokens": 8, "audio_tokens": 0, "accepted_prediction_tokens": 0, "rejected_prediction_tokens": 0}} | — | | | ||||
| 16 | +| `gpt-5-mini` | 200 | 0.78 | {"prompt_tokens": 13, "completion_tokens": 8, "total_tokens": 21, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "completion_tokens_details": {"reasoning_tokens": 8, "audio_tokens": 0, "accepted_prediction_tokens": 0, "rejected_prediction_tokens": 0}} | — | | | ||||
| 17 | + | ||||
| 18 | +## anthropic | ||||
| 19 | +- `GET /v1/models` status: 200 — 14 model IDs listed | ||||
| 20 | +- IDs: `claude-fable-5`, `claude-fable-5-1`, `claude-haiku-4-5-20251001`, `claude-haiku-5-5`, `claude-opus-4-5-20251101`, `claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, `claude-opus-5-5`, `claude-sonnet-4-5-20250929`, `claude-sonnet-4-6`, `claude-sonnet-5`, `claude-sonnet-5-5` | ||||
| 21 | + | ||||
| 22 | +| model | status | latency (s) | usage | approx. cost (USD) | reply | | ||||
| 23 | +|---|---|---|---|---|---| | ||||
| 24 | +| `claude-fable-5-1` | 200 | 0.98 | {"input_tokens": 18, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "output_tokens": 4, "output_tokens_details": {"thinking_tokens": 0}, "service_tier": "standard", "inference_geo": "global", "speed": "standard"} | 0.00095 | OK | | ||||
| 25 | +| `claude-opus-5-5` | 200 | 1.03 | {"input_tokens": 18, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "output_tokens": 4, "output_tokens_details": {"thinking_tokens": 0}, "service_tier": "standard", "inference_geo": "global", "speed": "standard"} | 0.00019 | OK | | ||||
| 26 | +| `claude-sonnet-5-5` | 200 | 1.09 | {"input_tokens": 18, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "output_tokens": 4, "output_tokens_details": {"thinking_tokens": 0}, "service_tier": "standard", "inference_geo": "global", "speed": "standard"} | 0.000114 | OK | | ||||
| 27 | +| `claude-haiku-5-5` | 200 | 0.71 | {"input_tokens": 18, "cache_creation_input_tokens": 0, "cache_read_input_tokens": 0, "cache_creation": {"ephemeral_5m_input_tokens": 0, "ephemeral_1h_input_tokens": 0}, "output_tokens": 4, "output_tokens_details": {"thinking_tokens": 0}, "service_tier": "standard", "inference_geo": "global", "speed": "standard"} | 3.8e-05 | OK | | ||||
added
research/decisions.md
+10 −0
@@ -0,0 +1,10 @@ | |||||
| 1 | +# Decision log — WP38 | ||||
| 2 | + | ||||
| 3 | +| id | date | decision | rationale | | ||||
| 4 | +|---|---|---|---| | ||||
| 5 | +| D-001 | 2026-11-01 | Data = owner-authorised read-only `.backup` of `fabrika.db` (2026-11-01T17:38:30Z); personal tables dropped on the node; no scraping, one control request to the public `/api/stats` | mandate rules 3–4; `robots.txt` disallows `/api/` for crawlers | | ||||
| 6 | +| D-002 | 2026-11-01 | Unit of analysis = **published active listing** of an enabled store at the snapshot; variants collapsed to the listing (min price), with variant counts kept as a covariate | the platform's own publication rule; variants are not separate products | | ||||
| 7 | +| D-003 | 2026-11-01 | Region recovery: official MERN administrative-region polygons + FSA centroid point-in-polygon for stores with coordinates; registry postal/city fields otherwise; flags `region_source ∈ {directory, site, fsa_map, pip_centroid, registry_postal, unknown}` | 22 % of live stores lack a region; results reported with/without recovered stores | | ||||
| 8 | +| D-004 | 2026-11-01 | H6 declared **untestable** at product level; a store-certification contrast is reported as a labelled proxy only | no product-level provenance in the source (mandate H6 clause) | | ||||
| 9 | +| D-005 | 2026-11-01 | All price analyses are cross-sectional at the snapshot; H4 exploratory only | no price history table; store onboarding ended 2026-08-24 | | ||||
| 10 | +| D-006 | 2026-11-01 | Seed 20261101 for every bootstrap/permutation; outputs hashed in `logs/manifest.json` | reproducibility | | ||||
added
src/__init__.py
+0 −0
added
src/audit/__init__.py
+0 −0
added
src/audit/model_inventory.py
+83 −0
@@ -0,0 +1,83 @@ | |||||
| 1 | +"""Phase 0 — inventory of OpenAI and Anthropic model IDs actually reachable with the project's keys. | ||||
| 2 | + | ||||
| 3 | +Stdlib only (urllib) so it runs before the venv exists. Keys are read from .env and never printed. | ||||
| 4 | +One `GET /v1/models` per provider, then ONE tiny completion per selected model (max 8 output tokens). | ||||
| 5 | +Writes logs/model_inventory.json and reports/model_inventory.md. Costs are computed from the token usage | ||||
| 6 | +returned by the provider and the public list prices hard-coded below (checked 2026-11-01; see claude-api skill). | ||||
| 7 | +""" | ||||
| 8 | +from __future__ import annotations | ||||
| 9 | +import json, os, time, urllib.request, urllib.error, sys, pathlib | ||||
| 10 | + | ||||
| 11 | +ROOT = pathlib.Path(__file__).resolve().parents[2] | ||||
| 12 | +env = {} | ||||
| 13 | +for line in (ROOT / ".env").read_text().splitlines(): | ||||
| 14 | + if "=" in line and not line.startswith("#"): | ||||
| 15 | + k, v = line.split("=", 1); env[k.strip()] = v.strip() | ||||
| 16 | +OPENAI = env.get("OPENAI_API_KEY", ""); ANTHROPIC = env.get("ANTHROPIC_API_KEY", "") | ||||
| 17 | + | ||||
| 18 | +# USD per 1M tokens (input, output) — public list prices as of 2026-11-01 (verify before relying on them) | ||||
| 19 | +PRICES = { | ||||
| 20 | + "claude-fable-5-1": (25.0, 125.0), "claude-opus-5-5": (5.0, 25.0), "claude-sonnet-5-5": (3.0, 15.0), "claude-haiku-5-5": (1.0, 5.0), | ||||
| 21 | +} | ||||
| 22 | + | ||||
| 23 | +def call(url, headers, body=None, timeout=60): | ||||
| 24 | + req = urllib.request.Request(url, data=json.dumps(body).encode() if body else None, headers=headers, method="POST" if body else "GET") | ||||
| 25 | + t0 = time.time() | ||||
| 26 | + try: | ||||
| 27 | + with urllib.request.urlopen(req, timeout=timeout) as r: | ||||
| 28 | + return r.status, json.loads(r.read().decode()), round(time.time() - t0, 2) | ||||
| 29 | + except urllib.error.HTTPError as e: | ||||
| 30 | + return e.code, {"error": e.read().decode()[:300]}, round(time.time() - t0, 2) | ||||
| 31 | + except Exception as e: # noqa: BLE001 | ||||
| 32 | + return -1, {"error": str(e)[:300]}, round(time.time() - t0, 2) | ||||
| 33 | + | ||||
| 34 | +out = {"checked_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "openai": {}, "anthropic": {}} | ||||
| 35 | + | ||||
| 36 | +# ---- OpenAI -------------------------------------------------------------- | ||||
| 37 | +if OPENAI: | ||||
| 38 | + st, body, lat = call("https://api.openai.com/v1/models", {"Authorization": f"Bearer {OPENAI}"}) | ||||
| 39 | + ids = sorted(m["id"] for m in body.get("data", [])) if st == 200 else [] | ||||
| 40 | + out["openai"]["list_status"] = st; out["openai"]["n_models"] = len(ids); out["openai"]["model_ids"] = ids | ||||
| 41 | + tests = {} | ||||
| 42 | + for mid in [m for m in ("gpt-5.5", "gpt-5.1", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-4.1", "gpt-4.1-mini", "gpt-4o-mini") if m in ids][:4]: | ||||
| 43 | + st, b, lat = call("https://api.openai.com/v1/chat/completions", {"Authorization": f"Bearer {OPENAI}", "Content-Type": "application/json"}, | ||||
| 44 | + {"model": mid, "messages": [{"role": "user", "content": "Reply with the single word OK."}], "max_completion_tokens": 8}) | ||||
| 45 | + u = b.get("usage", {}) | ||||
| 46 | + tests[mid] = {"status": st, "latency_s": lat, "usage": u, "reply": (b.get("choices") or [{}])[0].get("message", {}).get("content") if st == 200 else b.get("error")} | ||||
| 47 | + out["openai"]["tests"] = tests | ||||
| 48 | +else: | ||||
| 49 | + out["openai"]["list_status"] = "no key" | ||||
| 50 | + | ||||
| 51 | +# ---- Anthropic ----------------------------------------------------------- | ||||
| 52 | +if ANTHROPIC: | ||||
| 53 | + H = {"x-api-key": ANTHROPIC, "anthropic-version": "2023-06-01", "Content-Type": "application/json"} | ||||
| 54 | + st, body, lat = call("https://api.anthropic.com/v1/models?limit=100", H) | ||||
| 55 | + ids = sorted(m["id"] for m in body.get("data", [])) if st == 200 else [] | ||||
| 56 | + out["anthropic"]["list_status"] = st; out["anthropic"]["n_models"] = len(ids); out["anthropic"]["model_ids"] = ids | ||||
| 57 | + if st != 200: out["anthropic"]["list_error"] = body | ||||
| 58 | + tests = {} | ||||
| 59 | + for mid in [m for m in ("claude-fable-5-1", "claude-opus-5-5", "claude-sonnet-5-5", "claude-haiku-5-5") if m in ids]: | ||||
| 60 | + st, b, lat = call("https://api.anthropic.com/v1/messages", H, {"model": mid, "max_tokens": 8, "messages": [{"role": "user", "content": "Reply with the single word OK."}]}) | ||||
| 61 | + u = b.get("usage", {}) | ||||
| 62 | + cost = None | ||||
| 63 | + if mid in PRICES and u: | ||||
| 64 | + cost = round(u.get("input_tokens", 0) * PRICES[mid][0] / 1e6 + u.get("output_tokens", 0) * PRICES[mid][1] / 1e6, 6) | ||||
| 65 | + tests[mid] = {"status": st, "latency_s": lat, "usage": u, "approx_cost_usd": cost, "reply": (b.get("content") or [{}])[0].get("text") if st == 200 else b.get("error")} | ||||
| 66 | + out["anthropic"]["tests"] = tests | ||||
| 67 | +else: | ||||
| 68 | + out["anthropic"]["list_status"] = "no key" | ||||
| 69 | + | ||||
| 70 | +(ROOT / "logs").mkdir(exist_ok=True) | ||||
| 71 | +(ROOT / "logs" / "model_inventory.json").write_text(json.dumps(out, indent=1, ensure_ascii=False)) | ||||
| 72 | +lines = [f"# Model inventory (Phase 0) — checked {out['checked_utc']}", "", | ||||
| 73 | + "Tiny test requests only (max 8 output tokens). Keys read from `.env`, never printed.", ""] | ||||
| 74 | +for prov in ("openai", "anthropic"): | ||||
| 75 | + d = out[prov]; lines.append(f"## {prov}"); lines.append(f"- `GET /v1/models` status: {d.get('list_status')} — {d.get('n_models', 0)} model IDs listed") | ||||
| 76 | + if d.get("model_ids"): lines.append("- IDs: " + ", ".join(f"`{m}`" for m in d["model_ids"])) | ||||
| 77 | + if d.get("tests"): | ||||
| 78 | + lines += ["", "| model | status | latency (s) | usage | approx. cost (USD) | reply |", "|---|---|---|---|---|---|"] | ||||
| 79 | + for m, t in d["tests"].items(): | ||||
| 80 | + lines.append(f"| `{m}` | {t['status']} | {t['latency_s']} | {json.dumps(t['usage'])} | {t.get('approx_cost_usd', '—')} | {str(t['reply'])[:60]} |") | ||||
| 81 | + lines.append("") | ||||
| 82 | +(ROOT / "reports" / "model_inventory.md").write_text("\n".join(lines)) | ||||
| 83 | +print("\n".join(lines)) | ||||