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