Skip to content

data_updater_v2.data_clients.sec

SECClient — the SEC’s public data: EDGAR’s JSON APIs on data.sec.gov and its files and archives on www.sec.gov, no key, a User-Agent naming the caller (the SEC’s access rule; Settings.sec_user_agent), at most 10 requests a second (its published limit; both hosts count on one scope). Every fact below was probed live on 2026-10-18 (scratchpad probes/sec_probe.py) or read from the saved payloads in Data V2/.agents_tracking/sec-reference-2026-09-17 and profiles-samples-2026-09-19.

Routes and what they serve:

data.sec.gov submissions/CIK{cik}.json one filer: cik, name, entityType, sic, sicDescription, category, stateOfIncorporation, fiscalYearEnd, tickers, exchanges, ein, lei, website, formerNames (name, from, to), and its filings — recent as parallel arrays (form, filingDate, reportDate, accessionNumber, primaryDocument, isXBRL …; ~1,000 newest) plus files naming the older batches (submissions/ {filename}). The SPY trust’s lists NPORT-P monthly, N-CEN yearly, 485BPOS, 497. A CIK the SEC does not know: 404. api/xbrl/companyfacts/CIK{cik}.json every XBRL fact the filer reported, by taxonomy and tag, then unit: rows {end, val, accn, fy, fp, form, filed, frame; start for a duration} (Apple: 3.8 MB, 503 us-gaap tags; dei EntityCommonStockSharesOutstanding 70 rows, the count as of the cover date of each 10-Q/10-K, and EntityPublicFloat 19 rows, yearly). Point in time by construction: filed says when the number was known, frame the calendar period it stands for. api/xbrl/companyconcept/… one tag of one filer, the same rows. api/xbrl/frames/{tax}/{tag}/{unit}/{period}.json every filer’s one fact for one period (CY2026Q2I = the instant ending Q2 2026; CY2025 a year): rows {accn, cik, entityName, loc, end, val; start for a duration} — 4,428 companies’ shares outstanding in one call. A unit is spelled with dashes here (USD-per-shares); a date-typed tag is 404. www.sec.gov files/dera/data/mutual-fund-prospectus-risk/return-summary-data-sets/{yyyy}q{n}_rr1.zip the Risk/Return Summary data set, one quarter (82 MB: sub / num / txt / tag / lab / cal .tsv): every fund prospectus filed that quarter (485BPOS, 497), its facts per series and class — ExpensesOverAssets, NetExpensesOverAssets, ManagementFeesOverAssets, PortfolioTurnoverRate (fractions), the returns — and its text blocks (ObjectivePrimaryTextBlock, StrategyNarrativeTextBlock). A fund appears in the quarter it files its annual prospectus: four quarters cover every registered fund (probed 2026-10-19 on 2026q2: 2,313 filings, 537,808 facts, 638,111 texts). files/company_tickers_exchange.json {fields: [cik, name, ticker, exchange], data: [[…]]} 10,444 rows (Nasdaq, NYSE, OTC, none). files/company_tickers_mf.json fund classes: {fields: [cik, seriesId, classId, symbol], data}. cgi-bin/browse-edgar?action=getcurrent&output=atom the latest filings as an Atom feed (type, count, start): each entry’s title “FORM - NAME (CIK) (Filer)”, link to the filing index, updated. Archives/edgar/daily-index/{year}/QTR{q}/master.{yyyymmdd}.idx one day’s filings, pipe-separated after the header: CIK|Company Name|Form Type|Date Filed (yyyymmdd)| File Name; served as bytes. Archives/edgar/data/{cik}/{accession}/index.json one filing’s documents (directory.item[]: name, type, size, last-modified). Archives/edgar/data/{cik}/{accession}/{filename} one document as filed: an N-PORT’s primary_doc.xml (genInfo, fundInfo totAssets / totLiabs / netAssets and the three months’ flows mon1Flow..mon3Flow sales / redemption / reinvestment, invstOrSecs holdings with cusip, isin, balance, valUSD, pctVal); an N-CEN’s primary_doc.xml (the registrant, every series with its classes and tickers, fund types, the index-fund block, the adviser, the exchange and the creation unit size; the series terminated); a 10-Q’s XBRL instance ({name}htm.xml: every fact with its context — the cover count per CLASS for a multi-class filer, META’s class A 2,205,128,509 and class B 342,377,716 as of 2026-07-24, which companyconcept leaves out as dimensioned) and, beside the count, the cover’s 12(b) facts per registered class — dei:Security12bTitle, TradingSymbol, SecurityExchangeName, each in a context dimensioned by the class-of-stock axis (Apple: CommonStockMember AAPL NASDAQ and six note members with no ticker; META’s one class undimensioned): the ticker AS OF each filing, FB on the 10-Q filed 2022-04-28 and META on the one filed 2022-07-28 (the change was 2022-06-09). …/primary_doc.xml of a Form 25-NSE a notice of removal as XML (notificationOfRemoval, schema X0203 on 2026-10-13): the exchange (cik, entityName), the issuer (cik, entityName, fileNumber, address), descriptionClassSecurity (the class; a SPAC’s shares, units and warrants in one, semicolon-joined), ruleProvision (the 12d2-2 paragraph), signatureDate. The exchange AND the issuer each file one for the same removal (Bone Biologics’ warrant, EA Series Trust’s ETF, twice each on 2026-10-13). An issuer’s own Form 25 is HTML: the names, the class, the box it checked (x, Wingdings’ x, before the paragraph). …/{name}.htm of a Form 8-A12B a class registered on an exchange, HTML: the cover’s pairs of “Title of each class” and “Name of each exchange” (Common Stock, par value $0.01 per share / Texas Stock Exchange LLC; an ETF’s name / Cboe BZX Exchange, Inc.; a note / The Nasdaq Stock Market LLC) — never a ticker. 4 to 15 a day, Form 25 and 25-NSE 4 to 16 (2026-10-07 .. 10-16). files/data/fails-deliver-data/cnsfails{yyyymm}{a|b}.zip the fails-to-deliver file, a half month a zip (a = the 1st to the 15th, b = the 16th on; one text member: SETTLEMENT DATE|CUSIP|SYMBOL|QUANTITY (FAILS)| DESCRIPTION|PRICE, then two trailer lines with the record count and the total quantity; 66,693 rows in 2026-09b, 383 with the price ”.” = not available; the symbol glued as FINRA glues it, 26 placeholder codes like ARBXXXX, one row with no symbol at all — the CUSIP anchors every row). Published two to three weeks after the half ends (2026-09b up, 2026-10a 404 on 2026-10-19). The quarterly archives before July 2009 sit under frequently-requested-foia-document- fails-deliver-data/cnsp_sec_fails{yyyy}q{n}.zip. master.{yyyymmdd}.idx of a weekend, a holiday or today before the cut 403 with an AccessDenied XML body (not 404); a bare User-Agent is also 403, an HTML page.

