🧠 Does the Language of Artificial Intelligence Move Markets?
UQO Working Paper No. 0002 (FIRC-funded) — A Semantic Analysis of Russell 3000 SEC Filings and the Cross-Section of Stock Returns, 2010–2026 — **Version 2.1, November 2026 (revised after peer review; v2.0 of October 28, 2026 was the Russell 3000 extension of the S&P 500 study, formerly WP 17 v1.1, archived in docs/paper_v1.1_sp500_20261026/). Research funded by the FIRC (Fonds institutionnel de recherche et de création, UQO).
TL;DR (v2.1, revised after peer review) — We embed every Form 10-K, 10-Q and 8-K of 2,375 U.S. firms (current S&P 500 members ∪ iShares Russell 3000 holdings, 527,548 filings, 2010–2026) with a sentence transformer, score each chunk against AI anchor concepts, and link the filing-year signal to forward returns whose timing is look-ahead-free (July Y+1 → June Y+2) on a current-membership universe. In the broad market AI language carries a modest premium that is regression-robust and sort-fragile: winsorized Fama–MacBeth slope +1.88 pp/SD (NW t 2.41, CI [+0.27, +3.49]); winsorized EW Q5–Q1 +3.9 pp/yr (NW t 2.00, plain 1.78, CI [-0.8, +8.6]; median +0.5); every level conditional on survival to October 2026. The post-ChatGPT increase appears only among the largest 1,000 firms and in the 2024 cohort (winsorized +3.1 → +12.7, +3.3 without 2024; remaining firms +4.0 → +3.5); the tested large-vs-small contrast is +10.8 pp (t 1.83 firm / 1.55 two-way, wild p 0.225, MDE 16.5), and the event-study gradient (largest 1,000 CDA t 3.02 under the 2022 IWV market model) falls to 1.12 / 1.22 / 1.38 / 0.52 under beta-only / market-adjusted / size×momentum / FF5+MOM benchmarks. Disclosed AI projects (SPID, gpt-4o-mini extraction, unvalidated) show no detectable premium (any-AI contrast +2.8 pp, t 0.77, MDE 10.1).
📌 Status
| Item | Value |
|---|---|
| Version | 2.1 (November 2026) — revised after the FIRC-0002 peer review (Stage D rebuilt panel and Stage E prose; paper/sections/*.tex, paper/appendix/appendix.tex); v2.0 (October 28, 2026) = Russell 3000 extension; à valider par les co-auteurs |
| Funding | FIRC (UQO) |
| Previous versions | v1.1 (S&P 500, 2026-10-17 review) and v1.0 (June 2026): docs/paper_v1.1_sp500_20261026/ |
| Code & data | v2.0 exhibits: produced by the committed scripts/r3k_00…07 at commit 3cf7560 from data/raw_russell3000/ (factor panel, filing-level scores, SPID counts, universe) and data/processed_r3k/ (Yahoo prices and SEC share counts of the 2026-10-28 vintage; sha256 manifest in UQO-WP-REVIEW/reproducibility/FIRC-0002/environment/inputs.sha256); these two directories are gitignored (≈ 320 MB) and must be deposited (spbgit release or M3U96b archive referenced by hash — pending author action) before the results can be called reproducible by a third party. The re-run of the committed chain reproduces results.json exactly, results2.json except the spid and double_sort_* blocks (stale at commit time) and results_event.json under the author's pandas 3.0.2 (see reproducibility/FIRC-0002/baseline_rerun_diff.txt). v2.1 review chain (scripts/r3k_10…23, scripts/run_all.sh, pinned requirements.lock, tests/test_regenerate.py): rebuilt panel (corrected market capitalization, cleaned returns, CIK-keyed), results in results/r3k_v2/. Raw filing text and embeddings come from the EDGAR Research Database (UQO WP 0001) and are not redistributed; FinData OS (FirstRate) raw closes are a licensed second price source (access documented in data/processed_r3k_v2/README.md). |
🏆 Headline results (Russell 3000 unless stated; v2.1 rebuilt panel, winsorized within formation year unless stated)
| Object | Estimate (v2.1) |
|---|---|
| Panel | 27,354 firm-years, 2,375 firms, formation years 2010–2024 (6,719 firm-years of S&P 500 members); corrected market capitalization, cleaned returns (14 series breaks removed), CIK key |
| Full-sample Q5–Q1 spread (composite) | EW raw +5.5 (NW t 2.40); EW winsorized +3.9 (NW t 2.00, plain 1.78, CI [-0.8, +8.6]); median +0.5; VW (corrected cap) +7.4 (t 2.69); S&P 500 members EW winsorized +5.7 |
| Fama–MacBeth slope (composite) | winsorized +1.88 pp/SD (NW t 2.41, plain 2.51, CI [+0.27, +3.49]); raw +2.77 (t 2.44); with sector dummies, winsorized +0.88 (NW 2.80, plain 2.74); sector×year FE +0.75 (firm t 2.04, two-way 2.78) |
| Pre / post ChatGPT, Russell 3000 (winsorized) | +3.4 → +6.0 (post CI [-25.5, +37.6], n = 3); cohorts 2022: -5.0, 2023: +3.1, 2024: +19.9; pooled post +6.2 (t 2.14 firm / 0.84 two-way, wild p 0.631); post − pre +2.4 (t 0.78 / 0.36, MDE 8.5); permutation p 0.31; sup-Wald p 0.59; post FF6 alpha -0.3 %/yr |
| Pre / post, S&P 500 members (winsorized) | +3.8 → +13.2; cohorts 2022: +14.8, 2023: -7.1, 2024: +32.0; pooled post +13.3 (t 2.39 / 1.15); post Sharpe 0.69 |
| Size (winsorized) | largest 1,000: +3.1 → +12.7 (ex-2024 +3.3); remaining: +4.0 → +3.5; contrast hi×post×large +10.8 (t 1.83 / 1.55, wild p 0.225, MDE 16.5); size-neutral full +4.9 (t 2.19) |
| Event study (IWV market model, day 0 = 1 Dec 2022, N = 2,215) | 1-year H−L +14.2 pp (CDA 2.23; Welch 3.92 for reference); [0,+20] +1.0 (CDA 0.52); largest 1,000 +20.0 (CDA 3.02) vs remaining +12.2 (1.51); largest-1,000 CDA under beta-only / market-adjusted / size×mom / FF5+MOM: 1.12 / 1.22 / 1.38 / 0.52; 2022 ranks 1 of 8 placebo launches |
| Sector / within-sector | post-launch sector×year FE slope +0.46 (t 0.43); sector-neutral sort full +1.4 (t 1.61); β_TECH post 0.37; FF6+TECH post alpha -2.1 %/yr |
| Form-specific signals (winsorized) | 10-K only: full +6.2 (t 1.91); horse race 10-K +2.78 (t 2.23), 10-Q -0.32, 8-K +0.55; Wald equal slopes p 0.02 (raw p 0.23) |
| SPID AI projects | any-AI firm-level +2.8 pp (t 0.77, CI [-4.3, +9.9], MDE 10.1); cohort-level MDE 12.7; SPID×post -1.93 (t -1.93 / -0.96); prevalence 2.0 % of firm-years; no human labels yet |
| Placebo factors (post, two-way t) | cybersecurity interaction t 3.98 (RW p 0.05); AI disruption risk 0.96; ESG -1.48; only cybersecurity survives the family adjustment |
| Construct validity | encoder window 256 tokens ≈ 195 words of 512 (94.8 % of chunks truncated; 61 % of AI-term hits beyond the window); keyword baseline ρ 0.13; Utilities 6.5 % of Q5 vs 3.2 % of sample; stripped-anchor composite ρ 0.98; negation probe 0.396 vs 0.578 |
| Survivorship | EW panel − IWV +5.7 pp/yr (winsorized +3.6); 2019 IWV small tercile 61 % absent by 2025 vs large 16 %; exit-rate difference needed to generate the whole spread: 5.7 pp/yr (−50 % exit return); attrition by AI quintile not computable (X1) |
| Multiple testing | Romano–Wolf p of the composite spread within its family 0.32; statistics with |
The v2.0 values that these replace (EW +5.5, t 2.41; FM +3.07, t 2.80; within-sector t 4.38; largest 1,000 +2.9 → +12.8; event-study Welch 5.09 vs 1.55; Table 17 all t = 0.00) are recorded as BEFORE values in UQO-WP-REVIEW/improvements/FIRC-0002/implemented_changes.md and in the manuscript where the comparison matters.
🗂 Repository layout
ai-disclosure-stock-returns/
├── data/raw_russell3000/ # factor panels, filing_scores, filings, companies, universe.json, spid_firm_year_signals.csv (from the EDGAR DB)
├── data/processed_r3k/ # prices (Yahoo), SEC share history, FF factors, merged/analysis panels, LS series, event CARs
├── scripts/r3k_00..07_*.py # the v2.0 pipeline, in order (01: Yahoo prices · 01c: SEC share counts · 02: panel · 03: core · 04: extended · 05: event · 06: figures · 07: tables + macros)
├── scripts/r3k_10..23_*.py # the v2.1 review chain (run_all.sh): second price pass, SEC shares, FinData checks, rebuilt panel, core/extended/event/survivorship, figures, tables + macros, bib, SPID frame, construct validity
├── scripts/stageE_*.py # Stage E writing helpers: macros_stageE.tex (prose numbers from results/), response_to_referees table
├── results/r3k/ # v2.0 results (results.json, results2.json, results_event.json, CSVs)
├── results/r3k_v2/, results/n1/ # v2.1 results (incl. inline_numbers.json, validation frames) and the node audit (corpus counts, tokenizer, keyword baseline, alternative anchors)
├── figures/r3k/, figures/r3k_v2/ # v2.0 figures; v2.1 figures (17, pdf + png)
├── paper/ # main.tex, sections/ (prose + macros_stageE.tex), appendix/, tables/ (generated, incl. macros.tex), figures_r3k/ → main.pdf
├── code/tex2docx/ # LaTeX → Word conversion (prep_tex.py, post_docx.py)
└── docs/ # v1.1 archive, review report, changelog🚀 Quick start (v2.1 review chain — Stage D, 2026-11-05)
uv venv .venv-review --python 3.12 && uv pip install --python .venv-review/bin/python -r requirements.lock
bash scripts/run_all.sh # 10 (prices, FF daily) → 12 (SEC shares) → 13/13b (FinData checks) → 14…18 (panel, core, extended, event, survivorship) → 19/20 (figures, tables) → latexmk
.venv-review/bin/python -I tests/test_regenerate.py --quick # schema / leakage / manifest checks; without --quick: full regeneration + diff at 1e-6🚀 Quick start (v2.0 committed chain)
python3 -m pip install -r requirements.txt
python3 scripts/r3k_00_factors.py && python3 scripts/r3k_01_download_prices.py && python3 scripts/r3k_01c_sec_shares.py
for s in 02_build_panel 03_analysis 04_extended 05_event_study 06_figures 07_tables; do python3 scripts/r3k_$s.py; done
cd paper && latexmk # → main.pdf (every number in the text is a macro from tables/macros.tex)📊 Exhibit map (Stage E, exhibits director, 2026-11-05)
Every table of the paper is a self-contained float generated by scripts/r3k_20_tables_v2.py into paper/tables/<name>.tex
(\ExhibitTable{label}{caption}{size}{threeparttable + notes}), and every figure by scripts/r3k_19_figures_v2.py into
figures/r3k_v2/<name>.pdf with a float wrapper paper/figures_r3k/<name>.tex (\ExhibitFigure{label}{caption}{\includegraphics}).
A bare \input{tables/<name>} / \input{figures_r3k/<name>} places the exhibit with its scientific caption, label and notes; inside an
existing \begin{table} wrapper only the body is printed. paper/tables/appendix_exhibits.tex (input from main.tex after the appendix)
prints, behind \ExhibitOnce guards, every table not placed earlier and the appendix-bound figures, so no exhibit is lost or duplicated.
The full map (label → file → placement main/appendix → title → result-file sources) is paper/tables/EXHIBIT_MAP.md (also .json);
the render-and-inspect audit is UQO-WP-REVIEW/quality_control/_FIRC-0002_table_audit.csv and _figure_audit.csv. Numbers in captions and
notes are read from results/r3k_v2/* (BEFORE values of the committed v2.0, from results/r3k/*, appear only in tab_hygiene Panel B).