SPB Git

spb/wp39_uqo

Public

WP39: phase 0-2 scaffold — data audit, frozen design, PIT protocol, client, features, tests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Nov 2, 2026) Browse files

76 changed files +6,968 −0

76 changed files
added .env.example +11 −0
@@ -0,0 +1,11 @@
1+# WP39 UQO — environment-based authorization. Never commit a real .env.
2+# FinData OS (mandatory primary data source). Key file is read if FINDATA_API_KEY is unset.
3+FINDATA_BASE_URL=https://findata.spboucher.ai/api/v1
4+FINDATA_API_KEY=
5+FINDATA_API_KEY_FILE=~/findata-secrets/api-key-wp39.txt
6+# Scratch cache for licensed raw extracts (outside the repository, never committed)
7+WP39_CACHE=~/wp39-cache
8+# SEC EDGAR fair-access User-Agent (public data, no secret) for ticker->CIK->SIC crosswalk
9+SEC_USER_AGENT="UQO WP39 research (mailto:simon-pierre.boucher@uqo.ca)"
10+# Set to 1 to run the live API contract tests
11+WP39_LIVE=0
added .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 CLAUDE.md +43 −0
@@ -0,0 +1,43 @@
1+# CLAUDE.md — UQO Research WP39
2+
3+## THE INVISIBLE BALANCE SHEET
4+### Can Intraday Financial Markets Detect Corporate Deterioration Before Accounting Disclosures?
5+
6+**Project ID:** `wp39_uqo` · **Institution:** Université du Québec en Outaouais (UQO) · **PI:** Simon-Pierre Boucher
7+**Status:** research project built 2026-11-02 under the owner's specification (reproduced below in condensed form; the
8+owner's original brief is the authoritative text). All findings are hypotheses until reproducibly estimated.
9+
10+Owner instructions added during the build (2026-11-02): (1) the FinData **fundamentals API** is the accounting source and
11+must be used; (2) **minimise AI usage** — no LLM features, no neural/text models, no AI-generated statistics.
12+
13+## Non-negotiable execution rules
14+1. FinData OS (`https://findata.spboucher.ai/api/v1`) is the primary source of prices, volumes, earnings events and
15+ fundamentals. No silent substitution; every exception is documented in `DATA_AUDIT.md` / `docs/API_INTEGRATION.md`.
16+2. Inspect before changing; preserve all other working papers; this repository is its own git repo.
17+3. Credentials from the protected store only (`~/findata-secrets/api-key-wp39.txt` on the node); never printed, never
18+ in URLs, git, artifacts, notebooks, figures or manuscript. No destructive ingestion, no unapproved backfills.
19+4. FirstRate Data is privately licensed: no raw records in git, public endpoints, replication packages or logs.
20+5. Hypotheses, variable definitions, PIT rules, baselines, splits and significance plan are frozen in
21+ `docs/RESEARCH_DESIGN.md` and `docs/PIT_PROTOCOL.md` before interpreting results. Prediction ≠ causation.
22+6. Every claim traces to a saved table/figure/log/test. No fabricated statistics or references.
23+7. Phases with gates; `PROGRESS.md`, `DECISIONS.md`, `DATA_AUDIT.md`, `LIMITATIONS.md` are kept current.
24+8. English everywhere; LaTeX article compiled with `latexmk` (`paper/`).
25+
26+## Where things are
27+| Item | Location |
28+|---|---|
29+| Design, PIT rules, novelty | `docs/RESEARCH_DESIGN.md`, `docs/PIT_PROTOCOL.md`, `docs/NOVELTY_MEMO.md` |
30+| Data audit, limitations, decisions, progress | root `*.md` files |
31+| Code | `src/wp39/` (client, provenance, calendar, instruments, PIT fundamentals, corporate actions, ingest, features, labels, samples, splits, models, inference, portfolio, robustness, figures, pipeline) |
32+| Pipeline | `scripts/00_…09_` in order; `scripts/01a_extract_node_tables.sh` runs on M3U96a |
33+| Tests | `tests/` (`pytest`; live API tests need `WP39_LIVE=1`) |
34+| Artifacts | `artifacts/manifests` (hashes, versions), `artifacts/evaluation`, `artifacts/logs`, `results/`, `figures/` |
35+| Paper | `paper/main.tex` + `sections/` + generated `tables/`, `figures/` |
36+
37+## How to run (compute node M3U96a, API on localhost)
38+```bash
39+rsync -a --exclude .venv --exclude artifacts/logs ~/Desktop/UQO/Recherche/Recherche-UQO/finance/invisible-balance-sheet/ M3U96a:~/wp39_uqo/
40+ssh M3U96a 'cd ~/wp39_uqo && uv venv -p 3.12 .venv && uv pip install -e ".[dev]" && export FINDATA_BASE_URL=http://127.0.0.1:8600/api/v1 && \
41+ bash scripts/01a_extract_node_tables.sh && for s in 00 01 02 03 04 05 06 07 08; do .venv/bin/python scripts/${s}_*.py; done'
42+```
43+Then `rsync` `results/ figures/ artifacts/ paper/tables paper/figures` back and `cd paper && make`.
added DATA_AUDIT.md +167 −0
@@ -0,0 +1,167 @@
1+# DATA_AUDIT.md — WP39 `wp39_uqo`
2+
3+Phase 0 discovery and feasibility audit of the **FinData OS** API (`https://findata.spboucher.ai/api/v1`) as the primary
4+source for *The Invisible Balance Sheet*. All numbers below were measured on **2026-11-02** (America/Toronto) with the
5+owner's Claude Code key (admin scope, laptop) and then with a dedicated least-privilege key `wp39_uqo`
6+(scopes `read:market, read:fundamentals, query, export`; stored outside git in `~/findata-secrets/api-key-wp39.txt` on
7+M3U96a and `~/Desktop/Cluster/secrets/findata/api-key-wp39.txt` on the laptop, mode 600). No credential appears in
8+this repository, in logs or in artifacts. Probe transcripts: `artifacts/logs/phase0_probe.json` (produced by
9+`scripts/00_probe_findata.py`).
10+
11+## 0. Viability conclusion
12+
13+**YES — viable, with two structural caveats that shape the paper.**
14+
15+1. A licensed, point-in-time usable cohort exists: **5,451 US-listed entities** with quarterly fundamentals
16+ (**67 metrics**, `filing_date` 2012-01-03 → 2026-10-30, median 45 quarterly periods per firm), **373,326 earnings-release
17+ events** with release date and (for 65 %) before-open/after-close timing, and **6.70 billion raw 1-minute bars** for
18+ 16,195 stock symbols (2000-01-03 → 2026-10-30) including 8,069 `-DELISTED` symbols. Exports of 1-minute history are
19+ fast (≈ 1 s per symbol-decade, see §6).
20+2. **Caveat A — survivorship in fundamentals, not in prices.** The fundamentals/earnings tables contain **zero delisted
21+ entities** (ingestion ran for *active* tickers only). Minute bars do cover delisted names, so the price side is
22+ survivorship-free, but the accounting panel is conditioned on being listed on 2026-11-01. The vendor does serve
23+ fundamentals for at least some delisted tickers (probe: `FMD` → HTTP 200 with data; `CWZ` → 404), so a scoped
24+ delisted-fundamentals backfill is *possible* but requires owner approval and a capacity plan (not run; see §8).
25+3. **Caveat B — PIT is a proxy.** `available_at = filing_date + 1 day` is a policy, `revision_id = 1` for every fact
26+ (`observed_at` = first ingestion, 2026-11-01/02). Values are the vendor's *current* history, so restatements that
27+ happened before ingestion are invisible. The design therefore (i) uses only prior-quarter fundamentals as inputs,
28+ (ii) uses the **earnings-release date** (not the filing date) as the reveal date, and (iii) reserves a stringent
29+ specification using SEC-filing-level reconstruction for a subset (Phase 5, conditional on time).
30+
31+## 1. API contract — documented vs observed
32+
33+| Purpose | Route (observed in `openapi.json`, OpenAPI 3.1.0, API 1.0.0) | Observed behaviour |
34+|---|---|---|
35+| Datasets | `GET /catalog/datasets` | 64 datasets; 62 `active`, `fundamentals.sec_companyfacts` = `pending_configuration`, `market_ticks` = `unsupported` |
36+| Dataset detail | `GET /catalog/datasets/{id}` | version, `license_class = frd-private` |
37+| Bars | `GET /market/bars` | `interval ∈ {1m, 5m, 1d}` only (no 30m/1h on REST); `adjustment ∈ {raw, split, split_div}`; `limit ≤ 10 000`; `format ∈ {json, arrow, csv}`; `version` pin |
38+| Bars schema | `GET /catalog/schema/bars` | schema v1, `timestamp_convention = bar_open`, `timezone_storage = UTC`, 20 fields (see §3) |
39+| Fundamentals | `GET /fundamentals/{entity}` | `as_of`, `metrics`, `period_type ∈ {q,a}`, `include_superseded`, **`limit ≤ 20 000`** (default 2 000) |
40+| Fundamental periods | `GET /fundamentals/{entity}/periods` | one row per fiscal period with `filing_date`, `available_at`, `max_revision`, `restated` |
41+| SQL | `POST /query` | one read-only statement, `max_rows ≤ 100 000`, 30 s; views = dataset ids with `.`→`_` |
42+| Exports | `POST /exports` → `GET /exports/{id}` → `/download` | body `{dataset_id, symbols ≤ 500, start, end, adjustment, format}`; **range ≤ 12 years per request (HTTP 413 otherwise)**; Parquet with schema metadata and pinned `X-Dataset-Version` |
43+| Coverage | `GET /coverage`, `/coverage/symbols` (`limit ≤ 5 000`, cursor), `/coverage/heatmap` | per-session bar counts vs `expected_bars` (391 regular) |
44+| Instruments | `GET /instruments`, `/instruments/{symbol}` | status `active`/`delisted`, first/last date |
45+| Quality | `GET /quality`, `/quality/anomalies` | row-level flags (`price_jump`, `outside_session`, …) |
46+| **Earnings events** | **no route** | dataset `fundamentals.earnings` is listed (0 rows reported) but rows live in Postgres `earnings_events` → read-only extraction on the node (documented exception, §7) |
47+| Corporate actions | **no route** | Postgres `corporate_actions`: 6,131 splits (2000-01-03 → 2026-10-15), 243,209 cash dividends; applied at query time via `adjustment=` |
48+
49+Reconciliation notes: the catalog reports `row_count = 0` for Postgres-backed datasets (`fundamentals.*`, `corporate_actions`,
50+`reference.instruments`); that is a catalog limitation, not an absence of data. The REST `interval` enum is narrower than the
51+lake (30m/1h exist only as vendor-adjusted datasets); WP39 rebuilds 5m/30m/1d bars **from the raw 1m export** so that every
52+frequency shares one source and one adjustment path.
53+
54+## 2. Market bars — coverage
55+
56+Counts of distinct stock symbols with at least one bar on a mid-June session (SQL playground, `session_date =` predicate):
57+
58+| Session | 1m symbols | 1m bars | 1d symbols | of which `-DELISTED` in 1d |
59+|---|---:|---:|---:|---:|
60+| 2001-06-15 | — | — | 1,088 | 0 |
61+| 2005-06-15 | 3,498 (340,665 bars delisted) | 631,260 | 1,504 | 0 |
62+| 2010-06-15 | — | — | 2,309 | 0 |
63+| 2015-06-15 | 6,489 | 1,207,920 | 2,985 | 0 |
64+| 2020-06-15 | — | — | 4,144 | 0 |
65+| 2025-06-16 | 6,918 | 1,317,343 | 6,485 | 0 |
66+
67+Finding: the vendor **1d dataset is incomplete** relative to the 1m dataset (about half the symbols in 2005–2015 and no
68+delisted names). Decision D-003: daily bars are *derived* from the 1m export (regular session 09:30–16:00 ET) — never taken
69+from `market_bars.stock.1d.raw`. Delisted symbols are present in the 1m lake (e.g. `AA.B-DELISTED` 531 sessions
70+2014–2016; `CWZ-DELISTED` 2000–2014).
71+
72+Bar conventions verified on `XOM` and `SPY` exports: timestamps are bar **open** in UTC (`2012-01-03 09:01Z` = 04:01 ET),
73+extended hours 04:00–19:59 ET are present, zero-volume minutes are absent (bar counts per session 405–798 vs 391 expected
74+regular bars), `quality_flags` list is empty on normal rows, `revision_id = 1`.
75+
76+## 3. Bars schema (Arrow, schema v1)
77+
78+`instrument_id, symbol_as_reported, venue (null), asset_class, interval, timestamp_utc (timestamp[us, UTC], bar open),
79+session_date (date32, exchange tz), open, high, low, close, volume (double), currency, trade_count (int32?, derived only),
80+vwap (double?, derived only), adjustment_type, source_id, ingested_at, quality_flags (list<string>), revision_id (int32)`.
81+Parquet exports carry metadata `findata.schema = bars`, `findata.schema_version = 1`, `findata.timestamp_convention = bar_open`.
82+
83+## 4. Fundamentals — coverage and PIT fields
84+
85+- Entities: **5,451** (`frd:<TICKER>`, `security_id = firstrate:stock:<TICKER>`, none delisted, none with `security_id` null).
86+- Metrics observed per period: **67** (the vendor documents 76; 9 are never populated in the API output). Names:
87+ `acc_oci, assets_c, assets_nc, assets_tot, capex, cash, cash_business_acq, cash_change, cash_debt_sec, cash_div,
88+ cash_equity, cash_fin, cash_inv, cash_inv_acq, cash_op, cogs, cos_inc, debt, debt_c, debt_nc, def_rev, depr, dps, ebit,
89+ ebitda, ebt, eps, eps_d, equity, fx_impact_cash, gm, gp, intangibles, interest_exp, intr_cover, inv_c, inv_nc, inventory,
90+ investments, liab_c, liab_nc, liab_tot, net_inc, net_inc_com, net_inc_non_control, net_loss_discontinued, om, op_ex,
91+ op_inc, payables, ppe, pref_divs, receivables, research_dev, ret_earnings, rev, roa, roe, roic, sgna, share_comp, shares,
92+ shares_av, shares_av_diluted, tax_asset, tax_expense, tax_liability`.
93+- Quarterly `rev` facts by fiscal year (entities / facts): 2011: 1,798 / 1,812 · 2012: 2,461 / 8,725 · 2013: 2,623 / 9,868 ·
94+ 2014: 2,771 / 10,560 · 2015: 2,916 / 11,145 · 2016: 3,076 / 11,656 · 2017: 3,276 / 12,340 · 2018: 3,505 / 13,209 ·
95+ 2019: 3,763 / 14,034 · 2020: 4,309 / 15,488 · 2021: 4,663 / 17,458 · 2022: 4,851 / 18,289 · 2023: 5,043 / 18,904 ·
96+ 2024: 5,244 / 19,467 · 2025: 5,370 / 19,625 · 2026: 4,928 / 10,915. `filing_date` is never null (no `pit_fallback`).
97+- Firms by number of quarterly periods: ≥ 8: 5,018 · ≥ 20: 4,331 · ≥ 40: 2,891. First quarter year: 2011: 2,141 ·
98+ 2012: 317 · 2013–2019: 148–256 per year · 2020: 551 · 2021: 353 · 2022–2025: 164–215 per year.
99+- Filing lag (filing_date − fiscal_period_end, quarterly): p10 = 30 d, median = 40 d, p90 = 77 d.
100+- Q4 values are genuine quarterly flows (AAPL FY2019 revenue 260.17 bn = 84.31 + 58.02 + 53.81 + 64.04 bn).
101+- PIT fields per fact: `filing_date`, `published_at` (null), `available_at = filing_date + 1 d 00:00 ET`, `observed_at`
102+ (= 2026-11-01 18:24 ET for the first ingestion), `revision_id = 1`, `restatement_flag = false`, `superseded_at = null`.
103+ The API `as_of` semantics (`available_at ≤ as_of` and (`revision_id = 1` or `observed_at ≤ as_of`)) were exercised:
104+ AAPL `as_of = 2020-01-01` returns 2,000 facts (limit) and reports `facts_hidden_by_as_of = 2211`.
105+- Entity master: `cik`, `sector`, `industry` are **null for all 5,451 entities** → external SEC crosswalk needed (§7).
106+
107+## 5. Earnings-release events (reveal dates)
108+
109+Postgres `earnings_events` (`entity_id, event_date, eps_estimate, eps_reported, release_time, source_id, observed_at`):
110+373,326 rows, 5,451 entities, 2000-01-01 → 2027-04-29, one row per (entity, date). `release_time`: `after_close` 124,832 ·
111+`before_open` 120,586 · null 127,908. For 2012–2024 the null share is 35–36 %; `eps_estimate` is null for 24–27 % of
112+events (vendor estimate; vintage unknown → exploratory only). Row counts for 2025–2026 are inflated by forward-dated
113+placeholders (2026: 35,361 events), which are dropped at the sample end (2026-10-30).
114+
115+Matching quarterly filings to the first release event in `[period_end, filing_date + 10 d]` (213,954 filings 2012→):
116+96.3 % matched; 1,493 (0.7 %) have `filing_date < event_date`; 16,868 (7.9 %) have a lag > 30 d (likely mismatches or
117+late filers); median `filing_date − event_date` = **1 day**. Rule (PIT_PROTOCOL §3): reveal date `A_q` = matched release
118+date; a firm-quarter is **excluded** when no release is matched, when `filing_date < event_date`, or when the lag exceeds
119+30 days; the prediction cutoff always satisfies `c < min(A_q, F_q)` in trading days.
120+
121+## 6. Throughput and capacity (measured on M3U96a, API on localhost)
122+
123+| Operation | Measured |
124+|---|---|
125+| Export 1m raw, 1 symbol, 2012-01-01→2019-12-31 (`XOM`) | ready in 1.0 s, 859,354 rows, 13.6 MB Parquet, dataset version 17375 |
126+| Export 1m raw, 1 symbol, 2020-01-01→2026-10-30 | ready in 1.0 s, 884,983 rows, 15.4 MB |
127+| Full-range export (2012→2026, 14.8 years) | **HTTP 413** — limit 12 years per request → two requests per symbol |
128+| SQL cross-section (`session_date =` on 1m) | ≈ 3 s |
129+| Coverage per symbol (`/coverage/symbols`) | ms, cursor-paged |
130+| Fundamentals, one entity, all quarterly facts | one call (≤ 20 000 rows) |
131+
132+Capacity model for the main sample (≈ 4,300 firms with ≥ 8 quarters and 1m coverage): 2 exports × ~1.5 s ≈ 3.6 h of
133+export wall-time (sequential; 4 concurrent streams bring it under 1 h), ≈ 30 MB raw Parquet per firm (≈ 130 GB if kept).
134+Decision D-004: raw extracts are processed **streaming** (export → daily feature rows at 1m/5m/30m/1d → delete raw file,
135+keep SHA-256 + row count in the manifest), so steady-state scratch usage stays below 5 GB. The storage node M3U96a
136+(28 cores, 96 GB RAM, 319 GB free on the internal SSD, hard floor 60 GB for FinData) hosts the computation; the feature
137+panel (≈ 4,300 firms × ~3,700 sessions × 4 frequencies) is < 2 GB.
138+
139+## 7. External sources and exceptions
140+
141+| Need | Source | Status | Why not FinData |
142+|---|---|---|---|
143+| Reveal dates / release timing | FinData Postgres `earnings_events` (read-only `psql` on M3U96a) | available | not exposed by the API (gap logged for the FinData backlog) |
144+| CIK, SIC industry | SEC `company_tickers.json` (10,423 rows) + `submissions/CIK##########.json` (`sic`, `sicDescription`, `exchanges`, `formerNames`) | verified reachable (fair-access UA) | entity master has no CIK/sector |
145+| Daily factors (H5 only) | Kenneth French library, FF5 2×3 daily + momentum daily | verified (HTTP 200, updated 2026-10-26) | not a FinData dataset |
146+| Analyst consensus | vendor `eps_estimate` in `earnings_events` (24–27 % missing, vintage unknown) | exploratory only | no point-in-time consensus history available |
147+| TAQ / quotes / order flow | none | **not available** (vendor supplies bars only) | bar-based proxies are *never* called order flow, spreads or informed trading |
148+
149+## 8. Gaps, risks and recommendations to the owner
150+
151+1. **Delisted fundamentals backfill (recommended, not run).** A one-off `fundamentals` job for the 8,069 `-DELISTED`
152+ tickers (vendor returns data for at least part of them) would remove the survivorship conditioning of the accounting
153+ panel. Estimated cost: ≤ 8,069 vendor calls (1 req/s policy ≈ 2.3 h), a few hundred MB in Postgres. Requires: owner
154+ approval, `findata ingest fundamentals --delisted` (does not exist yet; connector change on M3U96a `~/apps/findata`).
155+2. **Earnings events API route** — expose `fundamentals.earnings` through `/api/v1/earnings/{entity}` so that WP39 (and
156+ future projects) stop reading Postgres directly.
157+3. **SEC EDGAR connector** (`fundamentals.sec_companyfacts`, pending a User-Agent setting) would give filing-level
158+ as-originally-reported values for the stringent PIT specification.
159+4. API bug found: `POST /admin/keys` returns HTTP 500 (`api_keys_user_id_fkey` violation) when the caller is an API key
160+ whose `user_id` is not in `users`; the CLI `findata create-key` works. Logged for the FinData backlog, not fixed here.
161+
162+## 9. License and privacy constraints applied
163+
164+FirstRate Data: perpetual private use, research and derived statistics allowed with attribution, **no redistribution of raw
165+records**. Consequently: no raw bars or fundamentals are committed; `data/raw` stays empty; the replication package ships
166+code, manifests (hashes, versions, counts), derived aggregate tables and figures only; the manuscript attributes FirstRate
167+Data via FinData OS. SEC and Kenneth French data are public.
added DECISIONS.md +14 −0
@@ -0,0 +1,14 @@
1+# DECISIONS.md — dated design and engineering decisions (WP39)
2+
3+| ID | Date (ET) | Decision | Reason | Consequence |
4+|---|---|---|---|---|
5+| D-001 | 2026-11-02 13:00 | Compute on **M3U96a** (FinData host) with a dedicated least-privilege key `wp39_uqo`; repository lives in the UQO Research workspace (`Recherche-UQO/finance/invisible-balance-sheet`, dir name follows the series convention; project id `wp39_uqo`) and is rsync'd to `M3U96a:~/wp39_uqo` for runs | API on localhost, lake co-located, 28 cores / 96 GB; secrets never leave `~/findata-secrets` / `~/Desktop/Cluster/secrets` | results and manifests synced back; raw cache stays on the node |
6+| D-002 | 2026-11-02 13:05 | **Earnings release dates** (`earnings_events.event_date`) define the reveal date `A_q`; the filing date `F_q` defines structured-fact availability (`available_at = F_q + 1`) | press releases precede 10-Q filings by a median of 1 day; cutoffs must precede the *first* public reveal | cutoff rule `c < min(A_q, F_q)`; release rows read from Postgres (no API route) — documented exception |
7+| D-003 | 2026-11-02 13:10 | Daily bars are **rebuilt from the 1-minute raw export** (regular session), not taken from `market_bars.stock.1d.raw` | vendor 1d dataset covers about half the symbols before 2016 and no delisted names | one source, one adjustment path for all four frequencies |
8+| D-004 | 2026-11-02 13:30 | Streaming feature extraction (export → features → delete raw Parquet; manifest keeps SHA-256) | disk budget on the FinData host (hard floor 60 GB free) | re-runs re-export from the pinned dataset version |
9+| D-005 | 2026-11-02 14:00 | Universe = all FinData fundamentals entities (survivor-conditioned); delisted-fundamentals backfill **proposed, not run** | vendor ingestion covered active tickers only; backfill needs owner approval + capacity plan (rule 3 of the brief) | survivorship caveat stated in abstract, data section, limitations; price side is survivorship-free |
10+| D-006 | 2026-11-02 14:05 | **No neural (B7) nor text/multimodal (B8) models; no LLM anywhere in the pipeline** | owner instruction received mid-session on 2026-11-02 ("limite le plus possible l'utilisation AI"); also keeps the frequency comparison about information sets rather than capacity | ladder is B0–B6; LightGBM provides the nonlinear benchmark with equal budgets |
11+| D-007 | 2026-11-02 14:10 | Primary target = adverse **operating-income** surprise vs a seasonal random walk with drift, scaled by total assets, threshold −0.5 % | no point-in-time consensus exists in FinData; operating income is less affected by one-off items than net income; Foster (1977) model is the classic honest expectation | consensus-based miss (vendor `eps_estimate`) is exploratory only |
12+| D-008 | 2026-11-02 14:15 | Frequency sets B3/B4/B5 use **identical feature families** (one column per family) computed from bars of 30 m / 5 m / 1 m | compare information sets, not dimensionality | a supplementary "all frequencies" model is run in Phase 4 |
13+| D-009 | 2026-11-02 14:20 | Literature verified with **Crossref metadata** (no AI summarisation); references without a verifiable DOI are cited without one (Grossman–Stiglitz 1980, Holm 1979) | rule 7 of the brief (no fabricated references) | `artifacts/logs/crossref_batch*.json` are the evidence |
14+| D-010 | 2026-11-02 14:30 | Phase gates that require "owner approval" are recorded as **self-approved under the autonomous mandate** with the memo attached; the owner can veto any of them before Phase 6 | the owner asked for the whole project to be built in one autonomous session and is not available mid-task | each gate entry in PROGRESS.md names the memo and the date |
added LIMITATIONS.md +31 −0
@@ -0,0 +1,31 @@
1+# LIMITATIONS.md — living list (WP39)
2+
3+## Data
4+- **Survivor-conditioned accounting panel.** Fundamentals and earnings-release rows exist only for the 5,451 tickers active
5+ on 2026-11-01. Firms that delisted during 2012–2026 (including those that deteriorated and failed) are absent from the
6+ firm-quarter sample, although their minute bars exist. Base rates of severe deterioration are therefore understated and
7+ H3/H5 effects for the most vulnerable firms are not identified. A delisted-fundamentals backfill is proposed (DATA_AUDIT §8).
8+- **PIT is a documented proxy.** `available_at = filing_date + 1 day` is a policy; all facts are `revision_id = 1` observed
9+ on 2026-11-01/02, i.e. the vendor's current (possibly restated) history. Original-as-reported values are not available.
10+ Inputs use prior quarters only, so restatements affect the *measurement of inputs and targets*, not the direction of time.
11+- **OHLCV bars, not ticks.** No quotes, no trades, no order flow. Bar-based statistics (down-bar volume share, bar
12+ autocorrelation) are descriptive proxies and are never interpreted as informed trading or spreads.
13+- Vendor merges ticker changes under the latest ticker (fully since 2022); CIK/SIC come from the SEC's *current*
14+ `company_tickers.json`, so historical ticker reuse before 2022 is only partially auditable (`formerNames` check).
15+- `release_time` is unknown for ~35 % of release events; we never use release-day bars, so this affects only the
16+ descriptive timing exhibit.
17+- The vendor `eps_estimate` has an unknown vintage and is missing for a quarter of events → exploratory only.
18+- 1-minute coverage is thinner before ~2005 and for illiquid names; the sample starts in 2012 and requires ≥ 100 regular
19+ bars per session, which excludes the most illiquid firm-days (a documented selection on liquidity).
20+
21+## Design
22+- The event-time cohort conditions on the *existence* of a release in the next 65 trading days; a hypothetical observer
23+ knows the approximate schedule but not the exact date. The fixed-calendar design is reported as the robustness check.
24+- Prediction, not causation: a positive H1 shows that bar-level information is statistically informative; it does not
25+ establish who traded on private information.
26+- No B7/B8 (neural/text) models by owner instruction; the frequency comparison is therefore within linear and
27+ gradient-boosted families only.
28+
29+## To be completed as results arrive
30+- (Phase 3) achieved sample sizes, base rates, coverage gaps by year/size.
31+- (Phase 5) which placebo/stress tests failed or were inconclusive.
added PROGRESS.md +22 −0
@@ -0,0 +1,22 @@
1+# PROGRESS.md — WP39 `wp39_uqo`
2+
3+## Phase 0 — Discovery and feasibility (2026-11-02) — GATE PASSED
4+- Inspected the UQO Research workspace (`Recherche-UQO/`, 39 papers, harmonisation standard); no `wp39` existed; created
5+ `finance/invisible-balance-sheet/` from the template; git initialised on a dedicated repository (no other paper touched).
6+- Probed FinData: `/health` ok, 64 datasets, OpenAPI 3.1 (45 routes), bars schema v1, fundamentals (67 metrics, 5,451
7+ entities, 2012→2026), earnings events (Postgres), coverage endpoints, export throughput (≈ 1 s per symbol-decade;
8+ 12-year cap per request). Created least-privilege key `wp39_uqo`.
9+- Verified external public sources: SEC `company_tickers.json` + `submissions` (CIK/SIC), Kenneth French daily factors.
10+- Verified 94 bibliography entries on Crossref; wrote `docs/NOVELTY_MEMO.md`, `literature/RELATED_WORK_MATRIX.csv`.
11+- Outputs: `DATA_AUDIT.md` (viability = YES with survivorship + PIT caveats), `configs/*.yaml`, `docs/API_INTEGRATION.md`,
12+ `docs/COMPUTE_BUDGET.md`, `docs/PIT_PROTOCOL.md`, `docs/RESEARCH_DESIGN.md` (frozen), `DECISIONS.md` D-001…D-010.
13+- Owner instructions received during the session: (1) the fundamentals API must be used — it is the accounting source;
14+ (2) minimise AI usage — no LLM features, no neural models (D-006).
15+- Blockers: none. Next safe step: Phase 1 gate memo, then code + tests (Phase 2).
16+
17+## Phase 1 — Research design and novelty — GATE (self-approved under the autonomous mandate, D-010)
18+- `docs/RESEARCH_DESIGN.md` frozen 2026-11-02 14:40 ET; hypotheses H1–H5 with null/alternative, primary endpoint (H1,
19+ h = 20, log loss, binary adverse operating-income surprise), decision rules, splits, inference, power plan.
20+- Owner review pending; nothing in Phases 2–5 depends on test-period data until the Phase 3 gate.
21+
22+## Phase 2 — Data acquisition and verification — IN PROGRESS
added configs/data_contract.yaml +40 −0
@@ -0,0 +1,40 @@
1+# Data contract — verified against the live FinData OS API on 2026-11-02 (see DATA_AUDIT.md)
2+findata:
3+ base_url: https://findata.spboucher.ai/api/v1
4+ openapi: /openapi.json
5+ datasets:
6+ bars_1m: market_bars.stock.1m.raw # raw, bar-open timestamps in UTC, 04:00-20:00 ET, zero-volume minutes absent
7+ bars_1m_etf: market_bars.etf.1m.raw # SPY used as market proxy
8+ bars_1d: market_bars.stock.1d.raw # INCOMPLETE vs 1m (fewer symbols) -> daily bars are rebuilt from 1m
9+ fundamentals: fundamentals.financials # Postgres-backed; GET /fundamentals/{entity}
10+ earnings: fundamentals.earnings # Postgres table earnings_events (no API route yet) -> documented exception
11+ limits:
12+ bars_1m_days_per_call: 31
13+ rows_per_page: 10000
14+ export_years_per_request: 12
15+ export_symbols_per_request: 500
16+ query_timeout_s: 30
17+ query_max_rows: 100000
18+ rate_limit_per_min: 600
19+ fundamentals_limit_max: 20000
20+ bars_schema_version: 1
21+ timestamp_convention: bar_open
22+ timezone_storage: UTC
23+ exchange_tz: America/New_York
24+ regular_session: ["09:30", "16:00"] # the 16:00 bar is the closing print
25+ extended_session: ["04:00", "20:00"]
26+ license_class: frd-private
27+pit:
28+ available_at_policy: "filing_date + 1 day 00:00 America/New_York (vendor proxy; fallback period_end + 91 d flagged pit_fallback)"
29+ revision_semantics: "revision_id=1 observed 2026-11-01/02; no pre-ingestion restatement history (vendor limitation)"
30+ reveal_date: "earnings_events.event_date (press release), release_time in {before_open, after_close, null}"
31+universe:
32+ entity_source: fundamentals entities (5,451 active tickers as of 2026-11-01; NO delisted entities -> survivorship caveat)
33+ min_quarters: 8
34+ first_filing_year: 2012
35+ last_session: 2026-10-30
36+external:
37+ sec_company_tickers: https://www.sec.gov/files/company_tickers.json
38+ sec_submissions: https://data.sec.gov/submissions/CIK{cik:010d}.json
39+ ff5_daily: https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_5_Factors_2x3_daily_CSV.zip
40+ mom_daily: https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Momentum_Factor_daily_CSV.zip
added configs/models.yaml +27 −0
@@ -0,0 +1,27 @@
1+# Equal tuning budget across information sets. Hyper-parameters are tuned ONLY on the validation period.
2+baselines:
3+ B0: {type: base_rate}
4+ B1: {type: logistic, inputs: [fundamentals, controls]}
5+ B2: {type: logistic, inputs: [fundamentals, controls, daily]}
6+ B3: {type: logistic, inputs: [fundamentals, controls, daily, intraday_30m]}
7+ B4: {type: logistic, inputs: [fundamentals, controls, daily, intraday_5m]}
8+ B5: {type: logistic, inputs: [fundamentals, controls, daily, intraday_1m]}
9+logistic:
10+ penalty: l2
11+ C_grid: [0.01, 0.03, 0.1, 0.3, 1.0, 3.0]
12+ standardize: train_only
13+ impute: train_median
14+lightgbm:
15+ information_sets: [B1, B2, B3, B4, B5]
16+ budget_trials: 24 # identical random-search budget for every information set
17+ seed: 20261102
18+ search_space:
19+ num_leaves: [7, 15, 31, 63]
20+ learning_rate: [0.01, 0.03, 0.05]
21+ min_child_samples: [50, 100, 200]
22+ feature_fraction: [0.5, 0.7, 0.9]
23+ bagging_fraction: [0.6, 0.8, 1.0]
24+ lambda_l2: [0.0, 1.0, 10.0]
25+ n_estimators_max: 2000
26+ early_stopping_rounds: 100
27+neural: {enabled: false, reason: "owner instruction 2026-11-02: minimise AI usage; B7/B8 not run"}
added configs/research.yaml +42 −0
@@ -0,0 +1,42 @@
1+# Frozen research design parameters (see docs/RESEARCH_DESIGN.md). Changing a value requires a DECISIONS.md entry.
2+seed: 20261102
3+sample:
4+ start: 2012-01-01
5+ end: 2026-10-30
6+ min_quarters_per_firm: 8
7+ min_price_usd: 1.0 # at cutoff, raw close
8+ min_regular_bars_per_day: 100 # sessions with fewer 1m regular-session bars are "sparse"
9+ min_valid_days_in_window: 15 # out of the 20-trading-day feature window
10+cutoffs:
11+ event_time_horizons_td: [40, 20, 10, 5, 1] # trading days before the earnings release date A_q
12+ primary_horizon_td: 20
13+ fixed_calendar: month_end # last trading day of each month
14+ embargo_rule: "cutoff c < min(A_q, F_q); bars with session_date <= c only; fundamentals with available_at <= c only"
15+feature_window:
16+ short_td: 20
17+ long_td: 60
18+frequencies: [1d, 30m, 5m, 1m]
19+targets:
20+ primary:
21+ name: adverse_opinc_surprise
22+ variable: op_inc
23+ expectation: seasonal_random_walk_with_drift # E[X_q] = X_{q-4} + mean(X_{q-1-k} - X_{q-5-k}, k=0..3), PIT
24+ scale: assets_tot (latest available)
25+ threshold: -0.005 # surprise <= -0.5% of total assets
26+ continuous_primary: scaled_opinc_surprise
27+ secondary:
28+ - {name: roa_yoy_decline, rule: "roa_q - roa_{q-4} <= -0.01"}
29+ - {name: ocf_innovation_negative, rule: "(cash_op_q - cash_op_{q-4})/assets <= -0.01"}
30+ - {name: liquidity_deterioration, rule: "current ratio falls >= 10% yoy OR interest coverage falls below 1 from >= 1"}
31+ - {name: eps_miss, rule: "eps_reported < eps_estimate (vendor estimate, exploratory)"}
32+splits:
33+ train: [2012-01-01, 2018-12-31]
34+ validation: [2019-01-01, 2020-12-31]
35+ test: [2021-01-01, 2026-10-30]
36+ walk_forward: {first_test_year: 2016, embargo_quarters: 1}
37+ firm_holdout_fraction: 0.2
38+inference:
39+ cluster: [entity_id, calendar_quarter]
40+ bootstrap_blocks: calendar_quarter
41+ n_bootstrap: 1000
42+ multiple_testing: holm
added data/README.md +17 −0
@@ -0,0 +1,17 @@
1+# data/
2+
3+No licensed raw records are stored in this repository.
4+
5+| Path | Content | Committed? |
6+|---|---|---|
7+| `data/raw/` | nothing (raw FirstRate bars live only in the ignored scratch cache `$WP39_CACHE` on the compute node) | no |
8+| `data/processed/` | derived firm-quarter panel, feature tables and labels (Parquet). Derived aggregates only; still **not** committed (size, license caution) | no |
9+| `artifacts/manifests/` | hashed dataset manifests: dataset ids, `X-Dataset-Version`, extraction dates, row counts, SHA-256 of extracts, code SHA | yes |
10+
11+Provenance rules (see `DATA_AUDIT.md`, `docs/API_INTEGRATION.md`):
12+- Market bars and fundamentals come from the owner's FinData OS API (`https://findata.spboucher.ai/api/v1`), a private
13+ lakehouse of FirstRate Data (license: private use, no redistribution of raw records).
14+- Earnings-release calendar rows are read from the FinData Postgres table `earnings_events` on the storage node because the
15+ API does not expose that dataset yet (documented exception).
16+- External public augmentations: SEC EDGAR `company_tickers.json` and `submissions` (CIK, SIC), Kenneth French data library
17+ (daily factors). Both are public, versioned by download date in the manifests.
added data/processed/.gitkeep +0 −0
added data/raw/README.md +4 −0
@@ -0,0 +1,4 @@
1+# data/raw — intentionally empty
2+Raw FirstRate Data records (via FinData OS) are licensed for private use and are never stored in this repository.
3+They live only in the ignored scratch cache on the compute node (`$WP39_CACHE`), are deleted after feature extraction,
4+and are described by hashed manifests in `artifacts/manifests/`.
added docs/API_INTEGRATION.md +41 −0
@@ -0,0 +1,41 @@
1+# API_INTEGRATION.md — how WP39 talks to FinData OS
2+
3+## Authorization
4+- Header `Authorization: Bearer <key>`; the key is read from `FINDATA_API_KEY` or the file `FINDATA_API_KEY_FILE`
5+ (default `~/findata-secrets/api-key-wp39.txt`, mode 600). The client never logs headers, never puts the key in a URL,
6+ and redacts any string starting with `fd_` in exceptions (`src/wp39/api_client.py::_redact`).
7+- Dedicated key `wp39_uqo` (scopes `read:market, read:fundamentals, query, export`; **no admin**), created 2026-11-02 with
8+ the node CLI `findata create-key` because `POST /admin/keys` returned HTTP 500 for API-key callers (bug logged in
9+ DATA_AUDIT §8).
10+- Compute runs on **M3U96a** against `http://127.0.0.1:8600/api/v1` (same host as the lake; the public URL
11+ `https://findata.spboucher.ai/api/v1` is used from the laptop for probes only).
12+
13+## Client (`src/wp39/api_client.py`)
14+- `httpx.Client` with 60 s timeout, retry with bounded exponential backoff (5 attempts, 0.5 → 8 s, jitter) on 429/5xx and
15+ network errors; idempotent GETs only are retried automatically; export creation is retried only when no export id was
16+ received.
17+- Every response's `X-Request-ID`, `X-Dataset-Id`, `X-Dataset-Version` are recorded in the provenance log
18+ (`artifacts/logs/api_calls.jsonl`, one line per call, no payloads).
19+- Cursor iteration for `/market/bars` and `/coverage/symbols`; export polling (`/exports/{id}`) every 1 s up to 10 min.
20+- Arrow/Parquet schema validation against `GET /catalog/schema/bars` (schema v1) before any file is accepted.
21+
22+## Calls used by the pipeline
23+| Step | Call | Scope | Volume |
24+|---|---|---|---|
25+| 00 probe | `/health`, `/catalog/datasets`, `/catalog/schema/bars`, `/openapi.json` | read | 4 |
26+| 01 universe | `/coverage/symbols?dataset_id=market_bars.stock.1m.raw` (cursor, 5,000/page), `/instruments/{symbol}` | read | ≈ 4 + N |
27+| 02 PIT panel | `/fundamentals/{entity}?period_type=q&limit=20000` (all facts, local as-of join), `/fundamentals/{entity}/periods` | read:fundamentals | 2 × N entities |
28+| 03 features | `POST /exports` (1m raw, ≤ 12 y, 1 symbol) ×2 per symbol, `/exports/{id}`, `/download`; SPY from `market_bars.etf.1m.raw` | export | 2 × N + 2 |
29+| checks | `POST /query` (cross-section counts, spot checks ≤ 100 k rows) | query | few |
30+
31+Exception (documented): earnings-release rows are extracted once on M3U96a with
32+`psql -d findata -c "\copy (select ... from earnings_events) to '…'"` (read-only). The extract's SHA-256, row count and
33+timestamp are in `artifacts/manifests/earnings_events.json`.
34+
35+## Idempotent partitioning and manifests
36+- Exports are cached per `(symbol, chunk)` as `$WP39_CACHE/bars/<symbol>__<start>__<end>.parquet` and deleted after the
37+ feature rows are written; `artifacts/manifests/bars_manifest.jsonl` keeps `symbol, start, end, dataset_id,
38+ dataset_version, row_count, bytes, sha256, exported_at, request_id`.
39+- Fundamentals extracts: `$WP39_CACHE/fundamentals/<entity>.parquet` with the same manifest fields.
40+- Re-running a script skips completed partitions (manifest lookup) and never overwrites a partition with a different
41+ dataset version without logging a `version_drift` warning.
added docs/COMPUTE_BUDGET.md +16 −0
@@ -0,0 +1,16 @@
1+# COMPUTE_BUDGET.md
2+
3+| Resource | Plan | Measured / status |
4+|---|---|---|
5+| Compute node | M3U96a (Mac Studio M3 Ultra, 28 cores, 96 GB RAM) — FinData API on localhost | load 1.5–1.9 before start |
6+| Scratch | `~/wp39-cache` on the internal SSD (319 GB free; FinData hard floor 60 GB) | streaming design keeps < 5 GB |
7+| API exports | ≈ 2 × 4,300 symbol-chunks, ≈ 1 s each server-side, 4 concurrent | pilot measured 1.0 s / 860 k rows |
8+| Fundamentals calls | 5,451 × 2 | ms each |
9+| Feature computation | Polars per symbol (≈ 1.7 M rows → 4 frequency tables), 8 worker processes | to be measured in the pilot |
10+| Models | logistic ridge (seconds) ; LightGBM 24 trials × 5 information sets × (1 chronological + 11 walk-forward folds) ≈ 1,440 fits, early stopping; ≈ 2–4 h on 28 cores | — |
11+| Bootstrap | 1,000 stationary-bootstrap draws over 23 test quarters per contrast — seconds | — |
12+| LaTeX | laptop (TeX Live, `latexmk`) | available |
13+| AI usage | none in the pipeline (no LLM features, no neural B7/B8); Claude Code used only as the engineer | owner instruction 2026-11-02 |
14+
15+Pilot (Phase 2 gate): 300 firms stratified by first-fundamentals year and size, full history → validates throughput,
16+feature sanity and label base rates before the full run.
added docs/NOVELTY_MEMO.md +53 −0
@@ -0,0 +1,53 @@
1+# NOVELTY_MEMO.md — the three closest papers and why WP39 is not them
2+
3+Prepared 2026-11-02 from publisher metadata verified on Crossref (`literature/RELATED_WORK_MATRIX.csv`,
4+`artifacts/logs/crossref_batch*.json`). Full texts were not machine-summarised; the points of distinction below are
5+based on the papers' stated designs as reported in their abstracts and our own reading of their published versions.
6+
7+## Closest paper 1 — Grégoire & Martineau (2022), *How Is Earnings News Transmitted to Stock Prices?*, JAR 60(1)
8+- **What it does.** Decomposes price discovery around earnings announcements using TAQ quotes *and* trades, showing that
9+ most of the reaction to after-hours announcements occurs in quotes with little trading.
10+- **Strongest objection to WP39 from this paper.** "Information arrives at the announcement; what you call anticipation is
11+ the pre-announcement drift already documented, and bars cannot even see quotes."
12+- **How WP39 differs.** WP39 does not study the announcement reaction at all: all features end strictly *before* the
13+ release and the outcome is the accounting number itself, not the return. We make no claim about quotes versus trades
14+ (our data are OHLCV bars, stated plainly) and we ask a forecasting question — whether the *resolution* of pre-release
15+ bar data carries incremental information about fundamentals — which their event-window decomposition does not address.
16+
17+## Closest paper 2 — Chen, Cho, Dou & Lev (2022), *Predicting Future Earnings Changes Using Machine Learning and Detailed Financial Data*, JAR 60(2)
18+- **What it does.** Shows that gradient-boosted trees on detailed XBRL financial-statement items predict the direction of
19+ next-year earnings changes better than parsimonious accounting models, and that the predictions are priced slowly.
20+- **Strongest objection.** "Fundamentals-based ML already predicts earnings changes; adding market data is Ou–Penman with
21+ a new model, and daily returns are known to lead earnings (Beaver–Lambert–Morse 1980; Kothari–Sloan 1992)."
22+- **How WP39 differs.** Their inputs are accounting items; ours hold the accounting information set fixed (B1) and
23+ measure the *marginal* value of market data at four sampling frequencies with equal model capacity (B2–B5, B6). The
24+ stock-prices-lead-earnings literature establishes the daily/annual lead; WP39 tests whether anything remains at the
25+ minute scale once daily information is in, with a strict PIT availability clock and a release-date reveal clock.
26+
27+## Closest paper 3 — Zhang, Zhang, Cucuringu & Qian (2023/2024), *Volatility Forecasting with Machine Learning and Intraday Commonality*, JFEC
28+- **What it does.** Pools intraday realized-volatility features across many stocks to forecast volatility with ML, showing
29+ that commonality in intraday patterns improves volatility forecasts.
30+- **Strongest objection.** "Intraday features forecast volatility, and earnings surprises are volatility events, so your
31+ deterioration signal is a volatility forecast in disguise."
32+- **How WP39 differs.** Our target is an accounting quantity with a *sign* (adverse surprise), not a variance; the design
33+ includes the volatility families explicitly in every frequency set so that the test isolates information beyond
34+ predicted volatility (placebo: a symmetric |surprise| target must show the pattern a volatility channel implies, a signed
35+ target must not). We also report directional asymmetry (negative semivariance, down-bar volume) as pre-specified
36+ mechanism variables, not as the headline.
37+
38+## Other adjacent work and the recycling check
39+- UQO WP15 (*Faster, Wider, More Fragile?*) studies intraday *shock propagation* across stocks on the same vendor data;
40+ it never links bars to accounting outcomes. WP39 shares the data vendor and the realized-measure toolkit only; no
41+ result or figure is reused.
42+- Pre-announcement informed trading (Christophe–Ferri–Angel 2004; Berkman et al. 2009; Kaniel et al. 2012;
43+ Hendershott–Livdan–Schürhoff 2015) uses trader-type data we do not have; our contribution is orthogonal: whether
44+ *anonymous* OHLCV at fine resolution is informative, and whether the information is attributable to the frequency.
45+- Patton & Verardo (2012) and Bollerslev–Li–Xue (2018) model announcement-day betas and volume-volatility; they are
46+ announcement-window studies.
47+- Earnings-prediction ML (Easton et al. 2024; Cao et al. 2024) uses accounting, analyst and text inputs, not intraday bars.
48+
49+## Verdict
50+No published paper, to our verified knowledge, measures the marginal forecasting value of 1-minute versus 5-, 30-minute
51+and daily OHLCV for *forthcoming accounting deterioration* with a point-in-time information set and matched model
52+capacity. The question is therefore open. If the empirical answer is a precise null, that is itself informative given
53+the practitioner belief that high-frequency activity "sees" fundamentals early.
added docs/PIT_PROTOCOL.md +75 −0
@@ -0,0 +1,75 @@
1+# PIT_PROTOCOL.md — point-in-time rules for WP39
2+
3+Frozen 2026-11-02 before any model was estimated. Any change is an amendment logged in `DECISIONS.md`.
4+
5+## 1. Clocks
6+
7+All instants are converted to **America/New_York** for session logic and kept in UTC in storage. Trading days follow the
8+XNYS calendar (`exchange_calendars`). For firm `i` and fiscal quarter `q`:
9+
10+| Symbol | Meaning | Source |
11+|---|---|---|
12+| `E_q` | fiscal period end | `fundamentals_facts.fiscal_period_end` |
13+| `A_q` | earnings-release date (press release) — the **reveal date** of quarter-`q` results | `earnings_events.event_date`, first event in `[E_q, F_q + 10 d]` |
14+| `τ_q` | release timing: `before_open`, `after_close`, or `unknown` | `earnings_events.release_time` |
15+| `F_q` | SEC filing date of the 10-Q/10-K | `fundamentals_facts.filing_date` |
16+| `V_q` | vendor-proxy availability of the structured facts | `available_at = F_q + 1 d 00:00 ET` |
17+| `c` | prediction cutoff (a trading day; features use information up to the **close** of `c`) | design |
18+
19+## 2. The information set at cutoff `c`
20+
21+`I(c)` contains exactly:
22+
23+1. **Market bars** with `session_date ≤ c` (regular session 09:30–16:00 ET for the main specification; the 16:00 bar is the
24+ closing print; extended hours 04:00–09:29 and 16:01–19:59 enter only the "extended" variants, never mixed).
25+2. **Fundamentals** with `available_at ≤ c 00:00 ET`, i.e. `F_j + 1 ≤ c`. The latest such quarter is `j*(c)`, and the
26+ model also receives the *age* `c − A_{j*}` in trading days. Because `V_q > F_q ≥ A_q > c` by construction (§3), quarter-`q`
27+ facts can never enter `I(c)`.
28+3. **Earnings-release history** with `event_date < c` (prior realized releases, used for the historical base-rate feature B0).
29+4. **Static crosswalk** (CIK, SIC) — time-invariant by assumption; `formerNames` are checked for ticker reuse (Phase 2 audit).
30+5. **Nothing else.** No consensus estimates for quarter `q` (vintage unknown), no index-membership backfills, no
31+ contemporaneous factors.
32+
33+## 3. Cutoff rules
34+
35+- **Event-time design** (primary, H1–H4): for horizon `h ∈ {40, 20, 10, 5, 1}` trading days, `c = A_q − h` trading days.
36+ Admissible only if `c < min(A_q, F_q)` *and* `c ≥ A_{q−1} + 1` (the previous release has already happened, so the
37+ cohort window never straddles two reveals). With `τ_q = before_open`, bars of `A_q` contain the reaction and are excluded
38+ (`c ≤ A_q − 1` guarantees it); with `τ_q = after_close` or `unknown` the same rule applies — we never use `A_q` bars.
39+- **Fixed-calendar design** (H1 robustness, H5): `c` = last trading day of each month; the target is the *next* release
40+ after `c` (first `A_q > c`), restricted to `A_q − c ≤ 65` trading days. The identity of "the next quarter" is known ex
41+ ante; its date is not needed by the forecaster.
42+- **Firm-quarter exclusions** (frozen): no matched release; `F_q < A_q`; `F_q − A_q > 30` calendar days; `E_q` not within
43+ 60–120 days of `E_{q−1}` (irregular fiscal calendars); quarter `q − 4` or `q − 1` not available at `c` (expectation
44+ undefined); raw close at `c` < 1 USD; fewer than 15 valid sessions in the 20-day feature window.
45+
46+## 4. Label construction (no price-based labels)
47+
48+Primary: `S_q = (X_q − E_c[X_q]) / TA_{j*}`, `X = op_inc` (quarterly operating income), `TA` = total assets of the latest
49+available quarter, `E_c[X_q] = X_{q−4} + (1/4) Σ_{k=0..3} (X_{q−1−k} − X_{q−5−k})` using only quarters available at `c`
50+(seasonal random walk with drift; Foster 1977). `D_q = 1[S_q ≤ −0.005]`. The secondary targets are in
51+`configs/research.yaml`. `X_q` itself is taken from the **first ingested revision** of quarter `q` (the only one available),
52+which is the vendor's current value — see LIMITATIONS §PIT.
53+
54+## 5. Leakage battery (each item is a unit test in `tests/`)
55+
56+| # | Risk | Guard | Test |
57+|---|---|---|---|
58+| L1 | quarter-`q` facts used as inputs | as-of join on `available_at ≤ c` | `test_pit_leakage.py::test_no_future_fundamentals` |
59+| L2 | selection by fiscal end instead of availability | join key is `available_at`, never `fiscal_period_end` | `test_pit_leakage.py::test_join_key_is_available_at` |
60+| L3 | post-release bars in the feature window | `session_date ≤ c < A_q` | `test_pit_leakage.py::test_no_bars_after_cutoff` |
61+| L4 | global standardisation / imputation / tuning on test data | transformers fit on train rows only; tuning on validation period only | `test_train_only_transforms.py` |
62+| L5 | DST / timezone errors | UTC → ET conversion, 09:30 and 16:00 bars identified on both DST regimes | `test_timestamp_dsts.py` |
63+| L6 | ticker reuse / identifier drift | crosswalk with effective dates; SEC `formerNames` audit | `test_instrument_ids.py` |
64+| L7 | splits/dividends creating mechanical returns | split-adjusted returns from `corporate_actions` (ex-date rule), raw bars immutable | `test_corporate_actions.py` |
65+| L8 | release timing assumed intraday | release-day bars never used; timing enters only as a descriptive variable | `test_labels.py::test_release_day_excluded` |
66+| L9 | overlapping target windows across splits | purge + 1-quarter embargo at every split boundary | `test_splits.py` |
67+| L10 | survivorship by construction | universe = all fundamentals entities (documented survivor conditioning), delisted bars kept where present | `01_audit_universe.py` report |
68+| L11 | vendor ingestion date mistaken for knowledge date | `observed_at` is never used as a knowledge date; `available_at` only | `test_pit_leakage.py::test_observed_at_not_used` |
69+| L12 | randomised placebo | labels shuffled within calendar quarter → gain must vanish; cutoffs shifted −45 td → H4 gain must vanish | `08_run_robustness.py` |
70+
71+## 6. Equivalence check of the local as-of join with the API
72+
73+For 25 random entities and 10 random `as_of` instants, the set of (metric, period) pairs returned by
74+`GET /fundamentals/{entity}?as_of=` must equal the set produced by the local filter `available_at ≤ as_of` on the full
75+extract. Implemented in `tests/test_api_contract.py::test_asof_equivalence` (live test, `WP39_LIVE=1`).
added docs/REPLICATION.md +38 −0
@@ -0,0 +1,38 @@
1+# REPLICATION.md — how to reproduce WP39
2+
3+## Requirements
4+- Python ≥ 3.12 with `uv` (`uv venv -p 3.12 .venv && uv pip install -e ".[dev]"`).
5+- Access to FinData OS (owner-issued key with scopes `read:market, read:fundamentals, query, export`) exposed as
6+ `FINDATA_API_KEY` or a mode-600 file at `FINDATA_API_KEY_FILE`. Without access, Phases 2–5 cannot run; the saved
7+ evaluation artifacts in `artifacts/evaluation/` and `results/` allow Phase 6 (tables/figures/paper) to be regenerated.
8+- Read-only `psql` access to the FinData Postgres database on the storage node for `scripts/01a_extract_node_tables.sh`
9+ (earnings events, entities, corporate actions — not yet exposed by the API).
10+- Internet access to `sec.gov` (CIK/SIC) and the Kenneth French library (daily factors).
11+- TeX Live with `latexmk` for the paper.
12+
13+## Order of execution (compute node, API on localhost)
14+```bash
15+export FINDATA_BASE_URL=http://127.0.0.1:8600/api/v1 WP39_CACHE=~/wp39-cache
16+bash scripts/01a_extract_node_tables.sh # node extracts + manifests
17+python scripts/00_probe_findata.py # contract reconciliation -> artifacts/logs/phase0_probe.json
18+python scripts/01_audit_universe.py # universe.parquet, results/universe_audit.json
19+python scripts/02_build_pit_panel.py # quarters.parquet (labels), design freeze hash
20+python scripts/03_build_features.py --workers 8 # streaming exports -> session features -> rolling windows
21+python scripts/04_build_labels.py # sample_event.parquet, sample_calendar.parquet, cascades
22+python scripts/05_train_baselines.py # B0-B5 logistic, ridge, firm hold-out, walk-forward
23+python scripts/06_train_advanced.py # LightGBM equal-budget, horizon ladder, OOF signals
24+python scripts/07_evaluate.py # metrics, paired contrasts, GW tests, Holm, power
25+python scripts/08_run_robustness.py # placebos, subgroups, panel regressions, H5
26+python scripts/09_make_manuscript.py # tables, figures, results_macros.tex
27+cd paper && make # main.pdf
28+pytest -q # 29 tests; WP39_LIVE=1 adds the live API contract tests
29+```
30+Runtime on a Mac Studio M3 Ultra (28 cores): see `PROGRESS.md` for measured wall-times of each step.
31+
32+## What is and is not in the package
33+- In: code, configs, docs, tests, manifests (hashes/versions/counts), derived evaluation tables, figures, paper.
34+- Out: raw bars and fundamentals (FirstRate Data license), the per-symbol feature cache (derived from licensed data;
35+ regenerable), model binaries.
36+- Determinism: all seeds come from `configs/research.yaml` (`seed: 20261102`); LightGBM uses `n_jobs=12` with
37+ deterministic histogram construction at the default settings, so results are reproducible to numerical precision on
38+ the same architecture.
added docs/RESEARCH_DESIGN.md +111 −0
@@ -0,0 +1,111 @@
1+# RESEARCH_DESIGN.md — preregistered specification (internal)
2+
3+Frozen **2026-11-02 14:40 ET**, before the first test-period observation was opened. Hash of this file at freeze is
4+recorded in `artifacts/manifests/design_freeze.json` by `scripts/02_build_pit_panel.py`. Later changes are amendments in
5+`DECISIONS.md` (dated, with reason) and never alter frozen primary endpoints.
6+
7+## 1. Question
8+
9+Does one-minute OHLCV activity contain **incremental** information about a firm's *forthcoming* adverse accounting
10+outcome, beyond (i) point-in-time fundamentals, (ii) daily OHLCV, (iii) coarser intraday aggregates of the same bars, and
11+(iv) calendar/industry/size controls? Anticipation (prices move before the release) is not the claim; the claim is about
12+the marginal forecasting value of **sampling frequency** holding the information set, calendar coverage, universe,
13+cutoff, horizon and training budget fixed.
14+
15+## 2. Hypotheses — null, alternative, primary endpoint, decision rule
16+
17+| | Null `H0` | Alternative `H1` | Primary endpoint | Decision rule |
18+|---|---|---|---|---|
19+| **H1** incremental information | OOS log loss of B5 (fundamentals + daily + 1m) ≥ that of B2 (fundamentals + daily) | B5 < B2 | Δ log loss (B5 − B2) on the untouched test period, 2021-01 → 2026-10, horizon h = 20 | 95 % block-bootstrap CI (blocks = calendar quarters, 1,000 draws) excludes 0 **and** Giacomini–White conditional test p < 0.05 (two-sided) |
20+| **H2** temporal resolution | Δ(B5 − B2) ≤ Δ(B4 − B2) and ≤ Δ(B3 − B2) | 1m gain strictly exceeds 5m and 30m gains | paired Δ log loss B5 − B4 and B5 − B3 | both CIs exclude 0 after Holm correction over the 3 frequency contrasts |
21+| **H3** heterogeneity | the B5 − B2 gain is equal across terciles of size, illiquidity, leverage | gain larger in small, illiquid, levered firms | interaction coefficient `β_HF×tercile` in the panel regression (§5) | Holm-corrected p < 0.05 for the pre-specified ordering |
22+| **H4** timing | the B5 − B2 gain does not increase as h shrinks (40→20→10→5→1) | monotone increase | slope of Δ log loss on −h across horizons | sign test on the five ordered horizons + placebo cutoffs (−45 td) showing no gain |
23+| **H5** pricing | the LFDS does not predict the announcement-window abnormal return nor post-cutoff factor-adjusted returns | it does | (a) regression of CAR[c+1, A_q+1] on LFDS with controls; (b) decile long-short FF5+MOM alpha with costs | CI excludes 0; economic value reported with turnover and costs regardless of significance |
24+
25+Primary endpoint for the headline sentence: **H1 at h = 20 on the binary primary target** with log loss. Brier, AUC,
26+PR-AUC, calibration slope/intercept, MAE/RMSE/OOS-R² (continuous target) are secondary metrics reported for every model.
27+The headline sentence will read: *"At a 20-trading-day horizon, on a 2012–2026 panel of U.S. listed firms with a strictly
28+point-in-time information set, one-minute OHLCV features change the out-of-sample log loss of forecasts of an adverse
29+operating-income surprise by [Δ, 95 % CI] relative to a daily-market-and-accounting benchmark; the gain is
30+[consistent/inconsistent] with [mechanisms] and has [measured/absent] economic value."*
31+
32+## 3. Sample
33+
34+Universe: all FinData fundamentals entities (5,451; survivor-conditioned, see LIMITATIONS) with ≥ 8 quarterly periods
35+and 1-minute bars; firm-quarters 2012-Q1 → 2026-Q2 with reveal dates ≤ 2026-10-30 and admissible cutoffs (PIT_PROTOCOL
36+§3). Sector = SEC SIC division (2-digit), size = log market cap at `c` (raw close × latest available `shares`).
37+
38+Expected sample (to be reported, not assumed): ~4,300 firms × ~40 quarters ≈ 150–170 k firm-quarters before exclusions.
39+
40+## 4. Variables
41+
42+**Targets** — `configs/research.yaml`. Primary binary `D_q = 1[S_q ≤ −0.5 % of assets]`, primary continuous `S_q`
43+(winsorised at 1/99 % on the training period).
44+
45+**PIT fundamentals (B1)** — latest available quarter at `c`: `rev` growth (yoy), gross margin `gp/rev`, operating margin
46+`op_inc/rev`, `roa`, `net_inc/assets_tot`, `cash_op/assets_tot`, accruals `(net_inc − cash_op)/assets_tot`,
47+`cash/assets_tot`, leverage `debt/assets_tot`, interest coverage `intr_cover` (clipped), current ratio `assets_c/liab_c`,
48+net issuance (Δ`shares` yoy), capex/assets, R&D/rev, `S_{j*}` (last surprise), last-four-quarter surprise mean, loss
49+indicator, log assets, log market cap, information age `c − A_{j*}`, fiscal-quarter dummies, sector dummies, year-quarter
50+calendar dummies (in-sample only; for prediction, calendar effects are replaced by the trailing cross-sectional base rate).
51+
52+**Daily OHLCV (B2)** — from 1m regular-session bars aggregated to daily: 20- and 60-day cumulative split-adjusted returns,
53+daily return volatility (20d), Parkinson range volatility, skewness and kurtosis of daily returns (60d), daily volume
54+relative to 60-day median (20d mean and last 5d), Amihud illiquidity (60d), share of zero-return days, overnight
55+(close-to-open) vs intraday (open-to-close) return decomposition (20d sums), max drawdown (60d), beta and residual
56+volatility against SPY (60d daily).
57+
58+**Intraday families (B3 = 30m, B4 = 5m, B5 = 1m)** — the *same* families computed on bars of the given length,
59+each aggregated per session then averaged (or summed) over the 20-day window:
60+realized variance (RV), bipower variation (BPV), relative jump `max(0, RV − BPV)/RV`, negative semivariance share
61+`RS⁻/RV`, signed-jump variation `(RS⁺ − RS⁻)/RV`, realized skewness and kurtosis, maximum absolute bar-return share
62+of RV (concentration), first-order autocorrelation of bar returns, variance ratio `RV_freq / RV_daily`, intraday drift
63+`(close − open)/open`, time-of-day volume profile (share of volume in the first and last 30 minutes), volume dispersion
64+across bars (Gini), down-bar volume share (volume on bars with negative return / total — *a bar statistic, not order
65+flow*), volume surprise relative to the firm's 60-day time-of-day seasonal profile, fraction of bars present (activity),
66+RV on market-down bars vs market-up bars (asymmetry vs SPY), realized beta to SPY at that frequency, vol-of-vol
67+(dispersion of daily RV within the window). At 30m the within-day counts are small (13 bars), so skewness/kurtosis and
68+autocorrelation are computed on the pooled window.
69+
70+Note on frequency comparison: B3/B4/B5 have the **same number of feature columns** (one per family); dimensionality does
71+not grow with frequency. A supplementary experiment (Phase 4) concatenates all three to test whether 1m dominates when
72+coarser aggregates are also present.
73+
74+## 5. Models and inference
75+
76+Baseline ladder B0–B6 (`configs/models.yaml`). Logistic ridge for B1–B5 with `C` tuned on the validation period only;
77+LightGBM with an identical random-search budget (24 trials, early stopping on validation) for every information set.
78+B7/B8 (temporal neural, text) are **not run** (owner instruction to minimise AI use; declared in DECISIONS D-006).
79+
80+Panel regression for interpretability and H3:
81+`S_{i,q} = α_i + δ_{s(i),t(q)} + β·LFDS_{i,c} + γ'X_{i,c} + ε_{i,q}`, where `LFDS` is the B5 out-of-fold predicted
82+probability (walk-forward, so it is never fitted on the same quarter), with firm fixed effects and sector×year-quarter
83+effects, two-way clustered SEs (firm, calendar quarter). H3 interactions use ex-ante terciles formed at `c`.
84+
85+Comparisons: Diebold–Mariano / Giacomini–White on per-quarter mean loss differentials with HAC; stationary block
86+bootstrap over calendar quarters for paired CIs; Holm within each hypothesis family; model confidence set over the ladder
87+as a supplementary exhibit.
88+
89+## 6. Validation protocol
90+
91+- Chronological: train 2012-01 → 2018-12, validation 2019-01 → 2020-12, test 2021-01 → 2026-10 (never opened until Phase 3
92+ gate). Purge: training observations whose `A_q` falls after the validation start minus one quarter are dropped
93+ (embargo = 1 calendar quarter) and likewise at the test boundary.
94+- Walk-forward: expanding window, annual refits, first test year 2016, 1-quarter embargo; this provides the out-of-fold
95+ LFDS for the panel regressions and the H4/H5 exercises.
96+- Firm hold-out: 20 % of firms (hash of entity id) never seen in training, evaluated separately from the time hold-out.
97+- Train-only transforms: winsorisation bounds, medians for imputation, standardisation, sector-time demeaning, tercile
98+ cut-points — all computed on the training rows of the current fold.
99+
100+## 7. Power
101+
102+With ≈ 40 k test firm-quarters, base rate ≈ 20–30 %, and quarter-level clustering (23 test quarters), the minimum
103+detectable paired Δ log loss is roughly 0.002–0.004 (to be computed from the validation-period variance of the loss
104+differential and reported in `artifacts/evaluation/power.json` before the test set is opened).
105+
106+## 8. What would make us abandon or pivot
107+
108+If, on the validation period, B2 already captures all of B5 (Δ within ±0.001 and CI covering 0), H1 is likely null; we
109+proceed to the test anyway (a precise null is a result) and devote Phase 5 to characterising *where* intraday information
110+does and does not help. If the earnings-release matching proves unreliable (> 10 % irregular lags after cleaning), the
111+event-time design is demoted and the fixed-calendar design becomes primary (amendment required).
added literature/RELATED_WORK_MATRIX.csv +25 −0
@@ -0,0 +1,25 @@
1+key,authors,year,journal,doi_or_url,data_source,frequency,sample,research_question,identification,findings,point_of_distinction_for_WP39
2+gregoire2022,Grégoire & Martineau,2022,Journal of Accounting Research,10.1111/1475-679X.12394,TAQ quotes and trades,intraday (quotes/trades),US earnings announcements,How is earnings news incorporated into prices?,event-window decomposition of price discovery,most price discovery for after-hours announcements occurs through quote updates with little trading,"WP39 uses only pre-release bars, forecasts the accounting outcome (not the return), never claims quote/trade mechanisms"
3+chen2022,Chen; Cho; Dou; Lev,2022,Journal of Accounting Research,10.1111/1475-679X.12429,XBRL detailed financial statement items,annual,US firms,Can ML on detailed financials predict earnings changes?,OOS prediction + return tests,boosted trees beat parsimonious models; slow pricing,"WP39 holds accounting inputs fixed and measures the marginal value of market data by sampling frequency"
4+zhang2023volatility,Zhang; Zhang; Cucuringu; Qian,2024,Journal of Financial Econometrics,10.1093/jjfinec/nbad005,intraday equity returns,intraday,US stocks,Does pooling intraday commonality improve ML volatility forecasts?,OOS forecasting,commonality improves volatility forecasts,"WP39 targets a signed accounting quantity, includes volatility families as controls, uses a signed vs absolute placebo"
5+beaver1980,Beaver; Lambert; Morse,1980,Journal of Accounting and Economics,10.1016/0165-4101(80)90013-0,CRSP/Compustat,annual,US,Do prices contain information about future earnings?,regression of earnings changes on returns,prices lead earnings,"establishes the daily/annual lead; WP39 asks what remains at minute resolution"
6+kothari1992,Kothari & Sloan,1992,Journal of Accounting and Economics,10.1016/0165-4101(92)90016-U,CRSP/Compustat,annual,US,Information in prices about future earnings (ERC),leading returns,ERCs rise with leading returns,"same"
7+collins1994,Collins; Kothari; Shanken; Sloan,1994,Journal of Accounting and Economics,10.1016/0165-4101(94)90024-8,CRSP/Compustat,annual,US,Why is the contemporaneous return-earnings association low?,lack of timeliness vs noise,prices anticipate earnings several years ahead,"same"
8+foster1977,Foster,1977,The Accounting Review,10.2308/tar-4493420,quarterly earnings,quarterly,US,Time-series properties of quarterly earnings,forecast evaluation,seasonal random walk with drift forecasts well,"WP39's expectation model for the surprise"
9+bernard1989,Bernard & Thomas,1989,Journal of Accounting Research,10.2307/2491062,CRSP/Compustat,daily,US,Post-earnings-announcement drift,event study,drift after SUE,"WP39 studies pre-release information, not post-announcement drift"
10+ou1989,Ou & Penman,1989,Journal of Accounting and Economics,10.1016/0165-4101(89)90017-7,Compustat,annual,US,Can financial statement analysis predict earnings and returns?,logit on ratios,yes,"WP39 B1 baseline follows this tradition"
11+sloan1996,Sloan,1996,The Accounting Review,10.2308/tar-9608042309,Compustat/CRSP,annual,US,Do prices reflect accruals information?,hedge portfolio,accrual anomaly,"accruals are a B1 control"
12+christophe2004,Christophe; Ferri; Angel,2004,Journal of Finance,10.1111/j.1540-6261.2004.00681.x,Nasdaq short sales,daily,US,Do short sellers anticipate earnings news?,pre-announcement short selling,yes,"trader-type data unavailable to WP39; WP39 tests anonymous OHLCV"
13+berkman2009,Berkman; Dimitrov; Jain; Koch; Tice,2009,Journal of Financial Economics,10.1016/j.jfineco.2008.04.009,CRSP/IBES,daily,US,Differences of opinion and returns around announcements,event study,prices fall around announcements for high-disagreement stocks,"announcement-window return study"
14+kaniel2012,Kaniel; Liu; Saar; Titman,2012,Journal of Finance,10.1111/j.1540-6261.2012.01727.x,NYSE CAUD individual trades,daily,US,Do individual investors trade informatively before earnings?,pre-event trading,yes partly,"trader-type data"
15+hendershott2015,Hendershott; Livdan; Schürhoff,2015,Journal of Financial Economics,10.1016/j.jfineco.2015.03.007,institutional order flow,daily,US,Are institutions informed about news?,order flow before news,yes,"order flow unavailable; WP39 never labels bar statistics as order flow"
16+patton2012,Patton & Verardo,2012,Review of Financial Studies,10.1093/rfs/hhs073,TAQ,intraday,US,Does beta move with news?,announcement-day realized beta,beta rises on announcement days,"announcement-day study"
17+bollerslev2018volume,Bollerslev; Li; Xue,2018,Review of Economic Studies,10.1093/restud/rdy003,TAQ,intraday,US,Volume-volatility relation around public news,structural model,announcement effects on volume-volatility elasticity,"announcement-window study"
18+weller2018,Weller,2018,Review of Financial Studies,10.1093/rfs/hhx137,TAQ + earnings,daily/intraday,US,Does algorithmic trading reduce information acquisition?,AT and pre-announcement price informativeness,AT reduces pre-announcement price informativeness,"closest mechanism paper: WP39 reports pre-release information by era as a mechanism exhibit"
19+lee2012,Lee,2012,Review of Financial Studies,10.1093/rfs/hhr084,TAQ,intraday,US,Jumps and information flow,jump tests around news,jumps cluster at news,"jump proxies are WP39 features"
20+easton2024,Easton; Kapons; Monahan; Schütt; Weisbrod,2024,The Accounting Review,10.2308/tar-2021-0478,Compustat,annual,US,Forecast earnings with k-NN,OOS forecasting,kNN competitive with analysts,"accounting inputs only"
21+cao2024,Cao; Jiang; Wang; Yang,2024,Journal of Financial Economics,10.1016/j.jfineco.2024.103910,analyst + ML,monthly,US,Man vs machine in stock analysis,OOS forecasts,AI complements analysts,"no intraday data"
22+gu2020,Gu; Kelly; Xiu,2020,Review of Financial Studies,10.1093/rfs/hhaa009,CRSP/Compustat characteristics,monthly,US,ML for return prediction,OOS R2,trees and NNs best,"methodological reference for equal-budget comparisons"
23+giacomini2006,Giacomini & White,2006,Econometrica,10.1111/j.1468-0262.2006.00718.x,—,—,—,Conditional predictive ability tests,—,—,"inference for H1/H2"
24+liu2015,Liu; Patton; Sheppard,2015,Journal of Econometrics,10.1016/j.jeconom.2015.02.008,TAQ,intraday,multi-asset,Does anything beat 5-minute RV?,forecast comparison,5-min RV hard to beat,"frequency comparison for variance measurement; WP39 asks the analogous question for fundamentals"
25+boucher2026wp15,Boucher,2026,UQO Working Paper 15,—,FirstRate Data 1-minute bars,1-minute,US 1992-2026,Intraday shock propagation,event studies,shocks propagate narrowly,"same vendor; different question; nothing reused"
added literature/references.bib +1021 −0
@@ -0,0 +1,1021 @@
1+% WP39 UQO bibliography. Journal metadata verified on Crossref 2026-11-02 (artifacts/logs/crossref_batch*.json).
2+
3+@article{gregoire2022,
4+ author = {Grégoire, Vincent and Martineau, Charles},
5+ title = {{How is Earnings News Transmitted to Stock Prices?}},
6+ journal = {Journal of Accounting Research},
7+ year = {2022},
8+ volume = {60},
9+ number = {1},
10+ pages = {261--297},
11+ doi = {10.1111/1475-679x.12394}
12+}
13+
14+@article{zhang2023volatility,
15+ author = {Zhang, Chao and Zhang, Yihuang and Cucuringu, Mihai and Qian, Zhongmin},
16+ title = {{Volatility Forecasting with Machine Learning and Intraday Commonality}},
17+ journal = {Journal of Financial Econometrics},
18+ year = {2024},
19+ volume = {22},
20+ number = {2},
21+ pages = {492--530},
22+ doi = {10.1093/jjfinec/nbad005}
23+}
24+
25+@article{ball1968,
26+ author = {Ball, Ray and Brown, Philip},
27+ title = {{An Empirical Evaluation of Accounting Income Numbers}},
28+ journal = {Journal of Accounting Research},
29+ year = {1968},
30+ volume = {6},
31+ number = {2},
32+ pages = {159},
33+ doi = {10.2307/2490232}
34+}
35+
36+@article{bernard1989,
37+ author = {Bernard, Victor L. and Thomas, Jacob K.},
38+ title = {{Post-Earnings-Announcement Drift: Delayed Price Response or Risk Premium?}},
39+ journal = {Journal of Accounting Research},
40+ year = {1989},
41+ volume = {27},
42+ pages = {1},
43+ doi = {10.2307/2491062}
44+}
45+
46+@article{bernard1990,
47+ author = {Bernard, Victor L. and Thomas, Jacob K.},
48+ title = {{Evidence that stock prices do not fully reflect the implications of current earnings for future earnings}},
49+ journal = {Journal of Accounting and Economics},
50+ year = {1990},
51+ volume = {13},
52+ number = {4},
53+ pages = {305--340},
54+ doi = {10.1016/0165-4101(90)90008-r}
55+}
56+
57+@article{sloan1996,
58+ author = {Sloan, Richard G.},
59+ title = {{Do Stock Prices Fully Reflect Information in Accruals and Cash Flows About Future Earnings?}},
60+ journal = {The Accounting Review},
61+ year = {1996},
62+ volume = {71},
63+ number = {3},
64+ pages = {289--315},
65+ doi = {10.2308/tar-9608042309}
66+}
67+
68+@article{ou1989,
69+ author = {Ou, Jane A. and Penman, Stephen H.},
70+ title = {{Financial statement analysis and the prediction of stock returns}},
71+ journal = {Journal of Accounting and Economics},
72+ year = {1989},
73+ volume = {11},
74+ number = {4},
75+ pages = {295--329},
76+ doi = {10.1016/0165-4101(89)90017-7}
77+}
78+
79+@article{kyle1985,
80+ author = {Kyle, Albert S.},
81+ title = {{Continuous Auctions and Insider Trading}},
82+ journal = {Econometrica},
83+ year = {1985},
84+ volume = {53},
85+ number = {6},
86+ pages = {1315},
87+ doi = {10.2307/1913210}
88+}
89+
90+@article{easley1987,
91+ author = {Easley, David and O'Hara, Maureen},
92+ title = {{Price, trade size, and information in securities markets}},
93+ journal = {Journal of Financial Economics},
94+ year = {1987},
95+ volume = {19},
96+ number = {1},
97+ pages = {69--90},
98+ doi = {10.1016/0304-405x(87)90029-8}
99+}
100+
101+@article{andersen2003,
102+ author = {Andersen, Torben G. and Bollerslev, Tim and Diebold, Francis X. and Labys, Paul},
103+ title = {{Modeling and Forecasting Realized Volatility}},
104+ journal = {Econometrica},
105+ year = {2003},
106+ volume = {71},
107+ number = {2},
108+ pages = {579--625},
109+ doi = {10.1111/1468-0262.00418}
110+}
111+
112+@article{barndorff2004,
113+ author = {Barndorff-Nielsen, O. E.},
114+ title = {{Power and Bipower Variation with Stochastic Volatility and Jumps}},
115+ journal = {Journal of Financial Econometrics},
116+ year = {2004},
117+ volume = {2},
118+ number = {1},
119+ pages = {1--37},
120+ doi = {10.1093/jjfinec/nbh001}
121+}
122+
123+@article{gu2020,
124+ author = {Gu, Shihao and Kelly, Bryan and Xiu, Dacheng},
125+ title = {{Empirical Asset Pricing via Machine Learning}},
126+ journal = {The Review of Financial Studies},
127+ year = {2020},
128+ volume = {33},
129+ number = {5},
130+ pages = {2223--2273},
131+ doi = {10.1093/rfs/hhaa009}
132+}
133+
134+@article{giacomini2006,
135+ author = {Giacomini, Raffaella and White, Halbert},
136+ title = {{Tests of Conditional Predictive Ability}},
137+ journal = {Econometrica},
138+ year = {2006},
139+ volume = {74},
140+ number = {6},
141+ pages = {1545--1578},
142+ doi = {10.1111/j.1468-0262.2006.00718.x}
143+}
144+
145+@article{diebold1995,
146+ author = {Diebold, Francis X. and Mariano, Roberto S.},
147+ title = {{Comparing Predictive Accuracy}},
148+ journal = {Journal of Business \& Economic Statistics},
149+ year = {1995},
150+ volume = {13},
151+ number = {3},
152+ pages = {253--263},
153+ doi = {10.1080/07350015.1995.10524599}
154+}
155+
156+@article{hansen2005,
157+ author = {Hansen, Peter Reinhard},
158+ title = {{A Test for Superior Predictive Ability}},
159+ journal = {Journal of Business \& Economic Statistics},
160+ year = {2005},
161+ volume = {23},
162+ number = {4},
163+ pages = {365--380},
164+ doi = {10.1198/073500105000000063}
165+}
166+
167+@article{fama2015,
168+ author = {Fama, Eugene F. and French, Kenneth R.},
169+ title = {{A five-factor asset pricing model}},
170+ journal = {Journal of Financial Economics},
171+ year = {2015},
172+ volume = {116},
173+ number = {1},
174+ pages = {1--22},
175+ doi = {10.1016/j.jfineco.2014.10.010}
176+}
177+
178+@article{bollerslev2020good,
179+ author = {Bollerslev, Tim and Li, Sophia Zhengzi and Zhao, Bingzhi},
180+ title = {{Good Volatility, Bad Volatility, and the Cross Section of Stock Returns}},
181+ journal = {Journal of Financial and Quantitative Analysis},
182+ year = {2020},
183+ volume = {55},
184+ number = {3},
185+ pages = {751--781},
186+ doi = {10.1017/s0022109019000097}
187+}
188+
189+@article{patton2015,
190+ author = {Patton, Andrew J. and Sheppard, Kevin},
191+ title = {{Good Volatility, Bad Volatility: Signed Jumps and The Persistence of Volatility}},
192+ journal = {Review of Economics and Statistics},
193+ year = {2015},
194+ volume = {97},
195+ number = {3},
196+ pages = {683--697},
197+ doi = {10.1162/rest_a_00503}
198+}
199+
200+@article{chen2022,
201+ author = {CHEN, XI and CHO, YANG HA (TONY) and DOU, YIWEI and LEV, BARUCH},
202+ title = {{Predicting Future Earnings Changes Using Machine Learning and Detailed Financial Data}},
203+ journal = {Journal of Accounting Research},
204+ year = {2022},
205+ volume = {60},
206+ number = {2},
207+ pages = {467--515},
208+ doi = {10.1111/1475-679x.12429}
209+}
210+
211+@article{piotroski2000,
212+ author = {Piotroski, Joseph D.},
213+ title = {{Value Investing: The Use of Historical Financial Statement Information to Separate Winners from Losers}},
214+ journal = {Journal of Accounting Research},
215+ year = {2000},
216+ volume = {38},
217+ pages = {1},
218+ doi = {10.2307/2672906}
219+}
220+
221+@article{hirshleifer2009,
222+ author = {HIRSHLEIFER, DAVID and LIM, SONYA SEONGYEON and TEOH, SIEW HONG},
223+ title = {{Driven to Distraction: Extraneous Events and Underreaction to Earnings News}},
224+ journal = {The Journal of Finance},
225+ year = {2009},
226+ volume = {64},
227+ number = {5},
228+ pages = {2289--2325},
229+ doi = {10.1111/j.1540-6261.2009.01501.x}
230+}
231+
232+@article{dellavigna2009,
233+ author = {DELLAVIGNA, STEFANO and POLLET, JOSHUA M.},
234+ title = {{Investor Inattention and Friday Earnings Announcements}},
235+ journal = {The Journal of Finance},
236+ year = {2009},
237+ volume = {64},
238+ number = {2},
239+ pages = {709--749},
240+ doi = {10.1111/j.1540-6261.2009.01447.x}
241+}
242+
243+@article{loughran2011,
244+ author = {LOUGHRAN, TIM and MCDONALD, BILL},
245+ title = {{When Is a Liability Not a Liability? Textual Analysis, Dictionaries, and 10-Ks}},
246+ journal = {The Journal of Finance},
247+ year = {2011},
248+ volume = {66},
249+ number = {1},
250+ pages = {35--65},
251+ doi = {10.1111/j.1540-6261.2010.01625.x}
252+}
253+
254+@article{bajgrowicz2016,
255+ author = {Bajgrowicz, Pierre and Scaillet, Olivier and Treccani, Adrien},
256+ title = {{Jumps in High-Frequency Data: Spurious Detections, Dynamics, and News}},
257+ journal = {Management Science},
258+ year = {2016},
259+ volume = {62},
260+ number = {8},
261+ pages = {2198--2217},
262+ doi = {10.1287/mnsc.2015.2234}
263+}
264+
265+@article{lee2008,
266+ author = {Lee, Suzanne S. and Mykland, Per A.},
267+ title = {{Jumps in Financial Markets: A New Nonparametric Test and Jump Dynamics}},
268+ journal = {Review of Financial Studies},
269+ year = {2008},
270+ volume = {21},
271+ number = {6},
272+ pages = {2535--2563},
273+ doi = {10.1093/rfs/hhm056}
274+}
275+
276+@article{bollerslev2018risk,
277+ author = {Bollerslev, Tim and Hood, Benjamin and Huss, John and Pedersen, Lasse Heje},
278+ title = {{Risk Everywhere: Modeling and Managing Volatility}},
279+ journal = {The Review of Financial Studies},
280+ year = {2018},
281+ volume = {31},
282+ number = {7},
283+ pages = {2729--2773},
284+ doi = {10.1093/rfs/hhy041}
285+}
286+
287+@article{hendershott2011,
288+ author = {HENDERSHOTT, TERRENCE and JONES, CHARLES M. and MENKVELD, ALBERT J.},
289+ title = {{Does Algorithmic Trading Improve Liquidity?}},
290+ journal = {The Journal of Finance},
291+ year = {2011},
292+ volume = {66},
293+ number = {1},
294+ pages = {1--33},
295+ doi = {10.1111/j.1540-6261.2010.01624.x}
296+}
297+
298+@article{richardson2005,
299+ author = {Richardson, Scott A. and Sloan, Richard G. and Soliman, Mark T. and Tuna, İrem},
300+ title = {{Accrual reliability, earnings persistence and stock prices}},
301+ journal = {Journal of Accounting and Economics},
302+ year = {2005},
303+ volume = {39},
304+ number = {3},
305+ pages = {437--485},
306+ doi = {10.1016/j.jacceco.2005.04.005}
307+}
308+
309+@article{beneish1999,
310+ author = {Beneish, Messod D.},
311+ title = {{The Detection of Earnings Manipulation}},
312+ journal = {Financial Analysts Journal},
313+ year = {1999},
314+ volume = {55},
315+ number = {5},
316+ pages = {24--36},
317+ doi = {10.2469/faj.v55.n5.2296}
318+}
319+
320+@article{campbell2008,
321+ author = {CAMPBELL, JOHN Y. and HILSCHER, JENS and SZILAGYI, JAN},
322+ title = {{In Search of Distress Risk}},
323+ journal = {The Journal of Finance},
324+ year = {2008},
325+ volume = {63},
326+ number = {6},
327+ pages = {2899--2939},
328+ doi = {10.1111/j.1540-6261.2008.01416.x}
329+}
330+
331+@article{fama1973,
332+ author = {Fama, Eugene F. and MacBeth, James D.},
333+ title = {{Risk, Return, and Equilibrium: Empirical Tests}},
334+ journal = {Journal of Political Economy},
335+ year = {1973},
336+ volume = {81},
337+ number = {3},
338+ pages = {607--636},
339+ doi = {10.1086/260061}
340+}
341+
342+@article{petersen2009,
343+ author = {Petersen, Mitchell A.},
344+ title = {{Estimating Standard Errors in Finance Panel Data Sets: Comparing Approaches}},
345+ journal = {Review of Financial Studies},
346+ year = {2009},
347+ volume = {22},
348+ number = {1},
349+ pages = {435--480},
350+ doi = {10.1093/rfs/hhn053}
351+}
352+
353+@article{cameron2011,
354+ author = {Cameron, A. Colin and Gelbach, Jonah B. and Miller, Douglas L.},
355+ title = {{Robust Inference With Multiway Clustering}},
356+ journal = {Journal of Business \& Economic Statistics},
357+ year = {2011},
358+ volume = {29},
359+ number = {2},
360+ pages = {238--249},
361+ doi = {10.1198/jbes.2010.07136}
362+}
363+
364+@article{novymarx2016,
365+ author = {Novy-Marx, Robert and Velikov, Mihail},
366+ title = {{A Taxonomy of Anomalies and Their Trading Costs}},
367+ journal = {Review of Financial Studies},
368+ year = {2016},
369+ volume = {29},
370+ number = {1},
371+ pages = {104--147},
372+ doi = {10.1093/rfs/hhv063}
373+}
374+
375+@article{bollerslev2016beta,
376+ author = {Bollerslev, Tim and Li, Sophia Zhengzi and Todorov, Viktor},
377+ title = {{Roughing up beta: Continuous versus discontinuous betas and the cross section of expected stock returns}},
378+ journal = {Journal of Financial Economics},
379+ year = {2016},
380+ volume = {120},
381+ number = {3},
382+ pages = {464--490},
383+ doi = {10.1016/j.jfineco.2016.02.001}
384+}
385+
386+@article{lo1988,
387+ author = {Lo, Andrew W. and MacKinlay, A. Craig},
388+ title = {{Stock Market Prices Do Not Follow Random Walks: Evidence from a Simple Specification Test}},
389+ journal = {Review of Financial Studies},
390+ year = {1988},
391+ volume = {1},
392+ number = {1},
393+ pages = {41--66},
394+ doi = {10.1093/rfs/1.1.41}
395+}
396+
397+@article{freyberger2020,
398+ author = {Freyberger, Joachim and Neuhierl, Andreas and Weber, Michael},
399+ title = {{Dissecting Characteristics Nonparametrically}},
400+ journal = {The Review of Financial Studies},
401+ year = {2020},
402+ volume = {33},
403+ number = {5},
404+ pages = {2326--2377},
405+ doi = {10.1093/rfs/hhz123}
406+}
407+
408+@article{bollerslev2016errors,
409+ author = {Bollerslev, Tim and Patton, Andrew J. and Quaedvlieg, Rogier},
410+ title = {{Exploiting the errors: A simple approach for improved volatility forecasting}},
411+ journal = {Journal of Econometrics},
412+ year = {2016},
413+ volume = {192},
414+ number = {1},
415+ pages = {1--18},
416+ doi = {10.1016/j.jeconom.2015.10.007}
417+}
418+
419+@article{liu2015,
420+ author = {Liu, Lily Y. and Patton, Andrew J. and Sheppard, Kevin},
421+ title = {{Does anything beat 5-minute RV? A comparison of realized measures across multiple asset classes}},
422+ journal = {Journal of Econometrics},
423+ year = {2015},
424+ volume = {187},
425+ number = {1},
426+ pages = {293--311},
427+ doi = {10.1016/j.jeconom.2015.02.008}
428+}
429+
430+@article{andersen1998,
431+ author = {Andersen, Torben G. and Bollerslev, Tim},
432+ title = {{Answering the Skeptics: Yes, Standard Volatility Models do Provide Accurate Forecasts}},
433+ journal = {International Economic Review},
434+ year = {1998},
435+ volume = {39},
436+ number = {4},
437+ pages = {885},
438+ doi = {10.2307/2527343}
439+}
440+
441+@article{aboody2010,
442+ author = {Aboody, David and Lehavy, Reuven and Trueman, Brett},
443+ title = {{Limited attention and the earnings announcement returns of past stock market winners}},
444+ journal = {Review of Accounting Studies},
445+ year = {2010},
446+ volume = {15},
447+ number = {2},
448+ pages = {317--344},
449+ doi = {10.1007/s11142-009-9104-9}
450+}
451+
452+@article{kothari2001,
453+ author = {Kothari, S.P},
454+ title = {{Capital markets research in accounting}},
455+ journal = {Journal of Accounting and Economics},
456+ year = {2001},
457+ volume = {31},
458+ number = {1-3},
459+ pages = {105--231},
460+ doi = {10.1016/s0165-4101(01)00030-1}
461+}
462+
463+@article{easley2012,
464+ author = {Easley, David and López de Prado, Marcos M. and O'Hara, Maureen},
465+ title = {{Flow Toxicity and Liquidity in a High-frequency World}},
466+ journal = {Review of Financial Studies},
467+ year = {2012},
468+ volume = {25},
469+ number = {5},
470+ pages = {1457--1493},
471+ doi = {10.1093/rfs/hhs053}
472+}
473+
474+@article{hou2015,
475+ author = {Hou, Kewei and Xue, Chen and Zhang, Lu},
476+ title = {{Digesting Anomalies: An Investment Approach}},
477+ journal = {Review of Financial Studies},
478+ year = {2015},
479+ volume = {28},
480+ number = {3},
481+ pages = {650--705},
482+ doi = {10.1093/rfs/hhu068}
483+}
484+
485+@article{dechow2010,
486+ author = {Dechow, Patricia and Ge, Weili and Schrand, Catherine},
487+ title = {{Understanding earnings quality: A review of the proxies, their determinants and their consequences}},
488+ journal = {Journal of Accounting and Economics},
489+ year = {2010},
490+ volume = {50},
491+ number = {2-3},
492+ pages = {344--401},
493+ doi = {10.1016/j.jacceco.2010.09.001}
494+}
495+
496+@article{fama1970,
497+ author = {Fama, Eugene F.},
498+ title = {{Efficient Capital Markets: A Review of Theory and Empirical Work}},
499+ journal = {The Journal of Finance},
500+ year = {1970},
501+ volume = {25},
502+ number = {2},
503+ pages = {383},
504+ doi = {10.2307/2325486}
505+}
506+
507+@article{bollerslev2011tails,
508+ author = {BOLLERSLEV, TIM and TODOROV, VIKTOR},
509+ title = {{Tails, Fears, and Risk Premia}},
510+ journal = {The Journal of Finance},
511+ year = {2011},
512+ volume = {66},
513+ number = {6},
514+ pages = {2165--2211},
515+ doi = {10.1111/j.1540-6261.2011.01695.x}
516+}
517+
518+@article{hirshleifer2003,
519+ author = {Hirshleifer, David and Teoh, Siew Hong},
520+ title = {{Limited attention, information disclosure, and financial reporting}},
521+ journal = {Journal of Accounting and Economics},
522+ year = {2003},
523+ volume = {36},
524+ number = {1-3},
525+ pages = {337--386},
526+ doi = {10.1016/j.jacceco.2003.10.002}
527+}
528+
529+@article{savor2016,
530+ author = {SAVOR, PAVEL and WILSON, MUNGO},
531+ title = {{Earnings Announcements and Systematic Risk}},
532+ journal = {The Journal of Finance},
533+ year = {2016},
534+ volume = {71},
535+ number = {1},
536+ pages = {83--138},
537+ doi = {10.1111/jofi.12361}
538+}
539+
540+@article{budish2015,
541+ author = {Budish, Eric and Cramton, Peter and Shim, John},
542+ title = {{The High-Frequency Trading Arms Race: Frequent Batch Auctions as a Market Design Response *}},
543+ journal = {The Quarterly Journal of Economics},
544+ year = {2015},
545+ volume = {130},
546+ number = {4},
547+ pages = {1547--1621},
548+ doi = {10.1093/qje/qjv027}
549+}
550+
551+@article{chen2024deep,
552+ author = {Chen, Luyang and Pelger, Markus and Zhu, Jason},
553+ title = {{Deep Learning in Asset Pricing}},
554+ journal = {Management Science},
555+ year = {2024},
556+ volume = {70},
557+ number = {2},
558+ pages = {714--750},
559+ doi = {10.1287/mnsc.2023.4695}
560+}
561+
562+@article{kozak2020,
563+ author = {Kozak, Serhiy and Nagel, Stefan and Santosh, Shrihari},
564+ title = {{Shrinking the cross-section}},
565+ journal = {Journal of Financial Economics},
566+ year = {2020},
567+ volume = {135},
568+ number = {2},
569+ pages = {271--292},
570+ doi = {10.1016/j.jfineco.2019.06.008}
571+}
572+
573+@article{brogaard2019,
574+ author = {BROGAARD, JONATHAN and HENDERSHOTT, TERRENCE and RIORDAN, RYAN},
575+ title = {{Price Discovery without Trading: Evidence from Limit Orders}},
576+ journal = {The Journal of Finance},
577+ year = {2019},
578+ volume = {74},
579+ number = {4},
580+ pages = {1621--1658},
581+ doi = {10.1111/jofi.12769}
582+}
583+
584+@article{ang2006,
585+ author = {ANG, ANDREW and HODRICK, ROBERT J. and XING, YUHANG and ZHANG, XIAOYAN},
586+ title = {{The Cross-Section of Volatility and Expected Returns}},
587+ journal = {The Journal of Finance},
588+ year = {2006},
589+ volume = {61},
590+ number = {1},
591+ pages = {259--299},
592+ doi = {10.1111/j.1540-6261.2006.00836.x}
593+}
594+
595+@article{skinner2002,
596+ author = {Skinner, Douglas J. and Sloan, Richard G.},
597+ title = {{Earnings Surprises, Growth Expectations, and Stock Returns or Don't Let an Earnings Torpedo Sink Your Portfolio}},
598+ journal = {Review of Accounting Studies},
599+ year = {2002},
600+ volume = {7},
601+ number = {2-3},
602+ pages = {289--312},
603+ doi = {10.1023/a:1020294523516}
604+}
605+
606+@article{levi2015,
607+ author = {Levi, Shai and Zhang, Xiao-Jun},
608+ title = {{Asymmetric decrease in liquidity trading before earnings announcements and the announcement return premium}},
609+ journal = {Journal of Financial Economics},
610+ year = {2015},
611+ volume = {118},
612+ number = {2},
613+ pages = {383--398},
614+ doi = {10.1016/j.jfineco.2015.08.003}
615+}
616+
617+@article{campbell1993,
618+ author = {Campbell, J. Y. and Grossman, S. J. and Wang, J.},
619+ title = {{Trading Volume and Serial Correlation in Stock Returns}},
620+ journal = {The Quarterly Journal of Economics},
621+ year = {1993},
622+ volume = {108},
623+ number = {4},
624+ pages = {905--939},
625+ doi = {10.2307/2118454}
626+}
627+
628+@article{fang2009,
629+ author = {FANG, LILY and PERESS, JOEL},
630+ title = {{Media Coverage and the Cross-section of Stock Returns}},
631+ journal = {The Journal of Finance},
632+ year = {2009},
633+ volume = {64},
634+ number = {5},
635+ pages = {2023--2052},
636+ doi = {10.1111/j.1540-6261.2009.01493.x}
637+}
638+
639+@article{beaver1980,
640+ author = {Beaver, William and Lambert, Richard and Morse, Dale},
641+ title = {{The information content of security prices}},
642+ journal = {Journal of Accounting and Economics},
643+ year = {1980},
644+ volume = {2},
645+ number = {1},
646+ pages = {3--28},
647+ doi = {10.1016/0165-4101(80)90013-0}
648+}
649+
650+@article{kothari1992,
651+ author = {Kothari, S.P and Sloan, Richard G},
652+ title = {{Information in prices about future earnings}},
653+ journal = {Journal of Accounting and Economics},
654+ year = {1992},
655+ volume = {15},
656+ number = {2-3},
657+ pages = {143--171},
658+ doi = {10.1016/0165-4101(92)90016-u}
659+}
660+
661+@article{collins1994,
662+ author = {Collins, Daniel W. and Kothari, S.P. and Shanken, Jay and Sloan, Richard G.},
663+ title = {{Lack of timeliness and noise as explanations for the low contemporaneuos return-earnings association}},
664+ journal = {Journal of Accounting and Economics},
665+ year = {1994},
666+ volume = {18},
667+ number = {3},
668+ pages = {289--324},
669+ doi = {10.1016/0165-4101(94)90024-8}
670+}
671+
672+@article{foster1977,
673+ author = {Foster, George},
674+ title = {{Quarterly Accounting Data: Time-Series Properties and Predicative-Ability Results.}},
675+ journal = {The Accounting Review},
676+ year = {1977},
677+ volume = {52},
678+ number = {1},
679+ pages = {1--21},
680+ doi = {10.2308/tar-4493420}
681+}
682+
683+@article{weller2018,
684+ author = {Weller, Brian M.},
685+ title = {{Does Algorithmic Trading Reduce Information Acquisition?}},
686+ journal = {The Review of Financial Studies},
687+ year = {2018},
688+ volume = {31},
689+ number = {6},
690+ pages = {2184--2226},
691+ doi = {10.1093/rfs/hhx137}
692+}
693+
694+@article{bollerslev2018volume,
695+ author = {Bollerslev, Tim and Li, Jia and Xue, Yuan},
696+ title = {{Volume, Volatility, and Public News Announcements}},
697+ journal = {The Review of Economic Studies},
698+ year = {2018},
699+ volume = {85},
700+ number = {4},
701+ pages = {2005--2041},
702+ doi = {10.1093/restud/rdy003}
703+}
704+
705+@article{patton2012,
706+ author = {Patton, Andrew J. and Verardo, Michela},
707+ title = {{Does Beta Move with News? Firm-Specific Information Flows and Learning about Profitability}},
708+ journal = {Review of Financial Studies},
709+ year = {2012},
710+ volume = {25},
711+ number = {9},
712+ pages = {2789--2839},
713+ doi = {10.1093/rfs/hhs073}
714+}
715+
716+@article{kaniel2012,
717+ author = {KANIEL, RON and LIU, SHUMING and SAAR, GIDEON and TITMAN, SHERIDAN},
718+ title = {{Individual Investor Trading and Return Patterns around Earnings Announcements}},
719+ journal = {The Journal of Finance},
720+ year = {2012},
721+ volume = {67},
722+ number = {2},
723+ pages = {639--680},
724+ doi = {10.1111/j.1540-6261.2012.01727.x}
725+}
726+
727+@article{christophe2004,
728+ author = {Christophe, Stephen E. and Ferri, Michael G. and Angel, James J.},
729+ title = {{Short-Selling Prior to Earnings Announcements}},
730+ journal = {The Journal of Finance},
731+ year = {2004},
732+ volume = {59},
733+ number = {4},
734+ pages = {1845--1876},
735+ doi = {10.1111/j.1540-6261.2004.00681.x}
736+}
737+
738+@article{berkman2009,
739+ author = {Berkman, Henk and Dimitrov, Valentin and Jain, Prem C. and Koch, Paul D. and Tice, Sheri},
740+ title = {{Sell on the news: Differences of opinion, short-sales constraints, and returns around earnings announcements☆}},
741+ journal = {Journal of Financial Economics},
742+ year = {2009},
743+ volume = {92},
744+ number = {3},
745+ pages = {376--399},
746+ doi = {10.1016/j.jfineco.2008.04.009}
747+}
748+
749+@article{hendershott2015,
750+ author = {Hendershott, Terrence and Livdan, Dmitry and Schürhoff, Norman},
751+ title = {{Are institutions informed about news?}},
752+ journal = {Journal of Financial Economics},
753+ year = {2015},
754+ volume = {117},
755+ number = {2},
756+ pages = {249--287},
757+ doi = {10.1016/j.jfineco.2015.03.007}
758+}
759+
760+@article{lee2012,
761+ author = {Lee, Suzanne S.},
762+ title = {{Jumps and Information Flow in Financial Markets}},
763+ journal = {Review of Financial Studies},
764+ year = {2012},
765+ volume = {25},
766+ number = {2},
767+ pages = {439--479},
768+ doi = {10.1093/rfs/hhr084}
769+}
770+
771+@article{cao2024,
772+ author = {Cao, Sean and Jiang, Wei and Wang, Junbo and Yang, Baozhong},
773+ title = {{From Man vs. Machine to Man + Machine: The art and AI of stock analyses}},
774+ journal = {Journal of Financial Economics},
775+ year = {2024},
776+ volume = {160},
777+ pages = {103910},
778+ doi = {10.1016/j.jfineco.2024.103910}
779+}
780+
781+@article{bali2023,
782+ author = {Bali, Turan G and Beckmeyer, Heiner and Mörke, Mathis and Weigert, Florian},
783+ title = {{Option Return Predictability with Machine Learning and Big Data}},
784+ journal = {The Review of Financial Studies},
785+ year = {2023},
786+ volume = {36},
787+ number = {9},
788+ pages = {3548--3602},
789+ doi = {10.1093/rfs/hhad017}
790+}
791+
792+@article{easton2024,
793+ author = {Easton, Peter D. and Kapons, Martin M. and Monahan, Steven J. and Schütt, Harm H. and Weisbrod, Eric H.},
794+ title = {{Forecasting Earnings Using \emph{k}-Nearest Neighbors}},
795+ journal = {The Accounting Review},
796+ year = {2024},
797+ volume = {99},
798+ number = {3},
799+ pages = {115--140},
800+ doi = {10.2308/tar-2021-0478}
801+}
802+
803+@article{so2013,
804+ author = {So, Eric C.},
805+ title = {{A new approach to predicting analyst forecast errors: Do investors overweight analyst forecasts?}},
806+ journal = {Journal of Financial Economics},
807+ year = {2013},
808+ volume = {108},
809+ number = {3},
810+ pages = {615--640},
811+ doi = {10.1016/j.jfineco.2013.02.002}
812+}
813+
814+@article{hou2012,
815+ author = {Hou, Kewei and van Dijk, Mathijs A. and Zhang, Yinglei},
816+ title = {{The implied cost of capital: A new approach}},
817+ journal = {Journal of Accounting and Economics},
818+ year = {2012},
819+ volume = {53},
820+ number = {3},
821+ pages = {504--526},
822+ doi = {10.1016/j.jacceco.2011.12.001}
823+}
824+
825+@article{hansen2006,
826+ author = {Hansen, Peter R and Lunde, Asger},
827+ title = {{Realized Variance and Market Microstructure Noise}},
828+ journal = {Journal of Business \& Economic Statistics},
829+ year = {2006},
830+ volume = {24},
831+ number = {2},
832+ pages = {127--161},
833+ doi = {10.1198/073500106000000071}
834+}
835+
836+@article{barndorff2008,
837+ author = {Barndorff-Nielsen, Ole E. and Hansen, Peter Reinhard and Lunde, Asger and Shephard, Neil},
838+ title = {{Designing Realized Kernels to Measure the ex post Variation of Equity Prices in the Presence of Noise}},
839+ journal = {Econometrica},
840+ year = {2008},
841+ volume = {76},
842+ number = {6},
843+ pages = {1481--1536},
844+ doi = {10.3982/ecta6495}
845+}
846+
847+@article{vankervel2019,
848+ author = {VAN KERVEL, VINCENT and MENKVELD, ALBERT J.},
849+ title = {{High-Frequency Trading around Large Institutional Orders}},
850+ journal = {The Journal of Finance},
851+ year = {2019},
852+ volume = {74},
853+ number = {3},
854+ pages = {1091--1137},
855+ doi = {10.1111/jofi.12759}
856+}
857+
858+@article{avramov2023,
859+ author = {Avramov, Doron and Cheng, Si and Metzker, Lior},
860+ title = {{Machine Learning vs. Economic Restrictions: Evidence from Stock Return Predictability}},
861+ journal = {Management Science},
862+ year = {2023},
863+ volume = {69},
864+ number = {5},
865+ pages = {2587--2619},
866+ doi = {10.1287/mnsc.2022.4449}
867+}
868+
869+@article{chordia2020,
870+ author = {Chordia, Tarun and Goyal, Amit and Saretto, Alessio},
871+ title = {{Anomalies and False Rejections}},
872+ journal = {The Review of Financial Studies},
873+ year = {2020},
874+ volume = {33},
875+ number = {5},
876+ pages = {2134--2179},
877+ doi = {10.1093/rfs/hhaa018}
878+}
879+
880+@article{barber2013,
881+ author = {Barber, Brad M. and De George, Emmanuel T. and Lehavy, Reuven and Trueman, Brett},
882+ title = {{The earnings announcement premium around the globe}},
883+ journal = {Journal of Financial Economics},
884+ year = {2013},
885+ volume = {108},
886+ number = {1},
887+ pages = {118--138},
888+ doi = {10.1016/j.jfineco.2012.10.006}
889+}
890+
891+@article{politis1994,
892+ author = {Politis, Dimitris N. and Romano, Joseph P.},
893+ title = {{The Stationary Bootstrap}},
894+ journal = {Journal of the American Statistical Association},
895+ year = {1994},
896+ volume = {89},
897+ number = {428},
898+ pages = {1303--1313},
899+ doi = {10.1080/01621459.1994.10476870}
900+}
901+
902+@article{hansen2011mcs,
903+ author = {Hansen, Peter R. and Lunde, Asger and Nason, James M.},
904+ title = {{The Model Confidence Set}},
905+ journal = {Econometrica},
906+ year = {2011},
907+ volume = {79},
908+ number = {2},
909+ pages = {453--497},
910+ doi = {10.3982/ecta5771}
911+}
912+
913+@article{benjamini1995,
914+ author = {Benjamini, Yoav and Hochberg, Yosef},
915+ title = {{Controlling the False Discovery Rate: A Practical and Powerful Approach to Multiple Testing}},
916+ journal = {Journal of the Royal Statistical Society Series B: Statistical Methodology},
917+ year = {1995},
918+ volume = {57},
919+ number = {1},
920+ pages = {289--300},
921+ doi = {10.1111/j.2517-6161.1995.tb02031.x}
922+}
923+
924+@article{amihud2002,
925+ author = {Amihud, Yakov},
926+ title = {{Illiquidity and stock returns: cross-section and time-series effects}},
927+ journal = {Journal of Financial Markets},
928+ year = {2002},
929+ volume = {5},
930+ number = {1},
931+ pages = {31--56},
932+ doi = {10.1016/s1386-4181(01)00024-6}
933+}
934+
935+@article{fama1993,
936+ author = {Fama, Eugene F. and French, Kenneth R.},
937+ title = {{Common risk factors in the returns on stocks and bonds}},
938+ journal = {Journal of Financial Economics},
939+ year = {1993},
940+ volume = {33},
941+ number = {1},
942+ pages = {3--56},
943+ doi = {10.1016/0304-405x(93)90023-5}
944+}
945+
946+@article{grossman1980,
947+ author = {Grossman, Sanford J. and Stiglitz, Joseph E.},
948+ title = {{On the Impossibility of Informationally Efficient Markets}},
949+ journal = {American Economic Review},
950+ year = {1980},
951+ volume = {70},
952+ number = {3},
953+ pages = {393--408}
954+}
955+@article{holm1979,
956+ author = {Holm, Sture},
957+ title = {{A Simple Sequentially Rejective Multiple Test Procedure}},
958+ journal = {Scandinavian Journal of Statistics},
959+ year = {1979},
960+ volume = {6},
961+ number = {2},
962+ pages = {65--70}
963+}
964+@article{kunsch1989,
965+ author = {K{\"u}nsch, Hans R.},
966+ title = {{The Jackknife and the Bootstrap for General Stationary Observations}},
967+ journal = {Annals of Statistics},
968+ year = {1989},
969+ volume = {17},
970+ number = {3},
971+ pages = {1217--1241},
972+ doi = {10.1214/aos/1176347265}
973+}
974+@inproceedings{ke2017lightgbm,
975+ author = {Ke, Guolin and Meng, Qi and Finley, Thomas and Wang, Taifeng and Chen, Wei and Ma, Weidong and Ye, Qiwei and Liu, Tie-Yan},
976+ title = {{LightGBM: A Highly Efficient Gradient Boosting Decision Tree}},
977+ booktitle = {Advances in Neural Information Processing Systems 30},
978+ year = {2017},
979+ pages = {3146--3154}
980+}
981+@book{lopezdeprado2018,
982+ author = {L{\'o}pez de Prado, Marcos},
983+ title = {{Advances in Financial Machine Learning}},
984+ publisher = {Wiley},
985+ address = {Hoboken, NJ},
986+ year = {2018}
987+}
988+@techreport{frazzini2018costs,
989+ author = {Frazzini, Andrea and Israel, Ronen and Moskowitz, Tobias J.},
990+ title = {{Trading Costs}},
991+ institution = {SSRN Working Paper 3229719},
992+ year = {2018},
993+ doi = {10.2139/ssrn.3229719}
994+}
995+@incollection{barndorff2010semivariance,
996+ author = {Barndorff-Nielsen, Ole E. and Kinnebrock, Silja and Shephard, Neil},
997+ title = {{Measuring Downside Risk: Realised Semivariance}},
998+ booktitle = {Volatility and Time Series Econometrics: Essays in Honor of Robert F. Engle},
999+ editor = {Bollerslev, Tim and Russell, Jeffrey and Watson, Mark},
1000+ publisher = {Oxford University Press},
1001+ year = {2010},
1002+ pages = {117--136},
1003+ doi = {10.1093/acprof:oso/9780199549498.003.0007}
1004+}
1005+@article{boucher2026wp15,
1006+ author = {Boucher, Simon-Pierre},
1007+ title = {{Faster, Wider, More Fragile? The Evolution of Intraday Shock Propagation in U.S. Equity Markets, 1992--2026}},
1008+ journal = {UQO Working Paper No. 15},
1009+ year = {2026}
1010+}
1011+
1012+@article{harvey2016,
1013+ author = {Harvey, Campbell R. and Liu, Yan and Zhu, Heqing},
1014+ title = {{\ldots and the Cross-Section of Expected Returns}},
1015+ journal = {The Review of Financial Studies},
1016+ year = {2016},
1017+ volume = {29},
1018+ number = {1},
1019+ pages = {5--68},
1020+ doi = {10.1093/rfs/hhv059}
1021+}
added paper/.latexmkrc +5 −0
Large diff (5 lines) is not loaded by default to keep the page fast.Load diff
added paper/Makefile +11 −0
Large diff (11 lines) is not loaded by default to keep the page fast.Load diff
added paper/appendix/appendix.tex +54 −0
Large diff (54 lines) is not loaded by default to keep the page fast.Load diff
added paper/main.tex +141 −0
Large diff (141 lines) is not loaded by default to keep the page fast.Load diff
added paper/references.bib +1021 −0
Large diff (1,021 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/data.tex +83 −0
Large diff (83 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/literature.tex +46 −0
Large diff (46 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/methodology.tex +78 −0
Large diff (78 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/theory_hypotheses.tex +64 −0
Large diff (64 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/titlepage.tex +77 −0
Large diff (77 lines) is not loaded by default to keep the page fast.Load diff
added paper/sections/titlepage_anon.tex +53 −0
Large diff (53 lines) is not loaded by default to keep the page fast.Load diff
added paper/uq_logo.jpg +0 −0

Binary file not shown.

added pyproject.toml +42 −0
Large diff (42 lines) is not loaded by default to keep the page fast.Load diff
added scripts/00_probe_findata.py +42 −0
Large diff (42 lines) is not loaded by default to keep the page fast.Load diff
added scripts/01_audit_universe.py +83 −0
Large diff (83 lines) is not loaded by default to keep the page fast.Load diff
added scripts/01a_extract_node_tables.sh +16 −0
Large diff (16 lines) is not loaded by default to keep the page fast.Load diff
added scripts/02_build_pit_panel.py +75 −0
Large diff (75 lines) is not loaded by default to keep the page fast.Load diff
added scripts/03_build_features.py +116 −0
Large diff (116 lines) is not loaded by default to keep the page fast.Load diff
added scripts/04_build_labels.py +83 −0
Large diff (83 lines) is not loaded by default to keep the page fast.Load diff
added scripts/05_train_baselines.py +108 −0
Large diff (108 lines) is not loaded by default to keep the page fast.Load diff
added scripts/06_train_advanced.py +116 −0
Large diff (116 lines) is not loaded by default to keep the page fast.Load diff
added scripts/07_evaluate.py +209 −0
Large diff (209 lines) is not loaded by default to keep the page fast.Load diff
added scripts/08_run_robustness.py +156 −0
Large diff (156 lines) is not loaded by default to keep the page fast.Load diff
added scripts/09_make_manuscript.py +203 −0
Large diff (203 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/__init__.py +2 −0
Large diff (2 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/api_client.py +226 −0
Large diff (226 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/calendar.py +78 −0
Large diff (78 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/catalog.py +31 −0
Large diff (31 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/corporate_actions.py +36 −0
Large diff (36 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/features.py +181 −0
Large diff (181 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/figures.py +156 −0
Large diff (156 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/inference.py +134 −0
Large diff (134 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/ingest.py +63 −0
Large diff (63 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/instruments.py +119 −0
Large diff (119 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/labels.py +104 −0
Large diff (104 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/models.py +137 −0
Large diff (137 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/pipeline.py +62 −0
Large diff (62 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/pit_fundamentals.py +115 −0
Large diff (115 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/portfolio.py +124 −0
Large diff (124 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/provenance.py +61 −0
Large diff (61 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/robustness.py +46 −0
Large diff (46 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/samples.py +180 −0
Large diff (180 lines) is not loaded by default to keep the page fast.Load diff
added src/wp39/splits.py +65 −0
Large diff (65 lines) is not loaded by default to keep the page fast.Load diff
added tests/__init__.py +0 −0
Large diff (0 lines) is not loaded by default to keep the page fast.Load diff
added tests/conftest.py +39 −0
Large diff (39 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_api_contract.py +42 −0
Large diff (42 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_corporate_actions.py +22 −0
Large diff (22 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_features.py +37 −0
Large diff (37 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_instrument_ids.py +17 −0
Large diff (17 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_labels.py +26 −0
Large diff (26 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_pit_leakage.py +45 −0
Large diff (45 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_reproducibility.py +23 −0
Large diff (23 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_splits.py +37 −0
Large diff (37 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_timestamp_dsts.py +30 −0
Large diff (30 lines) is not loaded by default to keep the page fast.Load diff
added tests/test_train_only_transforms.py +15 −0
Large diff (16 lines) is not loaded by default to keep the page fast.Load diff
Menu

Theme