Access: data.sec.gov answered a bare program name as User-Agent; www.sec.gov (the feed, the archives) answers 403 without the contact form the SEC asks for, “Name contact@domain” — Settings.sec_user_agent must carry one in production (probed 2026-10-18).

What the SEC says about corporate actions (probed 2026-10-19 on 18 filers and the frames, scratchpad probes/sec_actions_probe*.py): a cash dividend per share is reported per fiscal PERIOD — declared (CommonStockDividendsPerShareDeclared: 13 of 18 filers; 1,143 filers in the CY2025Q2 frame) and paid (CashPaid: 10 of 18; 469), the period’s TOTAL (AAPL 0.27 for the quarter ended 2026-06-27 is its one payout; O’s monthly payouts summed) — never an ex-date: companyfacts carries no date-typed fact at all (DividendsPayableDateOfRecordDayMonthAndYear absent in every filer; its frame 404), and the 8-K press release that names the record and payable days is prose (“payable on August 13, 2026, to shareholders of record as of the close of business on August 10, 2026”), there for 12 of 40 payers sampled over a year. A split is a ratio fact (StockholdersEquityNoteStockSplitConversionRatio1: 4 for a 4-for-1, 0.125 for a 1-for-8, 0.07 for Nektar’s 1-for-15 rounded to two places) whose context is an INSTANT the filer dated — CMG 2024-06-26 (our date, the first day on the new count), AAPL 2020-08-28, WMT 2024-02-23, AVGO 2024-07-12, GE 2021-07-30, SMCI 2024-09-30 (each the session before ours), TSLA 2020-08-10 and 2022-08-05 (the approval) — or a DURATION when it dates it no closer (NVDA’s 2024 10-for-1: the months of May and June, no instant); every later filing repeats the fact. So the SEC is the arbiter of the AMOUNT and the RATIO, not a calendar: FMP, EODHD and Nasdaq stay the calendars, and check_dividends / same_ratio read them against it. A listing is a Form 8-A12B (no ticker), a delisting a Form 25 (the class, the exchange, the paragraph), a ticker change shows on the next cover, a name change is formerNames, and a ticker that moved in the directory between two reads is directory_changes.

