Broker-Dealer Annual Reports (X-17A-5)
Annual audited reports (Form X-17A-5) filed by every registered broker-dealer, including the independent accountant who signed the audit and whether a material weakness was reported - disclosed nowhere else, since these firms file no 8-K. Filings are routinely back-dated by months or years, so each row also carries the measured gap between the report's own date and the day the SEC actually published it.
edgar_broker_dealer_reports - the dataset name to pass to the Obscura API.
What one row means
One **Form X-17A-5 Part III** annual audited report filed by a broker-dealer - the only public window into the balance sheet of an entity that, in the overwhelming majority of cases, files NOTHING ELSE on EDGAR. Every broker-dealer registered under Exchange Act Section 15 must file an annual report audited by an independent public accountant (Rule 17a-5(d)). The registrant is usually not a public company: it has no 10-K, no proxy, no XBRL and no ticker. This filing, and its `008-` broker-dealer registration number, is the whole of its public record. # THE FINANCIAL STATEMENTS ARE A PDF. THIS TABLE IS THE COVER SHEET. That was measured, not assumed. On every one of the 10 electronically filed X-17A-5 submissions in the 2024-02-14 dissemination feed, the financial content is a single `<TYPE>FULL` **PDF** (`Public.pdf`, `bhspub.pdf`, `cheval_12312023-fins3.pdf`, …) and there is no XBRL, no XML financial statement and no tagged FOCUS report anywhere in the submission. There is therefore no balance sheet to extract without OCR, and this table follows the `UPLOAD`/`CORRESP` precedent: it stores the METADATA SEC itself structures and the document manifest that points at the PDF, and it stores no financial figure at all. What that leaves is still the point of the dataset: * **`accountant_name` - WHO AUDITS THIS BROKER-DEALER, per year.** A change of auditor at a broker-dealer is a signal nothing else in the catalogue carries, because the registrant files no 8-K Item 4.01. * **`material_weakness` - the registrant's own Y/N declaration**, stated in the structured cover rather than buried in the PDF. * the fiscal period covered, the `008-` registration number, and the registrant's identity and domicile. # `is_paper` IS THE ROW'S MOST IMPORTANT FLAG, AND IT IS NOT AN ERA SEC accepts this form on PAPER as well as through EDGAR, and it publishes the paper ones as an auto-generated stub: accession `9999999997-YY-NNNNNN`, a `<PAPER>` header flag, one placeholder document naming a Document Control Number, and NO content whatsoever. Those rows carry the header columns and NULL for every structured-cover column, and `is_paper` says so. The paper and electronic populations COEXIST for a decade - they are not two eras with a boundary, which is why this is a per-row flag rather than a declared `regime`. Counted from the quarterly form indexes: 2011Q1 3,678 paper / 0 electronic; 2015Q2 376 / 0; **2016Q1 2,753 / 440** (the first electronic filings); 2018Q1 2,089 / 884; 2022Q1 1,308 / 1,338; 2025Q1 719 / 1,401; **2026Q1 0 / 2,136** (paper gone). See `docs/datasets/edgar_broker_dealer_reports.md` and `docs/availability/edgar_broker_dealer_reports.md`.
One row per One row per X-17A-5 or X-17A-5/A submission, keyed by its ACCESSION. A broker-dealer files one annual report per fiscal year, so the natural reading is one row per (broker-dealer, fiscal year) - but the key is the accession because an amendment (X-17A-5/A) and a re-filed period are separate submissions that must both survive. The archive path would be an equally unique key on this family (measured 80 accessions / 80 index paths over three dissemination days spanning 2024-2026: X-17A-5 never fans out, unlike EFFECT at 19 paths or 25-NSE at 2), and the accession is used anyway so the key rule is the same one every EDGAR document dataset here uses..
Point-in-time availability
Every Obscura dataset carries available_date: the calendar day the publisher made the row
available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the
same thing on every dataset in the catalog.
For edgar_broker_dealer_reports: filing_join: available_date is the EDGAR DISSEMINATION day, taken from the bronze object's own day partition, NEVER from the header's FILED AS OF DATE. WHY: this family is the worst back-dating offender on EDGAR after the SEC-side correspondence forms - 87,521 of 104,685 X-17A-5 rows (83.6%) were disseminated LATER than the date they are stamped with, and the mechanism is the paper channel: SEC scans and releases paper filings in batches weeks or months after receipt. Measured on the 2024-02-14 feed day: 27 of the 28 paper submissions carry an earlier legal filing date, mean lag 91.3 days, MAX 1,447 days (a 2019-12-31 fiscal year stamped 2020-02-28 and first disseminated 2024-02-14); the 10 electronic submissions on the same day all carry zero lag. Using FILED AS OF DATE would therefore publish four years of look-ahead on a single row. Evidence class B (observed dissemination-day membership against a stated earlier filing date); see docs/availability/edgar_broker_dealer_reports.md. period_start/period_end are the AUDITED FISCAL PERIOD and are never availability anchors.
Refresh cadence
Obscura refreshes edgar_broker_dealer_reports every 6 hours - the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.
Schema - 38 columns
The full public column list for edgar_broker_dealer_reports, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/edgar_broker_dealer_reports.
| Column | Type | Description |
|---|---|---|
| accession | text · not null | PK. SEC accession number of the submission. Two shapes, and the difference is the whole `is_paper` story: a filer-generated `0001019586-24-000001` for an electronic filing, and SEC's own `9999999997-YY-NNNNNN` for a scanned paper one. |
| filename | text · not null | The registrant's SEC EDGAR Archives path for this submission (`edgar/data/{cik}/{accession}.txt`), derived from the payload's own `FILER:` block rather than from whichever index row was walked, so it is the same value on every ingestion path. The join key into `edgar_filings`. |
| available_date | date | Public availability date: the EDGAR DISSEMINATION day, recovered from the bronze object's day partition. The point-in-time anchor and the only date a backtest may key on. On a paper filing this is routinely MONTHS after `filed_as_of` - see the dataset's availability note. |
| period_start | date | First day of the audited fiscal period (`PERIOD START:` / `<PERIOD-START>`, corroborated by `<periodBegin>` in the structured cover). Normally the fiscal year start. |
| period_end | date | Last day of the audited fiscal period (`CONFORMED PERIOD OF REPORT` / `<PERIOD>`, corroborated by `<periodEnd>`). The fiscal year end the audited statements are as of - a REPORTING period, never an availability date. |
| accepted_at | timestamp with time zone | When SEC ACCEPTED the submission (`<ACCEPTANCE-DATETIME>`), US-Eastern wall clock under a UTC type. Provenance only: an after-hours acceptance is disseminated the next morning, and on a paper filing the acceptance stamp is the day SEC keyed it in rather than the day it published it. NULL on a row ingested from the dissemination feed, whose envelope does not carry this stamp - a fact about the envelope, not a decoder gap. |
| filed_as_of | date | SEC's LEGAL filing date (`FILED AS OF DATE`). Kept as provenance and as the input to `dissemination_lag_days`; it is NEVER an availability date on this family, where 83.6 % of rows are back-dated. |
| dissemination_lag_days | integer | `available_date - filed_as_of` in whole days: how long SEC held this report before it became publicly readable. Zero on every electronic filing measured; a mean of 91 and a maximum of 1,447 on paper ones. Materialised so the look-ahead this dataset exists to avoid is visible as a column instead of an argument. NULL when either date is absent. |
| form_type | text · not null | The submission type exactly as EDGAR states it: `X-17A-5` or `X-17A-5/A`. Measured as the complete family on five quarterly form indexes spanning 2011-2026 - no other literal appears. |
| is_amendment | boolean · not null | TRUE when this is an amendment (`X-17A-5/A`) restating an earlier annual report. Roughly 2-3 % of the family (55 of 2,285 in 2024Q1). Derived from `form_type`; the migration CHECKs the derivation rather than trusting the writer. |
| is_paper | boolean · not null | **TRUE when this is a PAPER filing SEC scanned and released as a stub.** The header carries `<PAPER>`, the accession is `9999999997-…`, and the submission contains ONE placeholder document naming a Document Control Number instead of any content - so every structured-cover column on this row is NULL and no PDF exists to point at. This is a fact about the FILING CHANNEL, not an era: paper and electronic coexisted from 2016Q1 (2,753 / 440) to 2025Q1 (719 / 1,401), and paper reached zero only in 2026Q1. |
| has_structured_cover | boolean · not null | TRUE when the submission carries the machine-readable `primary_doc.xml` cover (`http://www.sec.gov/edgar/seventeenafiler`) that fills `accountant_name`, `material_weakness` and the rest. FALSE on every paper stub, and the direct test of whether the structured-cover columns on this row mean "no" or "not stated". |
| cik | bigint | Central Index Key of the filing broker-dealer, from the header's `FILER:` block. |
| company_name | text | The broker-dealer's name as EDGAR conforms it, e.g. `CHEVAL CAPITAL, INC.`, `UHLMANN PRICE SECURITIES, LLC`. |
| sec_file_number | text | **The `008-` BROKER-DEALER REGISTRATION NUMBER** (`008-49491`), from `SEC FILE NUMBER:`. This is the identifier that joins an X-17A-5 to the firm's Form BD record and to FINRA's registration data - and for a firm with no ticker and no other filing, it is the only durable identifier it has besides its CIK. |
| film_number | text | EDGAR's `FILM NUMBER:` for the submission. On a PAPER filing this is the **Document Control Number** the auto-generated stub instructs a reader to quote when requesting the original document from SEC, which makes it the only route from this row to the actual report. |
| irs_number | text | The registrant's IRS Employer Identification Number as text (leading zeros are significant). EDGAR's all-zero placeholder is normalised to NULL rather than stored as a nine-zero string that reads like a real identifier. |
| state_of_incorporation | text | Where the broker-dealer is INCORPORATED, as an EDGAR state-or-country code (`VA`, `IL`, `NY`, `DE`). A different fact from `business_state` - a Delaware LLC operating out of Chicago states both. |
| business_city | text | The registrant's HQ city from its `BUSINESS ADDRESS` block, verbatim. |
| business_state | text | The registrant's HQ state/country code from its `BUSINESS ADDRESS` block - where the firm OPERATES, as distinct from where it is incorporated. |
| fiscal_year_end | text | The registrant's fiscal year end as EDGAR's four-digit `MMDD` (`1231`, `0930`, `0331`). Text, not a date: it names a recurring day, not an instant. |
| accountant_name | text | **THE AUDITOR.** The independent public accountant's name exactly as the registrant states it in the structured cover (`<accountantName>`) - `Rubio CPA PC`, `Pamela Ohab`. NULL on every paper filing. A year-over-year change in this column at one `cik` is an auditor change at a broker-dealer, which is disclosed nowhere else in the public record because the registrant files no 8-K. |
| accountant_type | text | The accountant's declared qualification (`<accountantType>`), e.g. `Certified Public Accountant`. NULL on paper filings. |
| accountant_city | text | The accountant's city, from `<accountantAddress>`. Together with `accountant_state` it separates a national audit firm from a local one without name matching. |
| accountant_state | text | The accountant's state-or-country code, from `<accountantAddress>`. |
| material_weakness | boolean | **The registrant's own MATERIAL WEAKNESS declaration** from `<materialWeakness>`: TRUE for `Y`, FALSE for `N`, NULL when the submission states nothing (every paper filing). A firm declaring a material weakness in its internal control over compliance is the single highest-signal field on the form, and it is stated in the structured cover rather than only inside the PDF. |
| registrant_type | text | What kind of registrant is filing, from `<typeOfRegistrant>` - `Broker-dealer`, and the OTC-derivatives-dealer and security-based-swap variants the form also admits. NULL on paper filings. |
| registrant_subtype | text | The registrant sub-type when the form states one (`<subTypeOfBDRegistrant>`); rare - 1 of 10 measured electronic filings - and NULL otherwise. |
| contact_person_name | text | The name of the person the registrant nominates as the contact for this filing (`<contactPersonName>`). NULL on paper filings. |
| contact_person_phone | text | That contact's telephone number, verbatim and unnormalised (`7035497390`, `3122644400`). |
| oath_person_name | text | Who swore the oath or affirmation required by Rule 17a-5(e)(2) (`<signPersonName>`) - normally a principal of the firm. |
| oath_title | text | That person's title (`<oathTitle>`), e.g. `President`, `Managing Member`. The de facto senior-officer record for a firm that files no proxy. |
| oath_signed_on | date | The date on the oath (`<signDate>`). Usually the fiscal period end rather than the day it was signed - measured equal to `period_end` on 10 of 10 electronic filings - so it is stored as its own column and is deliberately NOT a conformed event date. |
| oath_notarized | boolean | The registrant's `<confirmNotarizedFlag>`: TRUE when it confirms the oath was notarised. NULL on paper filings. |
| live_test_flag | text | `<liveTestFlag>` from the structured cover - `LIVE` on everything that reaches dissemination. Kept because a `TEST` value would mean the row is not a real filing, and the parser refuses rather than stores that case. |
| document_count | integer | Number of documents in the submission (`PUBLIC DOCUMENT COUNT:`). 2 on a typical electronic filing (the XML cover plus one PDF), 1 on a paper stub, 3 when the firm attaches two years of audits. |
| exhibits | jsonb · not null | Ordered JSON array of every document in the submission as `[{"type":…,"sequence":…,"filename":…,"description":…}]`. The `<TYPE>FULL` entries are the audited financial statements as PDFs - this inventory is how a consumer reaches them (`https://www.sec.gov/Archives/edgar/data/{cik}/{accession-no-dashes}/{filename}`), and it is deliberately all this table stores of them. |
| report_document_count | integer · not null | How many `<TYPE>FULL` public-report PDFs the submission carries. 1 on a typical filing, 2 when a firm files two fiscal years at once, 0 on a paper stub. |
Access edgar_broker_dealer_reports
Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.
import obscura
client = obscura.Client("obs_live_…")
df = client.query(
dataset="edgar_broker_dealer_reports",
symbols=["NVDA", "AAPL"],
start="2024-01-01",
)
Create a free account Browse all 122 datasets
Frequently asked questions
What is in the edgar_broker_dealer_reports dataset?
Annual audited reports (Form X-17A-5) filed by every registered broker-dealer, including the independent accountant who signed the audit and whether a material weakness was reported - disclosed nowhere else, since these firms file no 8-K. Filings are routinely back-dated by months or years, so each row also carries the measured gap between the report's own date and the day the SEC actually published it. One **Form X-17A-5 Part III** annual audited report filed by a broker-dealer - the only public window into the balance sheet of an entity that, in the overwhelming majority of cases, files NOTHING ELSE on EDGAR. Every broker-dealer registered under Exchange Act Section 15 must file an annual report audited by an independent public accountant (Rule 17a-5(d)). The registrant is usually not a public company: it has no 10-K, no proxy, no XBRL and no ticker. This filing, and its `008-` broker-dealer registration number, is the whole of its public record. # THE FINANCIAL STATEMENTS ARE A PDF. THIS TABLE IS THE COVER SHEET. That was measured, not assumed. On every one of the 10 electronically filed X-17A-5 submissions in the 2024-02-14 dissemination feed, the financial content is a single `<TYPE>FULL` **PDF** (`Public.pdf`, `bhspub.pdf`, `cheval_12312023-fins3.pdf`, …) and there is no XBRL, no XML financial statement and no tagged FOCUS report anywhere in the submission. There is therefore no balance sheet to extract without OCR, and this table follows the `UPLOAD`/`CORRESP` precedent: it stores the METADATA SEC itself structures and the document manifest that points at the PDF, and it stores no financial figure at all. What that leaves is still the point of the dataset: * **`accountant_name` - WHO AUDITS THIS BROKER-DEALER, per year.** A change of auditor at a broker-dealer is a signal nothing else in the catalogue carries, because the registrant files no 8-K Item 4.01. * **`material_weakness` - the registrant's own Y/N declaration**, stated in the structured cover rather than buried in the PDF. * the fiscal period covered, the `008-` registration number, and the registrant's identity and domicile. # `is_paper` IS THE ROW'S MOST IMPORTANT FLAG, AND IT IS NOT AN ERA SEC accepts this form on PAPER as well as through EDGAR, and it publishes the paper ones as an auto-generated stub: accession `9999999997-YY-NNNNNN`, a `<PAPER>` header flag, one placeholder document naming a Document Control Number, and NO content whatsoever. Those rows carry the header columns and NULL for every structured-cover column, and `is_paper` says so. The paper and electronic populations COEXIST for a decade - they are not two eras with a boundary, which is why this is a per-row flag rather than a declared `regime`. Counted from the quarterly form indexes: 2011Q1 3,678 paper / 0 electronic; 2015Q2 376 / 0; **2016Q1 2,753 / 440** (the first electronic filings); 2018Q1 2,089 / 884; 2022Q1 1,308 / 1,338; 2025Q1 719 / 1,401; **2026Q1 0 / 2,136** (paper gone). See `docs/datasets/edgar_broker_dealer_reports.md` and `docs/availability/edgar_broker_dealer_reports.md`.
How do I avoid look-ahead bias with edgar_broker_dealer_reports?
Filter on edgar_broker_dealer_reports.available_date, the day the publisher made the row public. For this dataset that date is derived as follows - filing_join: available_date is the EDGAR DISSEMINATION day, taken from the bronze object's own day partition, NEVER from the header's FILED AS OF DATE. WHY: this family is the worst back-dating offender on EDGAR after the SEC-side correspondence forms - 87,521 of 104,685 X-17A-5 rows (83.6%) were disseminated LATER than the date they are stamped with, and the mechanism is the paper channel: SEC scans and releases paper filings in batches weeks or months after receipt. Measured on the 2024-02-14 feed day: 27 of the 28 paper submissions carry an earlier legal filing date, mean lag 91.3 days, MAX 1,447 days (a 2019-12-31 fiscal year stamped 2020-02-28 and first disseminated 2024-02-14); the 10 electronic submissions on the same day all carry zero lag. Using FILED AS OF DATE would therefore publish four years of look-ahead on a single row. Evidence class B (observed dissemination-day membership against a stated earlier filing date); see docs/availability/edgar_broker_dealer_reports.md. period_start/period_end are the AUDITED FISCAL PERIOD and are never availability anchors. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get edgar_broker_dealer_reports?
As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="edgar_broker_dealer_reports". The column schema is public at https://api.obscura.trade/v1/catalog/edgar_broker_dealer_reports.
Can I filter edgar_broker_dealer_reports by company or symbol?
Yes. edgar_broker_dealer_reports carries cik, the column the API's symbols filter resolves against.
How often is edgar_broker_dealer_reports updated?
Obscura refreshes edgar_broker_dealer_reports on a every 6 hours schedule - that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.