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') -> RawResponseOne 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) -> RawResponseOne filed document as served (text: XML, HTML, a .txt).
fetch_fails
fetch_fails(year: int, month: int, half: str) -> RawResponseOne 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) -> RawResponseOne 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) -> RawResponseOne filing’s document directory as served.
fetch_fund_tickers
fetch_fund_tickers() -> RawResponseThe fund-class directory as served: {fields, data}.
fetch_latest
fetch_latest(form: str | None = None, count: int = 100, start: int = 0) -> RawResponseThe latest filings feed (Atom XML, one document), form narrowing it.
fetch_risk_return
fetch_risk_return(year: int, quarter: int) -> RawResponseOne quarter’s Risk/Return Summary data set as served: the zip, bytes (82 MB).
fetch_tickers
fetch_tickers() -> RawResponseThe 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() — pure5 · 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 read7 · 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-PORT8 · FILINGS latest() · daily_index() · filing_index() · document() · nport() — the fund block, its flows and holdings · ncen() — the registrant and its seriesCarried 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() -> Noneaopen
aopen() -> SECClientclass_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) -> strOne 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) -> RawResponseOne tag’s facts of one filer as served.
fetch_company_facts
fetch_company_facts(cik: Any) -> RawResponseEvery XBRL fact of one filer as served (megabytes for a large filer).
fetch_frame
fetch_frame(taxonomy: str, tag: str, unit: str, period: str) -> RawResponseEvery filer’s one fact for one period as served (CY2026Q2I, CY2025).
fetch_submissions
fetch_submissions(cik: Any) -> RawResponseOne filer’s submissions document as served; an unknown CIK is empty (404).
fetch_submissions_file
fetch_submissions_file(filename: str) -> RawResponseOne 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) -> strA 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) -> boolWhether 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 | NoneThe venue code an exchange’s own name maps to (EXCHANGE_WORDS); None when no word
names it, or there is no name.