What the SEC does NOT serve: prices; a fund’s NAV or share count (N-PORT carries net assets and flows, N-CEN lists the classes without counts: the count is net assets over the close, the store’s); a 40-Act ETF in the COMPANY directory (QQQ, VTI, TECL, TLT are in the fund directory with their series and class; SPY, IBIT and GBTC — trusts, not 40-Act funds — are in the company one; 2 tickers of 38,000 sit in both; probed 2026-10-19).

Classes

EdgarClient

Bases: BaseClient

EDGAR’s files and archives on www.sec.gov (the ticker directories, the latest filings feed, the daily indexes, each filing’s documents). Carried state: the base’s only. SECClient owns one and speaks for it.

fetch_daily_index

fetch_daily_index(day: dt.date, kind: str = 'master') -> RawResponse

One day’s index file as served (master: pipe-separated; form, company: fixed width), one text document; a day with no file (a weekend) is 404: empty.

fetch_document

fetch_document(cik: Any, accession: str, filename: str) -> RawResponse

One filed document as served (text: XML, HTML, a .txt).

fetch_fails

fetch_fails(year: int, month: int, half: str) -> RawResponse

One half month’s fails-to-deliver zip as served (bytes); a half not published yet is 404: empty.

fetch_fails_quarter

fetch_fails_quarter(year: int, quarter: int) -> RawResponse

One pre-July-2009 quarter’s fails archive as served (bytes; the monthly text files inside); 2004Q1 sits under the newer path.

fetch_filing_index

fetch_filing_index(cik: Any, accession: str) -> RawResponse

One filing’s document directory as served.

fetch_fund_tickers

fetch_fund_tickers() -> RawResponse

The fund-class directory as served: {fields, data}.

fetch_latest

fetch_latest(form: str | None = None, count: int = 100, start: int = 0) -> RawResponse

The latest filings feed (Atom XML, one document), form narrowing it.

fetch_risk_return

fetch_risk_return(year: int, quarter: int) -> RawResponse

One quarter’s Risk/Return Summary data set as served: the zip, bytes (82 MB).

fetch_tickers

fetch_tickers() -> RawResponse

The ticker directory as served: {fields, data}.

SECClient

Bases: BaseClient

The SEC: EDGAR’s JSON APIs (this client, data.sec.gov) and its files and archives (the EdgarClient it owns, www.sec.gov), FMPClient’s section names where the SEC serves the section:

2 · UNIVERSE tickers() · fund_tickers() · ids() — our symbols to the
SEC's ids · profiles() — a company's profile from its
submissions · fund_profiles() — a fund trust's series from
its latest N-CEN · prospectus() — the Risk/Return facts and
objective per series from the quarterly data set ·
filings() — one filer's filings · listings() /
delistings() — the day's 8-A12B and Form 25 filings read ·
delisting_history() — one filer's Form 25s · cover() ·
symbol_history() / symbol_changes() — the ticker on each
cover and where it changed · name_changes() /
directory_changes() — pure
5 · CORPORATE ACTIONS dividends() — per period, declared and paid ·
dividends_calendar() — every filer's, one period ·
splits() · splits_calendar() — the ratio as filed, in the
tables' shape · dividends_declared() · dividends_paid() ·
split_ratios() — the raw facts · delisting_filings() ·
check_dividends() / same_ratio() — pure, the arbiter's read
7 · METRICS fails() · fails_quarter() — the fails-to-deliver files ·
shares() · floats() · concept() · facts() · frame() —
companyconcept, point in time · cover_counts() ·
class_shares() — the count per CLASS from the filings' own
XBRL, the multi-class filers' route · fund_metrics() — a
fund's net assets and monthly flows from every N-PORT
8 · FILINGS latest() · daily_index() · filing_index() · document() ·
nport() — the fund block, its flows and holdings · ncen() —
the registrant and its series

