Skip to content

Commit 849d255

Browse files
committed
feat: Add fluent Company interface for SEC EDGAR access
- Implemented the Company class to provide a convenient wrapper around SEC-registered companies, allowing access to metadata, filings, submissions, and XBRL data using ticker symbols or CIK numbers. - Introduced structured response models (Filing, CompanyInfo, Submission) to wrap raw API responses with typed properties for easier access and manipulation. - Added example usage scripts demonstrating the new Company interface and structured models. - Developed comprehensive unit tests for the Company class and response models to ensure functionality and reliability.
1 parent 796e80b commit 849d255

9 files changed

Lines changed: 1482 additions & 72 deletions

File tree

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818
- **samples/use_tickers_and_download.py**: Sample file demonstrating ticker resolution, company search, and filing download.
1919
- **tests/test_tickers.py**: 14 unit tests for the `Tickers` service (resolve, reverse lookup, search, caching, error handling).
2020
- **tests/test_download.py**: 9 unit tests for `download()` (text/binary content, save-to-file, error handling, client delegation).
21+
- **edgar/company.py**: New fluent `Company` class for ticker-based SEC EDGAR access.
22+
- `client.company("AAPL")` resolves ticker or CIK → `Company` object with `cik`, `ticker`, `name` properties.
23+
- `company.filings(form="10-K")` — fluent chaining to get filings without separate service objects.
24+
- `company.submissions()` — fetch full submission history.
25+
- `company.xbrl_facts()` — fetch XBRL company facts.
26+
- `company.download(url)` — download filing documents.
27+
- Accepts both ticker symbols (`"AAPL"`) and CIK numbers (`"320193"`).
28+
- **client.py**: `company()` method on `EdgarClient` for fluent company access. Existing `filings()` / `companies()` methods remain for backward compatibility.
29+
- **tests/test_company.py**: 21 unit tests for the `Company` class (construction, properties, fluent methods, client integration, backward compat).
30+
- **edgar/models.py**: New structured dataclass response models — `Filing`, `CompanyInfo`, `Submission`.
31+
- `Filing` wraps filing search result dicts with `form_type`, `filing_date`, `url`, `accession_number`, `title`, `summary` properties.
32+
- `CompanyInfo` wraps submissions metadata with `name`, `cik`, `tickers`, `sic`, `sic_description`, `recent_filings`, `recent_submissions` properties.
33+
- `Submission` wraps individual filing records with `form`, `filing_date`, `accession_number`, `report_date`, `is_xbrl`, `size` properties.
34+
- All models expose `.raw` attribute for backward compatibility with raw dict access.
35+
- All models are frozen (immutable) with `__repr__` for REPL/notebook discoverability.
36+
- **company.py**: `get_filings(form=None)``list[Filing]` and `get_info()``CompanyInfo` convenience methods returning structured models.
37+
- **tests/test_models.py**: 23 unit tests for all three models and the Company integration methods.
38+
- **README.md**: Complete rewrite with hero example, full service table (15 services), usage examples for ticker resolution, fluent Company API, XBRL, filing search, downloads, response models, and badge row.
2139

2240
### Changed
2341
- Migrated from `setup.py` to `pyproject.toml` for modern packaging.

README.md

Lines changed: 125 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,169 @@
11
# Python SEC
22

