# Codebook: quarterly gross margin from audited filings, 10 August 2026 Every figure in `gross-margin-panel.csv` is computed from **SEC EDGAR XBRL company facts**: the audited numbers as filed. Nothing here is a benchmark, a survey, a vendor disclosure or an estimate. The scripts that produced it are in `scripts/`, including **the two that failed**. ## The frame The **64 constituents of the BVP Nasdaq Emerging Cloud Index**, read from the data payload of `cloudindex.bvp.com/companies` on 9 August 2026 and fixed there: `/data/pricing-pages-2026-08/frame.md`. Reused deliberately. It is the same population as the pricing-page corpus, already justified, already public, and: the point: **not conditioned on the outcome**. It is an index of cloud companies, not a list of firms with AI features or with falling margins. A universe assembled by looking for margin compression would find it. ## Window and panel **2022Q1–2026Q1, 17 quarters.** 53 of the 64 constituents have a complete run across it: **901 firm-quarters**, balanced. The other 11 are accounted for below and never silently dropped. | | n | | |---|---:|---| | **Balanced**: every quarter in the window | 53 | the panel every headline figure is computed on | | **Partial**: listed or first filed with the SEC mid-window | 7 | ALKT, FIG, KVYO, RBRK, SAIL, SHOP, TTAN: in the CSV, `in_balanced_panel = False` | | **Excluded**: no quarterly US-GAAP gross profit exists | 4 | see below | **The four exclusions, with the actual reason:** | | | |---|---| | **CLBT, MNDY, WIX** | Israeli-domiciled foreign private issuers. They file annually (20-F) under IFRS and report gross profit **annually or semi-annually**, never quarterly. There is no quarterly figure to include | | **WDAY** | Workday files revenue under US-GAAP throughout the window but tags **no** cost-of-revenue element under any US-GAAP tag in it: the cost lines are company-extension tags. Gross profit is not derivable without leaving the audited taxonomy | ## Three decisions that change the numbers, all of them consequential **1. The fourth quarter is derived, because it is never filed.** A company files three 10-Qs and one 10-K. Q4 exists only as *annual minus the three quarters inside it*. Reading the API naively returns 13 or 14 quarters of a 17-quarter window and silently drops every Q4: the seasonally strongest one. Q4 here is the arithmetic difference, and it reconciles to the 10-K by construction. **2. Quarters are assigned by period MIDPOINT, not period end.** Salesforce's quarter runs 1 November to 31 January. Assigned by its end date it lands in the following calendar Q1, a full quarter late. Its midpoint is mid-December, so it is Q4. Sixteen of the 53 have off-calendar fiscal years and mis-phasing them shifts the whole series against the calendar. **3. SEC's own `frame` field is not used.** It is assigned sparsely and it is assigned *least* to exactly the off-calendar filers that decision 2 exists for. Using it produced 7 quarters for Workday and 0 for Wix, which reads as an absent company rather than an absent method. ## Fields | Field | Meaning | |---|---| | `symbol`, `name`, `cik` | constituent, and its SEC identifier | | `quarter` | calendar quarter containing the period midpoint | | `period_start`, `period_end` | the filed period, exactly as reported | | `revenue_usd` | first available of `RevenueFromContractWithCustomerExcludingAssessedTax`, `…IncludingAssessedTax`, `Revenues`, `SalesRevenueNet` | | `cost_of_revenue_usd` | first available of `CostOfRevenue`, `CostOfGoodsAndServicesSold`, `CostOfServices`, `CostOfGoodsSold`; where a filer reports only components (AppFolio), the components are summed | | `gross_profit_usd` | `GrossProfit` where filed, else revenue − cost of revenue | | `gross_margin` | gross profit ÷ revenue | | `in_balanced_panel` | whether the firm has all 17 quarters | Where a filer restated, **the latest filed value wins**. Rows with a computed margin outside (0,1) are dropped as a tagging error rather than carried. ## What this data cannot do, stated before anyone uses it **Cost of revenue is one blended line.** No filer breaks out inference. The panel can show what happened to the total; it cannot attribute any part of it to AI, and no arrangement of these columns will make it do so. Anyone: including this site: who claims to isolate an AI effect from these columns is inferring, not measuring. **The design detects a mean compression of about 2 percentage points.** Simulated at the observed between-firm spread: 50% power at −2pp, 84% at −3pp, and **17% at −1pp**. A null result here is not evidence that nothing under a point happened. `scripts/power-and-robustness.py` is the computation. **Two diagnostics were built, tested and thrown away.** Both are retained in `scripts/` because a failed instrument is evidence too: - `diagnostic-v1-failed.py`: a levels regression of log cost on log revenue. The naive "elasticity above 1" reading **fires about 50% of the time on random data**, and the significance-tested version **fires 98.9% of the time on a pure accounting reclassification** with no change in cost structure at all. - `diagnostic-v2-failed.py`: the first-difference rebuild. It survives the reclassification (3.9%) and then **detects a genuine 30% variable-cost shift only 3.8% of the time**, which is below its own false-positive rate. Robust and blind. Neither is published as a recommendation, because a test that cannot separate an economics change from a restatement: or that cannot see a real effect: is not a test. ## Reproducing it ``` python3 scripts/build-panel.py # fetch + panel (needs a SEC User-Agent with contact) python3 scripts/analyse.py # the headline series python3 scripts/power-and-robustness.py ``` The SEC API is free, unauthenticated and rate-limited to 10 requests/second; it requires a `User-Agent` naming a contact address. No scraping, no vendor data, no login.