Carried state: the base’s, and the owned EdgarClient (built from the same config, limiter and transport unless handed in; opened and closed with this client).

aclose

aclose() -> None

aopen

aopen() -> SECClient

class_shares

class_shares(cik: Any, since: dt.date | None = None, forms: Iterable[str] = COVER_FORMS) -> list[dict[str, Any]]

A filer’s cover counts per class from every forms filing since since (None: every one the SEC lists), oldest first: cover_counts on each, with the filing’s form and filed day (the known-on day) beside each row. One index and one document per filing, CONCURRENCY at a time.

concept

concept(cik: Any, taxonomy: str, tag: str, unit: str | None = None) -> list[dict[str, Any]]

One tag’s facts of one filer, oldest end first: start (a duration’s), end, val, unit, accn, fy, fp, form, filed, frame. unit narrows (shares, USD, USD/shares). [] for a tag or CIK the SEC does not have.

cover

cover(cik: Any, accession: str) -> dict[str, Any]

One filing’s cover page from its own XBRL instance (_cover): registrant, period_end, document_type, classes (one row per class the cover registers under 12(b): member — the class-of-stock axis member, CommonStockMember, None when undimensioned — title, ticker (None for a note), exchange as the cover spells it, NASDAQ) and counts (cover_counts’ rows). {} with empty lists when the filing lists no instance.

cover_counts

cover_counts(cik: Any, accession: str) -> list[dict[str, Any]]

The share counts one filing’s cover carries, from its own XBRL instance (the {name}_htm.xml in the filing’s index; the primary document when an instance is not listed): one row per count — as_of (the instant), shares_class (the class member the fact is dimensioned by, CommonClassA, None for an undimensioned count), shares, accession. The route for a multi-class filer (META, GOOGL, BRK) whose counts companyconcept leaves out; one filer, one class: one row.

daily_index

daily_index(day: dt.date) -> list[dict[str, Any]]

Every filing of one day (the master index): cik (ten digits), company, form, filed, filename (the Archives path). [] on a day with no file: a weekend, a holiday, today before the file is cut — EDGAR answers those 403 with an AccessDenied body (probed 2026-10-19: Columbus Day, a Sunday, a Saturday, today), which is not the 403 a nameless caller gets (an HTML page: that one fails).

delisting_filings

delisting_filings(cik: Any, since: dt.date | None = None) -> list[dict[str, Any]]

The filer’s Form 25 filings (DELISTING_FORMS): a notice that a class left an exchange, dated by its filing; newest first.

delisting_history

delisting_history(cik: Any, since: dt.date | None = None) -> list[dict[str, Any]]

One filer’s Form 25 filings read (delistings’ rows), oldest first: the classes it had struck, from the exchange’s and its own notices, since since (None: every one the SEC lists). One index or document per filing.

delistings

delistings(start: dt.date, end: dt.date | None = None) -> list[dict[str, Any]]

Every class struck from an exchange (DELISTING_FORMS) in the daily indexes from start to end (None: start alone), each Form 25 read — a 25-NSE as XML (_removal), an issuer’s own Form 25 as HTML (_removal_form) — oldest first, in one shape (_removed): cik (the ISSUER’s, whoever filed), name (the issuer’s as the form spells it), date (the filing day), effective (REMOVAL_DAYS later: when the removal takes effect; the last trade is on or before the filing), title (the class as filed; a SPAC’s shares, units and warrants in one), paper, exchange, exchange_name, rule (the paragraph relied on: “(a)(2)”, “(b)”, “(c)”), reason (the paragraph in the rule’s words, RULE_12D2_2), filers (who filed, exchange and issuer — both file one for the same removal; read as ONE row), accession (the first read), form.

dividends

dividends(cik: Any) -> list[dict[str, Any]]

Cash dividends per share as the filer reported them per fiscal period, oldest first, one row per period (_periods): period_start, period_end, declared (CommonStockDividendsPerShareDeclared), paid (...CashPaid; None when the filer reports only the other), fy, fp, form, filed, accession, frame (the calendar period the SEC assigns: CY2026Q2 a quarter, CY2025 a year; None for a year-to-date span) — each value the latest filing’s (a later 10-Q repeats a quarter as a comparative; a restated value replaces). A period’s TOTAL — AAPL’s quarter is its one payout, a monthly payer’s three — never an ex-date: the check beside the calendars (check_dividends), not a calendar. Two concept calls.