3-
## Table of Contents
3+
[![PyPI version](https://img.shields.io/pypi/v/python-sec.svg)](https://pypi.org/project/python-sec/)
4+
[![Python versions](https://img.shields.io/pypi/pyversions/python-sec.svg)](https://pypi.org/project/python-sec/)
5+
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
46

5-
- [Overview](#overview)
6-
- [Setup](#setup)
7-
- [Usage](#usage)
8-
- [Support These Projects](#support-these-projects)
7+
A lightweight Python client for the SEC EDGAR API. Look up companies by ticker, search filings, download documents, and query XBRL financial data — all in a few lines of code.
98

10-
## Overview
9+
## Quick Start
1110

12-
Current Version: **0.1.6**
11+
```bash
12+
pip install python-sec
13+
```
1314

14-
The Securities & Exchange Commission (SEC) has a treasure trove of business data available to indviduals
15-
for free. However, the biggest obstacle to getting this free data boils down to two challenges:
15+
```python
16+
from edgar.client import EdgarClient
1617

17-
1. Figuring out where it is
18-
2. Figuring out how to extract it
18+
# SEC requires a User-Agent identifying you.
19+
client = EdgarClient(user_agent="Your Name your-email@example.com")
1920

20-
The Python SEC library (`edgar`) is designed to make the collection and the extraction of SEC data quick
21-
and effortless. The library was designed around some of the following goals:
21+
# Look up Apple's 10-K filings — by ticker, no CIK needed.
22+
company = client.company("AAPL")
23+
filings = company.get_filings(form="10-K")
2224

23-
1. Making the usage of the EDGAR search system, in a prgorammatic fashion, more intuitive.
24-
2. Making the definition of queries more customizeable while still maintaining the overall clearity
25-
of the library.
26-
3. Standardize the returning content so that content is organized consistently and ensuring gaps in data
27-
are filled in or extended that way navigating to other directories or files can be done dynamically.
28-
4. Simplify the parsing of XBRL files so that data can be more easily manipulated.
25+
print(filings[0])
26+
# <Filing form='10-K' date='2024-11-01' title='10-K - Annual report ...'>
2927

30-
## Setup
28+
# Get structured company metadata.
29+
info = company.get_info()
30+
print(info.name, info.tickers, info.sic_description)
31+
# Apple Inc. ['AAPL'] ELECTRONIC COMPUTERS
3132

32-
**Setup - PyPi Install:**
33+
# Access XBRL facts.
34+
facts = company.xbrl_facts()
35+
```
3336

34-
To **install** the library, run the following command from the terminal.
37+
## Installation
3538

36-
```console
37-
pip install python-sec
39+
```bash
40+
pip install python-sec # from PyPI
41+
pip install --upgrade python-sec # upgrade
42+
pip install -e . # local dev (editable mode)
3843
```
3944

40-
**Setup - PyPi Upgrade:**
45+
## Services
46+
47+
| Service | Access | Description |
48+
| ---------------------- | -------------------------------------- | ---------------------------------------------------------- |
49+
| **Company** | `client.company("AAPL")` | Fluent interface — ticker/CIK → filings, submissions, XBRL |
50+
| **Tickers** | `client.resolve_ticker("AAPL")` | Resolve tickers ↔ CIK numbers, search by company name |
51+
| **Filings** | `client.filings()` | Search filings by CIK, form type, date range, company name |
52+
| **Companies** | `client.companies()` | Query companies by state, country, SIC code, name |
53+
| **Submissions** | `client.submissions()` | Full filing history for any entity via the REST API |
54+
| **XBRL** | `client.xbrl()` | Company facts, concepts, and cross-company frames |
55+
| **Archives** | `client.archives()` | Browse EDGAR archive directories |
56+
| **Current Events** | `client.current_events()` | Recent RSS filing feeds |
57+
| **Datasets** | `client.datasets()` | DERA financial datasets |
58+
| **Issuers** | `client.issuers()` | Issuer information |
59+
| **Mutual Funds** | `client.mutual_funds()` | Mutual fund filings |
60+
| **Series** | `client.series()` | Investment company series |
61+
| **Ownership Filings** | `client.ownership_filings()` | Insider ownership (Forms 3/4/5) |
62+
| **Variable Insurance** | `client.variable_insurance_products()` | Variable insurance product filings |
63+
| **Download** | `client.download(url)` | Fetch any filing document (HTML, XML, PDF) |
64+
65+
## Usage Examples
66+
67+
### Ticker Resolution
4168

42-
To **upgrade** the library, run the following command from the terminal.
69+
```python
70+
# Ticker → CIK
71+
cik = client.resolve_ticker("MSFT") # "0000789019"
4372

44-
```console
45-
pip install --upgrade python-sec
73+
# CIK → company info
74+
entries = client.resolve_cik("789019")
75+
# [{'cik_str': 789019, 'ticker': 'MSFT', 'title': 'MICROSOFT CORP'}]
76+
77+
# Search by company name
78+
results = client.tickers().search("Tesla")
4679
```
4780

48-
**Setup - Local Install:**
81+
### Company Research (Fluent API)
82+
83+
```python
84+
company = client.company("META")
4985

50-
If you are planning to make modifications to this project or you would like to access it
51-
before it has been indexed on `PyPi`. I would recommend you either install this project
52-
in `editable` mode or do a `local install`. For those of you, who want to make modifications
53-
to this project. I would recommend you install the library in `editable` mode.
86+
# Structured Filing objects with typed properties.
87+
filings = company.get_filings(form="10-K")
88+
for f in filings[:3]:
89+
print(f.form_type, f.filing_date[:10], f.url)
5490

55-
If you want to install the library in `editable` mode, make sure to run the `setup.py`
56-
file, so you can install any dependencies you may need. To run the `setup.py` file,
57-
run the following command in your terminal.
91+
# Structured CompanyInfo with typed properties.
92+
info = company.get_info()
93+
print(info.name, info.sic_description, info.fiscal_year_end)
5894

59-
```console
60-
pip install -e .
95+
# Recent submissions as Submission objects.
96+
for sub in info.recent_submissions[:5]:
97+
print(sub.form, sub.filing_date, sub.accession_number)
6198
```
6299

63-
If you don't plan to make any modifications to the project but still want to use it across
64-
your different projects, then do a local install.
100+
### Filing Search
65101

66-
```console
67-
pip install .
68-
```
102+
```python
103+
filings_service = client.filings()
104+
105+
# By CIK
106+
filings_service.get_filings_by_cik(cik="320193")
69107

70-
This will install all the dependencies listed in the `setup.py` file. Once done
71-
you can use the library wherever you want.
108+
# By form type
109+
filings_service.get_filings_by_type(cik="320193", filing_type="10-K")
72110

73-
## Usage
111+
# Complex query with date range
112+
filings_service.query(
113+
cik="320193",
114+
filing_type="10-Q",
115+
after_date="2023-01-01",
116+
before_date="2024-01-01",
117+
)
118+
```
74119

75-
Here is a simple example of using the `edgar` library to grab different groups of filings.
120+
### XBRL Financial Data
76121

77122
```python
78-
from pprint import pprint
79-
from edgar.client import EdgarClient
80-
from edgar.enums import StateCodes
81-
from edgar.enums import CountryCodes
82-
from edgar.enums import StandardIndustrialClassificationCodes
123+
xbrl = client.xbrl()
83124

84-
# Initialize the Edgar Client
85-
# SEC EDGAR requires a User-Agent in the format "Company/Name email@example.com".
86-
edgar_client = EdgarClient(user_agent="Your Name your-email@example.com")
125+
# All facts for a company.
126+
facts = xbrl.company_facts(cik="320193")
87127

88-
# Initialize the Company Services.
89-
company_services = edgar_client.companies()
128+
# A single concept across time.
129+
revenue = xbrl.company_concepts(cik="320193", concept="us-gaap/Revenue")
90130

91-
# Grab all the companies that are based in Texas.
92-
pprint(company_services.get_companies_by_state(state_code='TX'))
131+
# Cross-company comparison for a single period.
132+
frame = xbrl.frames(taxonomy="us-gaap", concept="AccountsPayableCurrent", uom="USD", period="CY2023Q1I")
133+
```
93134

94-
# Alternatively, if you didn't know the 2 letter code you could pass through an Enum.
95-
pprint(
96-
company_services.get_companies_by_state(
97-
state_code=StateCodes.WEST_VIRGINIA
98-
)
99-
)
135+
### Download Filing Documents
100136

101-
# Grab all the companies that are based in Australia, same logic here with the Enums.
102-
pprint(
103-
company_services.get_companies_by_country(
104-
country_code=CountryCodes.AUSTRALIA
105-
)
106-
)
137+
```python
138+
# Download as text.
139+
html = client.download("https://www.sec.gov/Archives/edgar/data/320193/filing.htm")
140+
141+
# Download and save to file.
142+
client.download("https://www.sec.gov/Archives/edgar/data/320193/filing.htm", path="filing.html")
143+
144+
# Download through the Company interface.
145+
company = client.company("AAPL")
146+
filings = company.get_filings(form="10-K")
147+
content = company.download(filings[0].url)
107148
```
108149

150+
## Response Models
151+
152+
The library provides structured dataclass models alongside raw dictionary access:
153+
154+
| Model | Wraps | Key Properties |
155+
| ------------- | ------------------------- | ------------------------------------------------------------------------- |
156+
| `Filing` | Filing search results | `form_type`, `filing_date`, `url`, `accession_number`, `title`, `summary` |
157+
| `CompanyInfo` | Submissions metadata | `name`, `cik`, `tickers`, `sic`, `sic_description`, `recent_submissions` |
158+
| `Submission` | Individual filing records | `form`, `filing_date`, `accession_number`, `report_date`, `is_xbrl` |
159+
160+
All models expose a `.raw` attribute containing the original dictionary for backward compatibility.
161+
109162
## Support These Projects
110163

111164
**Patreon:**
112165
Help support this project and future projects by donating to my [Patreon Page](https://www.patreon.com/sigmacoding). I'm
113-
always looking to add more content for individuals like yourself, unfortuantely some of the APIs I would require me to
166+
always looking to add more content for individuals like yourself, unfortunately some of the APIs would require me to
114167
pay monthly fees.
115168

116169
**YouTube:**

edgar/client.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from edgar.series import Series
55
from edgar.issuers import Issuers
66
from edgar.filings import Filings
7+
from edgar.company import Company
78
from edgar.datasets import Datasets
89
from edgar.archives import Archives
910
from edgar.tickers import Tickers
@@ -213,6 +214,31 @@ def tickers(self) -> Tickers:
213214
self._services["tickers"] = Tickers(session=self.edgar_session)
214215
return self._services["tickers"]
215216

217+
def company(self, identifier: str) -> Company:
218+
"""Creates a ``Company`` object from a ticker symbol or CIK number.
219+
220+
### Parameters
221+
----
222+
identifier : str
223+
A stock ticker symbol (e.g. ``"AAPL"``) or a CIK number
224+
(e.g. ``"320193"``).
225+
226+
### Returns
227+
----
228+
Company:
229+
A fluent ``Company`` object for chaining.
230+
231+
### Usage
232+
----
233+
>>> edgar_client.company("AAPL").filings(form="10-K")
234+
"""
235+
236+
return Company(
237+
identifier=identifier,
238+
session=self.edgar_session,
239+
tickers_service=self.tickers(),
240+
)
241+
216242
def resolve_ticker(self, ticker: str) -> str:
217243
"""Convenience method to resolve a ticker symbol to a CIK string.
218244

0 commit comments

Comments
 (0)