Fetch company financial records from SEC EDGAR
Project description
secfin
Fetch company financial records from SEC EDGAR.
Installation
pip install secfin
Or install from source:
pip install -e .
Quick Start
from secfin import SECClient, Company
# Initialize client (SEC requires User-Agent with contact info)
client = SECClient(user_agent="MyApp contact@email.com")
# Get company financials
company = Company("AAPL", client)
# Income Statement
income = company.get_income_statement()
print(f"Revenue: {income.revenue.latest()}")
print(f"Net Income: {income.net_income.latest()}")
# Balance Sheet
balance = company.get_balance_sheet()
print(f"Total Assets: {balance.total_assets.latest()}")
print(f"Cash: {balance.cash.latest()}")
# Cash Flow Statement
cashflow = company.get_cash_flow()
print(f"Operating Cash Flow: {cashflow.operating_cash_flow.latest()}")
print(f"Free Cash Flow: {cashflow.free_cash_flow.latest()}")
Features
- Income Statement: Revenue, Cost of Revenue, Gross Profit, R&D, SG&A, Operating Income, Net Income, EPS, Shares Outstanding
- Balance Sheet: Assets, Liabilities, Equity, Cash, Inventory, Debt
- Cash Flow: Operating, Investing, Financing cash flows, CapEx, Dividends, Free Cash Flow
- Analytics: TTM calculations, YoY growth, CAGR, margins, ratios
- Caching: Automatic disk caching to reduce API calls
- Async Support: Async batch fetching for improved performance
Data Export
Convert to pandas DataFrame:
# Get historical data as DataFrame
df = company.get_income_statement().to_dataframe()
print(df)
Get a summary of all financials:
summary = company.summary()
print(summary)
Quarterly vs Annual Data
# Annual data (10-K filings)
annual_income = company.get_income_statement(period="annual")
# Quarterly data (10-Q filings)
quarterly_income = company.get_income_statement(period="quarterly")
Financial Analytics
income = company.get_income_statement()
# Trailing Twelve Months (TTM)
ttm_revenue = income.revenue.ttm()
# Year-over-Year Growth
yoy_growth = income.revenue.growth() # Returns decimal (0.1 = 10%)
# Compound Annual Growth Rate
cagr_5yr = income.revenue.cagr(years=5)
# Margins
gross_margin = income.gross_margin()
operating_margin = income.operating_margin()
net_margin = income.net_margin()
# Balance Sheet Ratios
balance = company.get_balance_sheet()
current_ratio = balance.current_ratio()
debt_to_equity = balance.debt_to_equity()
Caching
Responses are cached locally to reduce API calls (default: 24 hours).
# Disable caching
client = SECClient("MyApp contact@email.com", cache_enabled=False)
# Custom cache TTL (1 hour)
client = SECClient("MyApp contact@email.com", cache_ttl=3600)
# Clear cache
client.clear_cache()
# View cache stats
print(client.cache_stats())
# {'files': 10, 'size_bytes': 5000000, 'size_mb': 4.77}
Async Batch Fetching
For faster fetching of large ticker lists:
import asyncio
from secfin import SECClient, AsyncBatchFetcher
client = SECClient("MyApp contact@email.com")
fetcher = AsyncBatchFetcher(client, max_concurrent=5)
# Async fetch
results = asyncio.run(fetcher.fetch_tickers(["AAPL", "MSFT", "GOOGL"]))
# Or use the sync wrapper
from secfin import run_async_fetch
results = run_async_fetch(client, ["AAPL", "MSFT", "GOOGL"])
Earnings Dates
Get historical and estimated future earnings dates:
company = Company("AAPL", client)
# Last earnings date
last = company.last_earnings()
print(f"Last Filing: {last['date']} ({last['form_type']})")
# Next earnings (estimated)
next_e = company.next_earnings()
print(f"Next Expected: {next_e['date']} ({next_e['fiscal_quarter']})")
# Historical earnings dates
history = company.earnings_history(limit=10)
for h in history:
print(f"{h['date']} | {h['form_type']} | {h['fiscal_quarter']}")
# Full earnings calendar
calendar = company.get_earnings_calendar()
print(f"Fiscal Year End: {calendar.fiscal_year_end}")
df = calendar.get_historical_df()
Example Output
Last Earnings:
Filing Date: 2026-01-30
Period End: 2025-12-27
Form Type: 10-Q
Quarter: Q1
Next Earnings (Estimated):
Expected Date: 2026-04-30
Form Type: 10-Q
Quarter: Q2
Rate Limiting
The client automatically respects SEC's rate limit (10 requests/second).
Batch Fetching - Index Constituents
Fetch financials for entire indices:
from secfin import SECClient, BatchFetcher
client = SECClient("MyApp contact@email.com")
fetcher = BatchFetcher(client)
# Fetch all S&P 500 companies (~500 companies)
sp500_data = fetcher.fetch_sp500()
# Fetch all NASDAQ 100 companies (~100 companies)
nasdaq_data = fetcher.fetch_nasdaq100()
# Fetch custom list of tickers
tickers = ["AAPL", "MSFT", "GOOGL", "AMZN", "META"]
custom_data = fetcher.fetch_tickers(tickers)
Progress Tracking
def my_progress(current, total, ticker, status):
print(f"Progress: {current}/{total} - {ticker}: {status}")
fetcher = BatchFetcher(client, on_progress=my_progress)
results = fetcher.fetch_nasdaq100()
Export to DataFrame
# Get summary DataFrame with key metrics
summary_df = fetcher.summary_dataframe(results)
print(summary_df)
# Get specific metric across all companies
revenue_df = fetcher.to_dataframe(results, "income_statement", "revenue")
print(revenue_df)
Available Indices
| Index | Method | Companies |
|---|---|---|
| S&P 500 | fetch_sp500() |
~500 |
| NASDAQ 100 | fetch_nasdaq100() |
~100 |
| Russell 2000 | fetch_russell2000(tickers) |
~2000 (requires ticker list) |
Russell 2000
Russell 2000 constituent list is not freely available. You need to provide your own list:
# Load your Russell 2000 tickers
russell_tickers = [...] # Your list of ~2000 tickers
results = fetcher.fetch_russell2000(tickers=russell_tickers)
Requirements
- Python 3.9+
- requests
- pandas
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file secfin-0.2.0.tar.gz.
File metadata
- Download URL: secfin-0.2.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cded0c22177b8516b498391aad22aae43000671651b09225d2a391fed3d61294
|
|
| MD5 |
0863ef6749f645a7e34ca651cbc9c1ae
|
|
| BLAKE2b-256 |
f1d0e58fc83ca6f099d6fd208931bd4b5fec98d6885aead00b75a6d3d8301b07
|
File details
Details for the file secfin-0.2.0-py3-none-any.whl.
File metadata
- Download URL: secfin-0.2.0-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f08613ae08e1c5818e4d8ac02faa50d1f0fe661f4ea97724dd24ca7c7a01281
|
|
| MD5 |
4295380a237e5ff9363731dbb87ce2ff
|
|
| BLAKE2b-256 |
2e28bab39d07b8c95ed748cc449b65e169d34eb2786fd3d31e04ade411043a83
|