dividends_calendar

dividends_calendar(year: int, quarter: int | None = None) -> list[dict[str, Any]]

Every filer’s cash dividend per share declared and paid in one calendar period (the frames CY{year}Q{quarter}, or the year), one row per filer: cik, entity, loc (the SEC’s state or country, US-IL), period_start, period_end, declared, paid, accn. The whole market in two calls (1,143 filers declared in CY2025Q2, 469 paid). A frame holds each filer’s one fact that best fits the period: a fiscal quarter off the calendar one (2025-03-30 .. 2025-06-28) sits under it.

dividends_declared

dividends_declared(cik: Any) -> list[dict[str, Any]]

Cash dividends per share declared, as the filer reported them per period (CommonStockDividendsPerShareDeclared), oldest first: start, end, val, fy, fp, form, filed, frame. A period’s total, never an ex-date: the check beside the calendars, not a calendar.

dividends_paid

dividends_paid(cik: Any) -> list[dict[str, Any]]

Cash dividends per share paid per period (CommonStockDividendsPerShareCashPaid), oldest first; fewer filers report it than declared.

document

document(cik: Any, accession: str, filename: str) -> str

One filed document’s text as served. A primary document the submissions list names under a rendering prefix (xslFormNPORT-P_X01/primary_doc.xml, xslF25X02/primary_doc.xml) is asked raw, the prefix dropped: the prefixed path answers 303 to the rendered page.

facts

facts(cik: Any) -> dict[str, dict[str, list[dict[str, Any]]]]

Every XBRL fact of one filer, taxonomy -> tag -> rows (_fact_rows: one row per fact, the unit on it), from the companyfacts document; {} for a CIK the SEC does not know. Megabytes for a large filer: ask concept for one tag.

fails

fails(year: int, month: int, half: str) -> list[dict[str, Any]]

One half month’s fails to deliver (fetch_fails), oldest first, every row the file carries: settlement_date, cusip (the row’s anchor), symbol (ours, as FINRA’s glued spelling reads: AHLPRD -> AHL-PD, BCSSWS -> BCSS-WT; None for a placeholder code or no symbol at all), symbol_as_told, quantity (shares failed), name (the description), price (None where the file says ”.”). [] for a half the SEC has not published (404). The trailer’s record count is checked: a file cut short fails (ValueError).

fails_quarter

fails_quarter(year: int, quarter: int) -> list[dict[str, Any]]

One pre-July-2009 quarter’s fails to deliver (fetch_fails_quarter: every monthly file in the archive), oldest first, in fails’ shape.

fetch_company_concept

fetch_company_concept(cik: Any, taxonomy: str, tag: str) -> RawResponse

One tag’s facts of one filer as served.

fetch_company_facts

fetch_company_facts(cik: Any) -> RawResponse

Every XBRL fact of one filer as served (megabytes for a large filer).

fetch_frame

fetch_frame(taxonomy: str, tag: str, unit: str, period: str) -> RawResponse

Every filer’s one fact for one period as served (CY2026Q2I, CY2025).

fetch_submissions

fetch_submissions(cik: Any) -> RawResponse

One filer’s submissions document as served; an unknown CIK is empty (404).

fetch_submissions_file

fetch_submissions_file(filename: str) -> RawResponse

One older filings batch (filings.files[].name) as served.

filing_index

filing_index(cik: Any, accession: str) -> list[dict[str, Any]]

One filing’s documents: name, type, size, last_modified.

filings

filings(cik: Any, forms: Iterable[str] | None = None, since: dt.date | None = None, older: bool = False, items: Iterable[str] | None = None) -> list[dict[str, Any]]

One filer’s filings, newest first: form, filing_date, report_date, accession (dashed, as the SEC prints it), primary_document, description, is_xbrl, items (an 8-K’s item numbers: 2.02 results, 3.01 a delisting notice, 5.03 a charter amendment — a name change or a reverse split, 8.01 other events). forms narrows (10-Q, NPORT-P, 25-NSE), items keeps the filings reporting any of those items, since bounds the filing date; older also reads the older batches the document names (one call each) — the recent list holds about the last 1,000 filings.

floats

floats(cik: Any) -> list[dict[str, Any]]

Public float as filed (dei:EntityPublicFloat, dollars as of the second quarter’s last business day, one a year on the 10-K), oldest first.

frame

frame(taxonomy: str, tag: str, unit: str, period: str) -> list[dict[str, Any]]

Every filer’s one fact for one period: cik (ten digits), entity, loc, start (a duration’s; None for an instant), end, val, accn — the whole market’s shares outstanding as of a quarter in one call (frame("dei", "EntityCommonStockSharesOutstanding", "shares", "CY2026Q2I"): 4,428 filers). [] for a period or tag with nothing.

fund_metrics

fund_metrics(cik: Any, series: str | None = None, since: dt.date | None = None) -> list[dict[str, Any]]

A fund registrant’s net assets and flows from every N-PORT filed since since (None: every one, monthly since 2019; the filings are public a quarter at a time), one row per month end, oldest first: series_id, series, date (the month’s last day), net_assets, total_assets, total_liabilities (the report period’s last month only: N-PORT carries them as of that day), sales, redemption, reinvestment, net_flow (sales less redemptions, the month’s total), period (the report date), accession, filed. series narrows a multi-series trust to one series id. The count behind a month is net assets over our close on the month’s last day, the store’s (SPY 2026-06-30: 781.2B). No NAV: the SEC does not serve one.

fund_profiles

fund_profiles(ciks: Iterable[Any]) -> dict[str, dict[str, Any] | None]

Each fund registrant’s series from its latest N-CEN, CIK (ten digits) -> ncen()’s read with filed and accession beside it: the registrant (name, lei), every series (series_id, name, lei, classes [{class_id, name, ticker}], fund_types, is_index_fund, is_index_fund_exclusive, adviser, adviser_lei, exchanges [{exchange, ticker}], creation_unit_shares, is_first_filing) and the series terminated. None for a CIK with no N-CEN (a unit investment trust files none: SPY). One filings read and one document per registrant, CONCURRENCY at a time.

fund_tickers

fund_tickers() -> list[dict[str, Any]]

The SEC’s fund-class directory: cik (the registrant’s), series_id, class_id, symbol — a fund ticker to its registrant, series and class.

ids

ids(symbols: Iterable[str]) -> dict[str, dict[str, Any] | None]

Our symbols -> the SEC’s ids, from both directories in two calls: cik (ten digits), name, exchange (the company directory’s word: Nasdaq, NYSE, CBOE, TXSE, OTC, None), series_id and class_id (the fund directory’s, a 40-Act fund’s), directory (companies, funds, or both when a symbol sits in both — 2 of 38,000 on 2026-10-19). None for a symbol neither lists (QQQ is a fund, SPY a company; a coin, an index, a commodity: never). The directories spell a ticker as we do (BRK-B, JPM-PC, VAL-WT, KCAC-UN, CELG-RI) or Nasdaq’s way (BEATW, a warrant: papers.spell_sec reads both); a spelling that is no US ticker is left out.

latest

latest(form: str | None = None, count: int = 100) -> list[dict[str, Any]]

The latest filings on EDGAR (form narrows: 8-K, 25-NSE, NPORT-P), newest first: form, company, cik, accession, filed (the feed’s timestamp), link. The “what was filed today” sensor.

listings

listings(start: dt.date, end: dt.date | None = None) -> list[dict[str, Any]]

Every class registered on an exchange (LISTING_FORMS) in the daily indexes from start to end (None: start alone), each filing’s cover read (_registrations), oldest first: cik (the registrant’s, ten digits), name (as the index spells it), date (the filing day), title (the class as the cover spells it: “Common Stock, par value $0.01 per share”, an ETF’s name, a note), paper (what the title says it is, papers.paper), exchange (the venue code, venue), exchange_name (as filed), form, accession. No ticker: the form carries none — the CIK and the class join it to ours. One index per day; one index and one document per filing, CONCURRENCY at a time; a filing whose cover reads no pair is a row with title None (the reader names it, never drops it).

ncen

ncen(cik: Any, accession: str, filename: str = 'primary_doc.xml') -> dict[str, Any]

One N-CEN filing read: registrant (name, lei, cik, classification, total_series, terminated [{series_id, name, terminated}]) and series (one row a series: series_id, name, lei, classes [{class_id, name, ticker}], fund_types, is_index_fund (the index-fund block is present), is_index_fund_exclusive, adviser, adviser_lei, is_first_filing, exchanges [{exchange, ticker}], creation_unit_shares). The annual census of a fund trust, as filed: what each fund is, who runs it, where it trades; no counts, no NAV.

nport

nport(cik: Any, accession: str, filename: str = 'primary_doc.xml') -> dict[str, Any]

One N-PORT filing read: fund (registrant, cik, lei, series, series_id, period (the report date), total_assets, total_liabilities, net_assets) and holdings (one row a position: name, lei, title, cusip, isin, ticker, balance, units, currency, value_usd, pct_value, payoff, asset_category, issuer_category, country). The fund’s month-end net assets and its holdings, as filed.

profiles

profiles(ciks: Iterable[Any]) -> dict[str, dict[str, Any] | None]

Each filer’s profile from its submissions document, CIK (ten digits) -> profile, None for a CIK the SEC does not know: name, entity_type, sic, sic_description, category, state (of incorporation), fiscal_year_end (MMDD), tickers, exchanges, ein, lei, website, former_names ([{name, from, to}], dates), and filings: the recent filings as filings() shapes them. Asked as one batch.

prospectus

prospectus(year: int, quarter: int, series: Iterable[str] | None = None) -> list[dict[str, Any]]

The Risk/Return Summary facts of every fund prospectus filed in one quarter (the data set, one 82 MB zip read in memory), one row per series and class as filed: series_id, class_id (None for a series-level fact), accession, period (ddate, the prospectus’s fiscal date), document (the prospectus the fact sits in), expense_ratio, net_expense_ratio, management_fee, turnover (fractions and rates as the fund files them: VTI 0.0003, a turnover above one is a fund that turned over more than once), objective and strategy (the text blocks, series-level). series narrows to those series ids (every row otherwise: ~12,700 series a quarter). A fund appears in the quarter it files its annual prospectus, so four quarters cover every fund; a quarter whose set is not published yet (the running one: a 403 AccessDenied, EDGAR’s word for a missing file) is []. A value filed at one or more is not a fraction and is left as told: the reader judges.

shares

shares(cik: Any) -> list[dict[str, Any]]

Shares outstanding as filed: the count on each 10-Q and 10-K cover (dei: EntityCommonStockSharesOutstanding), oldest first — end (the as-of day), val, filed (when it was known), form, frame, accn. The history of the count that a market cap multiplies, never restated.

split_ratios

split_ratios(cik: Any) -> list[dict[str, Any]]

Stock split ratios the filer reported (StockholdersEquityNoteStockSplitConversionRatio1, 4 for a 4-for-1), oldest first; a filer reports it in the period of the split, or not at all.

splits

splits(cik: Any) -> list[dict[str, Any]]

Stock splits as the filer reported them (the ratio fact), oldest first, in the split table’s shape (_split_rows): date (the context’s INSTANT — the filer’s effective day, within a session of the first day on the new count: CMG 2024-06-26 on it, AAPL 2020-08-28 the session before — or the period’s END when the filer dates it no closer), period_start (None for an instant), split_to, split_from (4 for 1; a ratio below one is a reverse — 0.125 is 1 for 8; a rounded 0.07 is 1 for 14.29 as told, and same_ratio reads it against a vendor’s 1 for 15), ratio (as told), form, filed, accession, frame. The same split repeated by later filings is one row (the first filing’s); a ratio of one is taken out (actions.sound_splits); a split dated by its period and again by an instant is two rows — the instant is the dated one.

splits_calendar

splits_calendar(year: int, quarter: int) -> list[dict[str, Any]]

Every filer’s split ratio dated in one calendar quarter (the INSTANT frame CY{year}Q{quarter}I: 57 filers in CY2024Q2, WMT’s 3 on 2024-02-23 in CY2024Q1I), one row per filer in splits’ shape: cik, entity, loc, date, period_start (None), split_to, split_from, ratio, accn. A filer that dated its split only by a period (NVDA’s 2024 10-for-1) is not here: splits on its CIK reads it.

symbol_changes

symbol_changes(cik: Any, since: dt.date | None = None) -> list[dict[str, Any]]

Where a filer’s ticker changed between two consecutive covers (symbol_history), oldest first: old_symbol, new_symbol, after (the last cover filed under the old), by (the first filed under the new: the change lies between), title, name (the registrant on the later cover). A class is followed by its axis member, else by its title; when one ticker leaves and one arrives between two covers with no class to pair them, they are paired. The SEC dates a change by its covers, not to the day: the calendars’ rows within (after, by] confirm it.

symbol_history

symbol_history(cik: Any, since: dt.date | None = None, forms: Iterable[str] = COVER_FORMS) -> list[dict[str, Any]]

The ticker on every forms cover the filer filed since since (None: all), oldest first, one row per class with a ticker: filed (the known-on day), period_end, form, accession, member, title, ticker, exchange, registrant. The SEC’s own record of what a filer traded as, filing by filing (FB then META). One index and one document per filing, CONCURRENCY at a time.

tickers

tickers() -> list[dict[str, Any]]

The SEC’s ticker directory: cik (ten digits), name, ticker (the SEC spells a class with a dash, BRK-B, as we do), exchange (Nasdaq, NYSE, OTC, or None). 10,444 rows on 2026-10-18. FetchError when it does not come back whole.

Functions

check_dividends

check_dividends(payouts: Iterable[Mapping[str, Any]], periods: Iterable[Mapping[str, Any]]) -> list[dict[str, Any]]

Our payouts (the dividend table’s rows: ex_date, amount, declaration_date, payment_date) against the filer’s periods (dividends’ rows): per period, the payouts that fall in it and whether their sum is what the filer declared and paid (actions.same_amount). A payout is declared in the period holding its declaration date (its ex-date when none is told) and paid in the one holding its payment date (its ex-date when none). The periods read are the SEC’s quarters (frame CY2026Q2) when the filer has them, else its years (CY2025): a year-to-date span would count a quarter twice. Rows: period_start, period_end, frame, declared, declared_sum, declared_agrees (None when the filer declared nothing for the period), paid, paid_sum, paid_agrees, payouts (the ex-dates counted as declared).

cik10

cik10(value: Any) -> str

A CIK as the SEC’s JSON routes spell it: ten digits, zero-padded (320193 -> 0000320193). Digits only; anything else raises.

directory_changes

directory_changes(before: Iterable[Mapping[str, Any]], after: Iterable[Mapping[str, Any]]) -> dict[str, list[dict[str, Any]]]

Two reads of the ticker directory (tickers), earlier and later, compared by (cik, ticker): renamed — one ticker gone and one new under the same CIK (cik, name, old_symbol, new_symbol); added and removed — the rest, as directory rows. A CIK with several tickers gone or new at once is not paired: its rows stay added and removed.

fund_gearing

fund_gearing(name: str | None, objective: str | None = None, fund_types: Iterable[str] | None = None) -> tuple[float | None, bool | None]

A fund’s signed daily multiplier and whether it is geared, from whichever of the SEC’s and the vendors’ words says it: the fund’s NAME first (papers.gearing), else the prospectus OBJECTIVE the Risk/Return summary carries (gearing_from_objective: “300% of the daily performance”), else N-CEN’s geared fund type, which says geared and not the number (None, True). A plain fund never says it is plain: the name’s reading (1, False) stands when nothing says otherwise; (None, None) when there is no name.

name_changes

name_changes(profile: Mapping[str, Any]) -> list[dict[str, Any]]

A filer’s name changes from its profile’s former_names (profiles), oldest first: old_name, new_name (the next former name, then the current), date (the day the old name ended, as the SEC dates it: Facebook Inc -> Meta Platforms, Inc. on 2021-10-27; the ticker followed on 2022-06-09).

same_ratio

same_ratio(told: float | None, other: float | None) -> bool

Whether a ratio the SEC carries (written as the filer rounded it: 0.07 for a 1-for-15, 0.125 for a 1-for-8, 0.06667 at five places) is a vendor’s price factor: equal within half a unit of the told value’s last decimal place.

venue

venue(exchange_name: Any) -> str | None

The venue code an exchange’s own name maps to (EXCHANGE_WORDS); None when no word names it, or there is no name.