Support EdgarTools to access and analyze SEC Edgar filings, XBRL financial statements, 10-K, 10-Q, and 8-K reports

This commit is contained in:
Timothy Kassis
2026-02-23 13:02:15 -08:00
parent f8da4bf9a7
commit 0ffa12a0e2
10 changed files with 2332 additions and 7 deletions

View File

@@ -0,0 +1,274 @@
# edgartools — AI Integration Reference
## Table of Contents
- [Installation](#installation)
- [MCP Server Setup](#mcp-server-setup)
- [MCP Tools Reference](#mcp-tools-reference)
- [Built-in AI Features](#built-in-ai-features)
- [Skills for Claude](#skills-for-claude)
- [Troubleshooting](#troubleshooting)
---
## Installation
```bash
# Core library
uv pip install edgartools
# For MCP server and Skills
uv pip install "edgartools[ai]"
```
---
## MCP Server Setup
The MCP server gives any MCP-compatible client (Claude Desktop, Cursor, Cline, Continue.dev) direct access to SEC data.
### Option 1: uvx (Recommended — zero install)
Add to your MCP config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"edgartools": {
"command": "uvx",
"args": ["--from", "edgartools[ai]", "edgartools-mcp"],
"env": {
"EDGAR_IDENTITY": "Your Name your.email@example.com"
}
}
}
}
```
If you get "spawn uvx ENOENT" on macOS, use the full path: `which uvx`.
### Option 2: Python (when edgartools already installed)
```json
{
"mcpServers": {
"edgartools": {
"command": "python3",
"args": ["-m", "edgar.ai"],
"env": {
"EDGAR_IDENTITY": "Your Name your.email@example.com"
}
}
}
}
```
On Windows, use `python` instead of `python3`.
### Option 3: Docker
```dockerfile
FROM python:3.12-slim
RUN pip install "edgartools[ai]"
ENV EDGAR_IDENTITY="Your Name your.email@example.com"
ENTRYPOINT ["python", "-m", "edgar.ai"]
```
```bash
docker build -t edgartools-mcp .
docker run -i edgartools-mcp
```
### Verify Setup
```bash
python -m edgar.ai --test
```
---
## MCP Tools Reference
### edgar_company
Get company profile, financials, recent filings, and ownership in one call.
| Parameter | Description |
|-----------|-------------|
| `identifier` | Ticker, CIK, or company name (required) |
| `include` | Sections: `profile`, `financials`, `filings`, `ownership` |
| `periods` | Number of financial periods (default: 4) |
| `annual` | Annual vs quarterly (default: true) |
Example prompts:
- "Show me Apple's profile and latest financials"
- "Get Microsoft's recent filings and ownership data"
### edgar_search
Search for companies or filings.
| Parameter | Description |
|-----------|-------------|
| `query` | Search keywords (required) |
| `search_type` | `companies`, `filings`, or `all` |
| `identifier` | Limit to specific company |
| `form` | Filter by form type (e.g., `10-K`, `8-K`) |
| `limit` | Max results (default: 10) |
### edgar_filing
Read filing content or specific sections.
| Parameter | Description |
|-----------|-------------|
| `accession_number` | SEC accession number |
| `identifier` + `form` | Alternative: company + form type |
| `sections` | `summary`, `business`, `risk_factors`, `mda`, `financials`, or `all` |
Example prompts:
- "Show me the risk factors from Apple's latest 10-K"
- "Get the MD&A section from Tesla's most recent annual report"
### edgar_compare
Compare companies side-by-side or by industry.
| Parameter | Description |
|-----------|-------------|
| `identifiers` | List of tickers/CIKs |
| `industry` | Industry name (alternative to identifiers) |
| `metrics` | Metrics to compare (e.g., `revenue`, `net_income`) |
| `periods` | Number of periods (default: 4) |
### edgar_ownership
Insider transactions, institutional holders, or fund portfolios.
| Parameter | Description |
|-----------|-------------|
| `identifier` | Ticker, CIK, or fund CIK (required) |
| `analysis_type` | `insiders`, `institutions`, or `fund_portfolio` |
| `days` | Lookback for insider trades (default: 90) |
| `limit` | Max results (default: 20) |
---
## Built-in AI Features
These work without the `[ai]` extra.
### .docs Property
Every major object has searchable API docs:
```python
from edgar import Company
company = Company("AAPL")
company.docs # Full API reference
company.docs.search("financials") # Search specific topic
# Also available on:
filing.docs
filings.docs
xbrl.docs
statement.docs
```
### .to_context() Method
Token-efficient output for LLM context windows:
```python
company = Company("AAPL")
# Control detail level
company.to_context(detail='minimal') # ~100 tokens
company.to_context(detail='standard') # ~300 tokens (default)
company.to_context(detail='full') # ~500 tokens
# Hard token limit
company.to_context(max_tokens=200)
# Also available on:
filing.to_context(detail='standard')
filings.to_context(detail='minimal')
xbrl.to_context(detail='standard')
statement.to_context(detail='full')
```
---
## Skills for Claude
Skills teach Claude to write better edgartools code by providing patterns and best practices.
### Install for Claude Code (auto-discovered)
```python
from edgar.ai import install_skill
install_skill() # installs to ~/.claude/skills/edgartools/
```
### Install for Claude Desktop (upload as project knowledge)
```python
from edgar.ai import package_skill
package_skill() # creates edgartools.zip
# Upload the ZIP to a Claude Desktop Project
```
### Skill Domains
| Domain | What It Covers |
|--------|----------------|
| **core** | Company lookup, filing search, API routing, quick reference |
| **financials** | Financial statements, metrics, multi-company comparison |
| **holdings** | 13F filings, institutional portfolios |
| **ownership** | Insider transactions (Form 4), ownership summaries |
| **reports** | 10-K, 10-Q, 8-K document sections |
| **xbrl** | XBRL fact extraction, statement rendering |
### When to Use Which
| Goal | Use |
|------|-----|
| Ask Claude questions about companies/filings | MCP Server |
| Have Claude write edgartools code | Skills |
| Both | Install both — they complement each other |
---
## Filing to Markdown for LLM Processing
```python
company = Company("NVDA")
filing = company.get_filings(form="10-K").latest()
# Export to markdown for LLM analysis
md = filing.markdown(include_page_breaks=True)
with open("nvidia_10k_for_analysis.md", "w") as f:
f.write(md)
print(f"Saved {len(md)} characters")
```
---
## Troubleshooting
**"EDGAR_IDENTITY environment variable is required"**
Add your name and email to the `env` section of your MCP config. The SEC requires identification.
**"Module edgar.ai not found"**
Install with AI extras: `uv pip install "edgartools[ai]"`
**"python3: command not found" (Windows)**
Use `python` instead of `python3` in MCP config.
**MCP server not appearing in Claude Desktop**
1. Check config file location for your OS
2. Validate JSON syntax
3. Restart Claude Desktop completely
4. Run `python -m edgar.ai --test` to verify
**Skills not being picked up**
1. Verify: `ls ~/.claude/skills/edgartools/`
2. For Claude Desktop, upload as ZIP to a Project
3. Skills affect code generation, not conversational responses

View File

@@ -0,0 +1,268 @@
# edgartools — Companies Reference
## Table of Contents
- [Finding Companies](#finding-companies)
- [Company Properties](#company-properties)
- [Filing Access](#filing-access)
- [Financial Data Methods](#financial-data-methods)
- [Company Screening](#company-screening)
- [Advanced Search](#advanced-search)
- [Company API Reference](#company-api-reference)
- [Error Handling](#error-handling)
---
## Finding Companies
### By Ticker (case-insensitive)
```python
from edgar import Company
company = Company("AAPL")
company = Company("aapl") # same result
```
### By CIK (fastest, most reliable)
```python
company = Company(320193)
company = Company("320193")
company = Company("0000320193") # zero-padded
```
### By Name Search
```python
from edgar import find
results = find("Apple")
# Returns list: use results[0] or iterate
for c in results:
print(f"{c.ticker}: {c.name}")
apple = results[0]
```
### Multiple Share Classes
```python
brk_a = Company("BRK-A") # Class A
brk_b = Company("BRK-B") # Class B
# Both share the same CIK
```
---
## Company Properties
```python
company = Company("MSFT")
company.name # "Microsoft Corporation"
company.cik # 789019
company.display_name # "MSFT - Microsoft Corporation"
company.ticker # "MSFT"
company.tickers # ["MSFT"] (list of all tickers)
company.industry # "SERVICES-PREPACKAGED SOFTWARE"
company.sic # "7372"
company.fiscal_year_end # "0630" (June 30)
company.exchange # "Nasdaq"
company.website # "https://www.microsoft.com"
company.city # "Redmond"
company.state # "WA"
company.shares_outstanding # float (from SEC company facts)
company.public_float # float in dollars
company.is_company # True
company.not_found # False if found
```
---
## Filing Access
### get_filings()
```python
# All filings
filings = company.get_filings()
# Filter by form type
annual = company.get_filings(form="10-K")
multi = company.get_filings(form=["10-K", "10-Q"])
# Filter by date
recent = company.get_filings(filing_date="2023-01-01:")
range_ = company.get_filings(filing_date="2023-01-01:2023-12-31")
# Filter by year/quarter
q4 = company.get_filings(year=2023, quarter=4)
multi_year = company.get_filings(year=[2022, 2023])
# Other filters
xbrl_only = company.get_filings(is_xbrl=True)
original = company.get_filings(amendments=False)
```
**Parameters:**
- `form` — str or list of str
- `year` — int, list, or range
- `quarter` — 1, 2, 3, or 4
- `filing_date` / `date` — "YYYY-MM-DD" or "YYYY-MM-DD:YYYY-MM-DD"
- `amendments` — bool (default True)
- `is_xbrl` — bool
- `is_inline_xbrl` — bool
- `sort_by` — field name (default "filing_date")
**Returns:** `EntityFilings` collection
### latest()
```python
latest_10k = company.latest("10-K") # single Filing
latest_3 = company.latest("10-Q", 3) # list of Filings
```
### Convenience Properties
```python
tenk = company.latest_tenk # TenK object or None
tenq = company.latest_tenq # TenQ object or None
```
---
## Financial Data Methods
```python
# Annual (from latest 10-K)
financials = company.get_financials()
# Quarterly (from latest 10-Q)
quarterly = company.get_quarterly_financials()
# XBRL facts
facts = company.get_facts() # Returns EntityFacts
```
---
## Company Screening
```python
import pandas as pd
from edgar import Company
tickers = ["AAPL", "MSFT", "NVDA", "AMZN", "META"]
rows = []
for ticker in tickers:
company = Company(ticker)
rows.append({
'ticker': ticker,
'name': company.name,
'industry': company.industry,
'shares_outstanding': company.shares_outstanding,
'public_float': company.public_float,
})
df = pd.DataFrame(rows)
df = df.sort_values('public_float', ascending=False)
# Filter mega-caps (float > $1T)
mega_caps = df[df['public_float'] > 1e12]
```
---
## Advanced Search
### By Industry (SIC code)
```python
from edgar.reference import get_companies_by_industry
software = get_companies_by_industry(sic=7372)
```
### By Exchange
```python
from edgar.reference import get_companies_by_exchanges
nyse = get_companies_by_exchanges("NYSE")
nasdaq = get_companies_by_exchanges("Nasdaq")
```
### By State
```python
from edgar.reference import get_companies_by_state
delaware = get_companies_by_state("DE")
```
---
## Company API Reference
### Constructor
```python
Company(cik_or_ticker: Union[str, int])
```
Raises `CompanyNotFoundError` if not found.
### Address Methods
```python
addr = company.business_address()
# addr.street1, addr.city, addr.state_or_country, addr.zipcode
addr = company.mailing_address()
```
### Utility Methods
```python
ticker = company.get_ticker() # primary ticker
exchanges = company.get_exchanges() # list of exchange names
company_data = company.data # EntityData with former_names, entity_type, flags
```
### Factory Functions
```python
from edgar import get_company, get_entity
company = get_company("AAPL") # same as Company("AAPL")
entity = get_entity("AAPL")
```
---
## Error Handling
```python
from edgar import Company
try:
company = Company("INVALID")
except Exception as e:
# fallback to search
results = find("Invalid Corp")
if results:
company = results[0]
# Check if found
company = Company("MAYBE_INVALID")
if company.not_found:
print("Not available")
else:
filings = company.get_filings()
```
---
## Batch Processing
```python
tickers = ["AAPL", "MSFT", "GOOGL"]
companies = []
for ticker in tickers:
try:
company = Company(ticker)
companies.append({
'ticker': ticker,
'name': company.name,
'cik': company.cik,
'industry': company.industry,
})
except Exception as e:
print(f"Error with {ticker}: {e}")
```
## Performance Tips
1. Use CIK when possible — faster than ticker lookup
2. Cache Company objects; avoid repeated API calls
3. Filter filings with specific parameters in `get_filings()`
4. Use reasonable date ranges to limit result sets

View File

@@ -0,0 +1,237 @@
# edgartools — Data Objects Reference
Every SEC filing can be parsed into a structured Python object:
```python
obj = filing.obj() # returns TenK, EightK, ThirteenF, Form4, etc.
```
## Supported Forms
### Annual & Quarterly Reports (10-K / 10-Q) → TenK / TenQ
```python
tenk = filing.obj() # or tenq for 10-Q
# Financial statements
tenk.income_statement # formatted income statement
tenk.balance_sheet # balance sheet
tenk.financials # Financials object with all statements
# Document sections
tenk.risk_factors # full risk factors text
tenk.business # business description
tenk.mda # management discussion & analysis
# Usage via Financials
if tenk.financials:
income = tenk.financials.income_statement
balance = tenk.financials.balance_sheet
cashflow = tenk.financials.cash_flow_statement
```
**Note:** Always check `tenk.financials` before accessing — not all filings have XBRL data.
---
### Current Events (8-K) → EightK
```python
eightk = filing.obj()
eightk.items # list of reported event codes (e.g. ["2.02", "9.01"])
eightk.press_releases # attached press releases
print(f"Items: {eightk.items}")
```
Common 8-K item codes:
- `1.01` — Entry into material agreement
- `2.02` — Results of operations (earnings)
- `5.02` — Director/officer changes
- `8.01` — Other events
---
### Insider Trades (Form 4) → Form4 (Ownership)
```python
form4 = filing.obj()
form4.reporting_owner # insider name
form4.transactions # buy/sell details with prices, shares, dates
# Get HTML table
html = form4.to_html()
```
Also covers:
- Form 3 — Initial ownership statement
- Form 5 — Annual changes in beneficial ownership
---
### Beneficial Ownership (SC 13D / SC 13G) → Schedule13D / Schedule13G
```python
schedule = filing.obj()
schedule.total_shares # aggregate beneficial ownership
schedule.items.item4_purpose_of_transaction # activist intent (13D only)
schedule.items.item5_interest_in_securities # ownership percentage
```
- **SC 13D**: Activist investors (5%+ with intent to influence)
- **SC 13G**: Passive holders (5%+)
---
### Institutional Portfolios (13F-HR) → ThirteenF
```python
thirteenf = filing.obj()
thirteenf.infotable # full holdings DataFrame
thirteenf.total_value # portfolio market value
# Analyze holdings
holdings_df = thirteenf.infotable
print(holdings_df.head())
print(f"Total AUM: ${thirteenf.total_value/1e9:.1f}B")
```
---
### Proxy & Governance (DEF 14A) → ProxyStatement
```python
proxy = filing.obj()
proxy.executive_compensation # pay tables (5-year DataFrame)
proxy.proposals # shareholder vote items
proxy.peo_name # "Mr. Cook" (principal exec officer)
proxy.peo_total_comp # CEO total compensation
```
---
### Private Offerings (Form D) → FormD
```python
formd = filing.obj()
formd.offering # offering details and amounts
formd.recipients # related persons
```
---
### Crowdfunding Offerings (Form C) → FormC
```python
formc = filing.obj()
formc.offering_information # target amount, deadline, securities
formc.annual_report_disclosure # issuer financials (C-AR)
```
---
### Insider Sale Notices (Form 144) → Form144
```python
form144 = filing.obj()
form144.proposed_sale_amount # shares to be sold
form144.securities # security details
```
---
### Fund Voting Records (N-PX) → FundReport
```python
npx = filing.obj()
npx.votes # vote records by proposal
```
---
### ABS Distribution Reports (Form 10-D) → TenD (CMBS only)
```python
ten_d = filing.obj()
ten_d.loans # loan-level DataFrame
ten_d.properties # property-level DataFrame
ten_d.asset_data.summary() # pool statistics
```
---
### Municipal Advisors (MA-I) → MunicipalAdvisorForm
```python
mai = filing.obj()
mai.advisor_name # advisor details
```
---
### Foreign Private Issuers (20-F) → TwentyF
```python
twentyf = filing.obj()
twentyf.financials # financial data for foreign issuers
```
---
## Complete Form → Class Mapping
| Form | Class | Key Attributes |
|------|-------|----------------|
| 10-K | TenK | `financials`, `income_statement`, `risk_factors`, `business` |
| 10-Q | TenQ | `financials`, `income_statement`, `balance_sheet` |
| 8-K | EightK | `items`, `press_releases` |
| 20-F | TwentyF | `financials` |
| 3 | Form3 | initial ownership |
| 4 | Form4 | `reporting_owner`, `transactions` |
| 5 | Form5 | annual ownership changes |
| DEF 14A | ProxyStatement | `executive_compensation`, `proposals`, `peo_name` |
| 13F-HR | ThirteenF | `infotable`, `total_value` |
| SC 13D | Schedule13D | `total_shares`, `items` |
| SC 13G | Schedule13G | `total_shares` |
| NPORT-P | NportFiling | fund portfolio |
| 144 | Form144 | `proposed_sale_amount`, `securities` |
| N-PX | FundReport | `votes` |
| Form D | FormD | `offering`, `recipients` |
| Form C | FormC | `offering_information` |
| 10-D | TenD | `loans`, `properties`, `asset_data` |
| MA-I | MunicipalAdvisorForm | `advisor_name` |
---
## How It Works
```python
from edgar import Company
apple = Company("AAPL")
filing = apple.get_latest_filing("10-K")
tenk = filing.obj() # returns TenK with all sections and financials
```
If a form type is not yet supported, `filing.obj()` raises `UnsupportedFilingTypeError`.
## Pattern for Unknown Form Types
```python
obj = filing.obj()
if obj is None:
# Fallback to raw content
text = filing.text()
html = filing.html()
xbrl = filing.xbrl()
```

View File

@@ -0,0 +1,372 @@
# edgartools — EntityFacts Reference
Structured access to SEC company financial facts with AI-ready features, querying, and professional formatting.
## Table of Contents
- [EntityFacts Class](#entityfacts-class)
- [FactQuery — Fluent Query Builder](#factquery--fluent-query-builder)
- [FinancialStatement Class](#financialstatement-class)
- [FinancialFact Class](#financialfact-class)
- [Common Patterns](#common-patterns)
---
## EntityFacts Class
### Getting EntityFacts
```python
from edgar import Company
company = Company("AAPL")
facts = company.get_facts() # Returns EntityFacts object
```
### Core Properties
```python
facts.cik # 320193
facts.name # "Apple Inc."
len(facts) # total number of facts
# DEI properties (from SEC filings)
facts.shares_outstanding # float or None
facts.public_float # float or None
facts.shares_outstanding_fact # FinancialFact with full metadata
facts.public_float_fact # FinancialFact with full metadata
```
### Financial Statement Methods
```python
# Income statement
stmt = facts.income_statement() # FinancialStatement (4 annual periods)
stmt = facts.income_statement(periods=8) # 8 periods
stmt = facts.income_statement(annual=False) # quarterly
df = facts.income_statement(as_dataframe=True) # return DataFrame directly
# Balance sheet
stmt = facts.balance_sheet()
stmt = facts.balance_sheet(periods=4)
stmt = facts.balance_sheet(as_of=date(2024, 12, 31)) # point-in-time
# Cash flow
stmt = facts.cash_flow()
stmt = facts.cashflow_statement(periods=5, annual=True)
# Parameters:
# periods (int): number of periods (default: 4)
# annual (bool): True=annual, False=quarterly (default: True)
# period_length (int): months — 3=quarterly, 12=annual
# as_dataframe (bool): return DataFrame instead of FinancialStatement
# as_of (date): balance sheet only — point-in-time snapshot
```
### Query Interface
```python
query = facts.query()
# Returns FactQuery builder — see FactQuery section
```
### Get Single Fact
```python
revenue_fact = facts.get_fact('Revenue')
q1_revenue = facts.get_fact('Revenue', '2024-Q1')
# Returns FinancialFact or None
```
### Time Series
```python
revenue_ts = facts.time_series('Revenue', periods=8) # DataFrame
```
### DEI / Entity Info
```python
# DEI facts DataFrame
dei_df = facts.dei_facts()
dei_df = facts.dei_facts(as_of=date(2024, 12, 31))
# Entity info dict
info = facts.entity_info()
print(info['entity_name'])
print(info['shares_outstanding'])
```
### AI / LLM Methods
```python
# Comprehensive LLM context
context = facts.to_llm_context(
focus_areas=['profitability', 'growth'], # or 'liquidity'
time_period='5Y' # 'recent', '5Y', '10Y', 'all'
)
# MCP-compatible tool definitions
tools = facts.to_agent_tools()
```
### Iteration
```python
for fact in facts:
print(f"{fact.concept}: {fact.numeric_value}")
```
---
## FactQuery — Fluent Query Builder
Create via `facts.query()`. All filter methods return `self` for chaining.
### Concept Filtering
```python
query = facts.query()
# Fuzzy matching (default)
q = query.by_concept('Revenue')
# Exact matching
q = query.by_concept('us-gaap:Revenue', exact=True)
# By human-readable label
q = query.by_label('Total Revenue', fuzzy=True)
q = query.by_label('Revenue', fuzzy=False)
```
### Time-Based Filtering
```python
# Fiscal year
q = query.by_fiscal_year(2024)
# Fiscal period
q = query.by_fiscal_period('FY') # 'FY', 'Q1', 'Q2', 'Q3', 'Q4'
q = query.by_fiscal_period('Q1')
# Period length in months
q = query.by_period_length(3) # quarterly
q = query.by_period_length(12) # annual
# Date range
q = query.date_range(start=date(2023, 1, 1), end=date(2024, 12, 31))
# Point-in-time
q = query.as_of(date(2024, 6, 30))
# Latest n periods
q = query.latest_periods(4, annual=True)
q = query.latest_instant() # most recent balance sheet items
```
### Statement / Form Filtering
```python
q = query.by_statement_type('IncomeStatement')
q = query.by_statement_type('BalanceSheet')
q = query.by_statement_type('CashFlow')
q = query.by_form_type('10-K')
q = query.by_form_type(['10-K', '10-Q'])
```
### Quality Filtering
```python
q = query.high_quality_only() # audited facts only
q = query.min_confidence(0.9) # confidence score 0.0-1.0
```
### Sorting
```python
q = query.sort_by('filing_date', ascending=False)
q = query.sort_by('fiscal_year')
```
### Execution
```python
# Execute and return facts
facts_list = query.execute() # List[FinancialFact]
count = query.count() # int (no fetch)
latest_n = query.latest(5) # List[FinancialFact] (most recent)
# Convert to DataFrame
df = query.to_dataframe()
df = query.to_dataframe('label', 'numeric_value', 'fiscal_period')
# Pivot by period
stmt = query.pivot_by_period() # FinancialStatement
df = query.pivot_by_period(return_statement=False) # DataFrame
# LLM context
llm_data = query.to_llm_context()
```
### Full Chaining Example
```python
results = facts.query()\
.by_concept('Revenue')\
.by_fiscal_year(2024)\
.by_form_type('10-K')\
.sort_by('filing_date')\
.execute()
```
---
## FinancialStatement Class
Wrapper around DataFrame with intelligent formatting and display.
### Properties
```python
stmt = company.income_statement()
stmt.shape # (10, 4) — rows x periods
stmt.columns # period labels: ['FY 2024', 'FY 2023', ...]
stmt.index # concept names: ['Revenue', 'Cost of Revenue', ...]
stmt.empty # bool
```
### Methods
```python
# Get numeric DataFrame for calculations
numeric_df = stmt.to_numeric()
growth_rates = numeric_df.pct_change(axis=1)
# Get specific concept across periods
revenue_series = stmt.get_concept('Revenue') # pd.Series or None
# Calculate period-over-period growth
growth = stmt.calculate_growth('Revenue', periods=1) # pd.Series
# Format a value
formatted = stmt.format_value(1234567, 'Revenue') # "$1,234,567"
# LLM context
context = stmt.to_llm_context()
```
### Display
- Jupyter: automatic HTML rendering with professional styling
- Console: formatted text with proper alignment
- Compatible with Rich library
---
## FinancialFact Class
Individual fact with full metadata.
### Core Attributes
```python
fact = facts.get_fact('Revenue')
fact.concept # "us-gaap:Revenue"
fact.taxonomy # "us-gaap"
fact.label # "Revenue"
fact.value # raw value
fact.numeric_value # float for calculations
fact.unit # "USD", "shares", etc.
fact.scale # 1000, 1000000, etc.
```
### Temporal Attributes
```python
fact.period_start # date (for duration facts)
fact.period_end # date
fact.period_type # "instant" or "duration"
fact.fiscal_year # int
fact.fiscal_period # "FY", "Q1", "Q2", "Q3", "Q4"
```
### Filing Context
```python
fact.filing_date # date filed
fact.form_type # "10-K", "10-Q", etc.
fact.accession # SEC accession number
```
### Quality
```python
fact.data_quality # DataQuality.HIGH / MEDIUM / LOW
fact.is_audited # bool
fact.confidence_score # float 0.0-1.0
```
### AI Attributes
```python
fact.semantic_tags # List[str]
fact.business_context # str description
```
### Methods
```python
context = fact.to_llm_context() # dict for LLM
formatted = fact.get_formatted_value() # "365,817,000,000"
period_key = fact.get_display_period_key() # "Q1 2024", "FY 2023"
```
---
## Common Patterns
### Multi-Period Income Analysis
```python
from edgar import Company
company = Company("AAPL")
facts = company.get_facts()
# 4 annual periods
stmt = facts.income_statement(periods=4, annual=True)
print(stmt)
# Convert to numeric for calculations
numeric = stmt.to_numeric()
revenue_growth = numeric.loc['Revenue'].pct_change()
print(revenue_growth)
```
### Query Latest Revenue Facts
```python
latest_revenue = facts.query()\
.by_concept('Revenue')\
.latest_periods(4, annual=True)\
.to_dataframe()
```
### Error Handling
```python
from edgar.entity.core import NoCompanyFactsFound
try:
facts = company.get_facts()
except NoCompanyFactsFound:
print("No facts available")
# Methods return None gracefully
stmt = facts.income_statement() # None if no data
if stmt and not stmt.empty:
# process
pass
```

View File

@@ -0,0 +1,387 @@
# edgartools — Filings Reference
## Table of Contents
- [Getting a Filing](#getting-a-filing)
- [Filing Properties](#filing-properties)
- [Accessing Content](#accessing-content)
- [Structured Data](#structured-data)
- [Attachments & Exhibits](#attachments--exhibits)
- [Search Within a Filing](#search-within-a-filing)
- [Viewing & Display](#viewing--display)
- [Save, Load & Export](#save-load--export)
- [Filings Collection API](#filings-collection-api)
- [Filtering & Navigation](#filtering--navigation)
---
## Getting a Filing
```python
from edgar import Company, get_filings, get_by_accession_number, Filing
# From a company
company = Company("AAPL")
filing = company.get_filings(form="10-K").latest()
# Global search
filings = get_filings(2024, 1, form="10-K")
filing = filings[0]
filing = filings.latest()
# By accession number
filing = get_by_accession_number("0000320193-23-000106")
# Direct construction (rarely needed)
filing = Filing(
form='10-Q',
filing_date='2024-06-30',
company='Tesla Inc.',
cik=1318605,
accession_no='0001628280-24-028839'
)
```
---
## Filing Properties
### Basic Properties
```python
filing.cik # 320193
filing.company # "Apple Inc."
filing.form # "10-K"
filing.filing_date # "2023-11-03"
filing.period_of_report # "2023-09-30"
filing.accession_no # "0000320193-23-000106"
filing.accession_number # alias for accession_no
```
### EntityFiling Extra Properties (from company.get_filings())
```python
filing.acceptance_datetime # datetime
filing.file_number # "001-36743"
filing.size # bytes
filing.primary_document # filename
filing.is_xbrl # bool
filing.is_inline_xbrl # bool
```
### URL Properties
```python
filing.homepage_url # SEC index page URL
filing.filing_url # primary document URL
filing.text_url # text version URL
filing.base_dir # base directory for all files
```
---
## Accessing Content
```python
html = filing.html() # HTML string or None
text = filing.text() # plain text (clean)
md = filing.markdown() # markdown string
xml = filing.xml() # XML string or None (ownership forms)
full = filing.full_text_submission() # complete SGML submission
# Markdown with page breaks (good for LLM processing)
md = filing.markdown(include_page_breaks=True, start_page_number=1)
```
---
## Structured Data
### Get Form-Specific Object (Primary Method)
```python
obj = filing.obj() # or filing.data_object()
# Returns: TenK, TenQ, EightK, Form4, ThirteenF, ProxyStatement, etc.
```
**IMPORTANT:** The base `Filing` class has NO `financials` property.
```python
# WRONG:
filing.financials # AttributeError!
# CORRECT:
tenk = filing.obj()
if tenk and tenk.financials:
income = tenk.financials.income_statement
```
### Form → Class Mapping
| Form | Class | Module |
|------|-------|--------|
| 10-K | TenK | edgar.company_reports |
| 10-Q | TenQ | edgar.company_reports |
| 8-K | EightK | edgar.company_reports |
| 20-F | TwentyF | edgar.company_reports |
| 4 | Form4 | edgar.ownership |
| 3 | Form3 | edgar.ownership |
| 5 | Form5 | edgar.ownership |
| DEF 14A | ProxyStatement | edgar.proxy |
| 13F-HR | ThirteenF | edgar.holdings |
| SC 13D/G | Schedule13 | edgar.ownership |
| NPORT-P | NportFiling | edgar.nport |
| 144 | Form144 | edgar.ownership |
### Get XBRL Data
```python
xbrl = filing.xbrl() # Returns XBRL object or None
if xbrl:
income = xbrl.statements.income_statement()
balance = xbrl.statements.balance_sheet()
cashflow = xbrl.statements.cash_flow_statement()
```
---
## Attachments & Exhibits
### List Attachments
```python
attachments = filing.attachments
print(f"Total: {len(attachments)}")
for att in attachments:
print(f"{att.sequence}: {att.description}")
print(f" Type: {att.document_type}")
print(f" File: {att.document}")
```
### Primary Document
```python
primary = filing.document
```
### Access by Index or Name
```python
first = filing.attachments[0]
specific = filing.attachments["ex-10_1.htm"]
```
### Download Attachments
```python
filing.attachments[0].download("./downloads/")
filing.attachments.download("./downloads/") # all
```
### Work with Exhibits
```python
exhibits = filing.exhibits
for exhibit in exhibits:
print(f"Exhibit {exhibit.exhibit_number}: {exhibit.description}")
if exhibit.exhibit_number == "10.1":
exhibit.download("./exhibits/")
```
---
## Search Within a Filing
```python
# Simple text search
results = filing.search("artificial intelligence")
print(f"Found {len(results)} mentions")
# Regex search
emails = filing.search(
r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
regex=True
)
# Financial terms
revenue_mentions = filing.search("revenue")
risk_factors = filing.search("risk factor")
critical = filing.search(r'\b(material weakness|restatement)\b', regex=True)
```
### Document Sections
```python
sections = filing.sections() # list of section names
doc = filing.parse() # parse to Document for advanced ops
```
---
## Viewing & Display
```python
filing.view() # display in console/Jupyter with Rich
filing.open() # open primary doc in browser
filing.open_homepage() # open SEC index page
filing.serve(port=8080) # serve locally at http://localhost:8080
```
---
## Save, Load & Export
```python
# Save
filing.save("./data/filings/") # auto-generates filename
filing.save("./data/apple_10k.pkl") # specific file
# Load
filing = Filing.load("./data/apple_10k.pkl")
# Export
data = filing.to_dict()
summary_df = filing.summary()
# Download raw
filing.download(data_directory="./raw_filings/", compress=False)
```
---
## Filings Collection API
### get_filings() — Global Search
```python
from edgar import get_filings
filings = get_filings(2024, 1, form="10-K") # Q1 2024 10-Ks
filings = get_filings(2023, form="10-K") # all 2023 10-Ks
filings = get_filings([2022, 2023, 2024]) # multiple years
filings = get_filings(2024, [1, 2], form="10-Q")
filings = get_filings(2024, 1, amendments=False)
```
**Note:** `get_filings()` has NO `limit` parameter. Use `.head(n)` after.
### Collection Properties
```python
len(filings) # count
filings.empty # bool
filings.date_range # (start_date, end_date)
filings.start_date # earliest
filings.end_date # latest
```
### Access & Iteration
```python
first = filings[0]
last = filings[-1]
for filing in filings:
print(f"{filing.form}: {filing.company}")
# By accession number
filing = filings.get("0001234567-24-000001")
```
### Subset Operations
```python
filings.latest() # most recent (single Filing)
filings.latest(10) # 10 most recent (Filings)
filings.head(20) # first 20
filings.tail(20) # last 20
filings.sample(10) # random 10
```
---
## Filtering & Navigation
### filter()
```python
# Form type
annual = filings.filter(form="10-K")
multi = filings.filter(form=["10-K", "10-Q"])
original = filings.filter(form="10-K", amendments=False)
# Date
jan = filings.filter(date="2024-01-01")
q1 = filings.filter(date="2024-01-01:2024-03-31")
recent = filings.filter(date="2024-01-01:")
# Company
apple = filings.filter(ticker="AAPL")
apple = filings.filter(cik=320193)
faang = filings.filter(ticker=["AAPL", "MSFT", "GOOGL"])
# Exchange
nasdaq = filings.filter(exchange="NASDAQ")
major = filings.filter(exchange=["NASDAQ", "NYSE"])
```
### Chain Filters
```python
result = (filings
.filter(form="10-K")
.filter(exchange="NASDAQ")
.filter(date="2024-01-01:")
.latest(50))
```
### Find by Company Name
```python
tech = filings.find("Technology")
apple = filings.find("Apple")
```
### Pagination
```python
next_page = filings.next()
prev_page = filings.previous()
current = filings.current()
```
---
## Export & Persistence
```python
df = filings.to_pandas()
df = filings.to_pandas('form', 'company', 'filing_date', 'cik')
filings.save_parquet("filings.parquet") # or .save()
filings.download(data_directory="./raw_data/", compress=True)
```
---
## Common Recipes
### Extract Revenue from Latest 10-K
```python
company = Company("MSFT")
filing = company.get_filings(form="10-K").latest()
tenk = filing.obj()
if tenk.financials:
income = tenk.financials.income_statement
print(income)
```
### Convert to Markdown for LLM Analysis
```python
company = Company("NVDA")
filing = company.get_filings(form="10-K").latest()
md = filing.markdown(include_page_breaks=True)
with open("nvidia_10k.md", "w") as f:
f.write(md)
```
### Search Across Recent 8-K Filings
```python
filings = get_filings(2024, 1, form="8-K").head(50)
for filing in filings:
if filing.search("earnings"):
print(f"{filing.company} ({filing.filing_date})")
```
### Batch Process with Pagination
```python
def process_all(filings):
current = filings
results = []
while current and not current.empty:
for filing in current:
results.append(filing.to_dict())
current = current.next()
return results
```

View File

@@ -0,0 +1,274 @@
# edgartools — Financial Data Reference
## Table of Contents
- [Quick Start](#quick-start)
- [Available Statements](#available-statements)
- [Convenience Methods](#convenience-methods)
- [Detail Levels (Views)](#detail-levels-views)
- [DataFrame Export](#dataframe-export)
- [Quarterly vs Annual](#quarterly-vs-annual)
- [Multi-Period Analysis](#multi-period-analysis)
- [Raw XBRL Facts Query](#raw-xbrl-facts-query)
- [API Quick Reference](#api-quick-reference)
- [Troubleshooting](#troubleshooting)
---
## Quick Start
```python
from edgar import Company
company = Company("AAPL")
# Annual (from latest 10-K)
financials = company.get_financials()
income = financials.income_statement()
# Quarterly (from latest 10-Q)
quarterly = company.get_quarterly_financials()
income = quarterly.income_statement()
```
---
## Available Statements
```python
financials = company.get_financials()
income = financials.income_statement()
balance = financials.balance_sheet()
cashflow = financials.cashflow_statement() # note: no underscore
equity = financials.statement_of_equity()
comprehensive = financials.comprehensive_income()
```
| Method | Description |
|--------|-------------|
| `income_statement()` | Revenue, COGS, operating income, net income |
| `balance_sheet()` | Assets, liabilities, equity |
| `cashflow_statement()` | Operating, investing, financing cash flows |
| `statement_of_equity()` | Changes in stockholders' equity |
| `comprehensive_income()` | Net income + other comprehensive income |
---
## Convenience Methods
Get single values directly:
```python
financials = company.get_financials()
revenue = financials.get_revenue()
net_income = financials.get_net_income()
total_assets = financials.get_total_assets()
total_liabs = financials.get_total_liabilities()
equity = financials.get_stockholders_equity()
op_cash_flow = financials.get_operating_cash_flow()
free_cash_flow = financials.get_free_cash_flow()
capex = financials.get_capital_expenditures()
current_assets = financials.get_current_assets()
current_liabs = financials.get_current_liabilities()
# All key metrics at once
metrics = financials.get_financial_metrics() # dict
# Prior period: period_offset=1 (previous), 0=current
prev_revenue = financials.get_revenue(period_offset=1)
```
---
## Detail Levels (Views)
Control the level of detail in financial statements:
```python
income = financials.income_statement()
# Summary: ~15-20 rows, matches SEC Viewer
df_summary = income.to_dataframe(view="summary")
# Standard (default): ~25-35 rows, matches filing document
df_standard = income.to_dataframe(view="standard")
# Detailed: ~50+ rows, all dimensional breakdowns
df_detailed = income.to_dataframe(view="detailed")
```
| View | Use Case |
|------|----------|
| `"summary"` | Quick overview, validating against SEC Viewer |
| `"standard"` | Display, full context (default) |
| `"detailed"` | Data extraction, segment analysis |
**Example — Apple Revenue breakdown:**
- Summary: `Revenue $391,035M`
- Standard: `Products $298,085M`, `Services $92,950M`
- Detailed: iPhone, Mac, iPad, Wearables separately
---
## DataFrame Export
```python
income = financials.income_statement()
# Convert to DataFrame
df = income.to_dataframe()
df = income.to_dataframe(view="detailed")
# Export
df.to_csv("apple_income.csv")
df.to_excel("apple_income.xlsx")
```
---
## Quarterly vs Annual
| Need | Method |
|------|--------|
| Annual (10-K) | `company.get_financials()` |
| Quarterly (10-Q) | `company.get_quarterly_financials()` |
```python
quarterly = company.get_quarterly_financials()
q_income = quarterly.income_statement()
```
---
## Multi-Period Analysis
Use `XBRLS` to analyze trends across multiple filings:
```python
from edgar.xbrl import XBRLS
# Get last 3 annual filings (use amendments=False)
filings = company.get_filings(form="10-K", amendments=False).head(3)
# Stitch together
xbrls = XBRLS.from_filings(filings)
# Get aligned multi-period statements
income = xbrls.statements.income_statement()
income_detailed = xbrls.statements.income_statement(view="detailed")
balance = xbrls.statements.balance_sheet()
cashflow = xbrls.statements.cashflow_statement()
# Convert to DataFrame (periods as columns)
df = income.to_dataframe()
print(df)
```
**Why `amendments=False`?** Amended filings (10-K/A) sometimes contain only corrected sections, not complete financial statements, which breaks multi-period stitching.
---
## Raw XBRL Facts Query
For research or custom calculations:
```python
xbrl = filing.xbrl()
# Find revenue facts
revenue_facts = xbrl.facts.query()\
.by_concept("Revenue")\
.to_dataframe()
# Search by label
rd_facts = xbrl.facts.query()\
.by_label("Research", exact=False)\
.to_dataframe()
# Filter by value range
large_items = xbrl.facts.query()\
.by_value(min_value=1_000_000_000)\
.to_dataframe()
```
---
## API Quick Reference
### Company-Level
| Method | Description |
|--------|-------------|
| `company.get_financials()` | Latest annual (10-K) |
| `company.get_quarterly_financials()` | Latest quarterly (10-Q) |
### Financials Object
| Method | Description |
|--------|-------------|
| `financials.income_statement()` | Income statement |
| `financials.balance_sheet()` | Balance sheet |
| `financials.cashflow_statement()` | Cash flow |
| `financials.get_revenue()` | Revenue scalar |
| `financials.get_net_income()` | Net income scalar |
| `financials.get_total_assets()` | Total assets scalar |
| `financials.get_financial_metrics()` | Dict of all key metrics |
### Statement Object
| Method | Description |
|--------|-------------|
| `statement.to_dataframe()` | Convert to DataFrame |
| `statement.to_dataframe(view="summary")` | SEC Viewer format |
| `statement.to_dataframe(view="standard")` | Filing document format |
| `statement.to_dataframe(view="detailed")` | All dimensional breakdowns |
### Filing-Level (More Control)
| Method | Description |
|--------|-------------|
| `filing.xbrl()` | Parse XBRL from filing |
| `xbrl.statements.income_statement()` | Income statement |
| `xbrl.facts.query()` | Query individual facts |
### Multi-Period
| Method | Description |
|--------|-------------|
| `XBRLS.from_filings(filings)` | Stitch multiple filings |
| `xbrls.statements.income_statement()` | Aligned multi-period |
---
## Troubleshooting
### "No financial data found"
```python
filing = company.get_filings(form="10-K").latest()
if filing.xbrl():
print("XBRL available")
else:
# Older/smaller companies may not have XBRL
text = filing.text() # fallback to raw text
```
### "Statement is empty"
Try the detailed view:
```python
df = income.to_dataframe(view="detailed")
```
### "Numbers don't match SEC website"
Check the reporting periods:
```python
xbrl = filing.xbrl()
print(xbrl.reporting_periods)
```
### Accessing financials from a 10-K filing
```python
# WRONG: filing.financials does not exist
filing.financials # AttributeError!
# CORRECT:
tenk = filing.obj()
if tenk and tenk.financials:
income = tenk.financials.income_statement
```

View File

@@ -0,0 +1,373 @@
# edgartools — XBRL Reference
## Table of Contents
- [Core Classes](#core-classes)
- [XBRL Class](#xbrl-class)
- [Statements Access](#statements-access)
- [XBRLS — Multi-Period Analysis](#xbrls--multi-period-analysis)
- [Facts Querying](#facts-querying)
- [Statement to DataFrame](#statement-to-dataframe)
- [Value Transformations](#value-transformations)
- [Rendering](#rendering)
- [Error Handling](#error-handling)
- [Import Reference](#import-reference)
---
## Core Classes
| Class | Purpose |
|-------|---------|
| `XBRL` | Parse single filing's XBRL |
| `XBRLS` | Multi-period analysis across filings |
| `Statements` | Access financial statements from single XBRL |
| `Statement` | Individual statement object |
| `StitchedStatements` | Multi-period statements interface |
| `StitchedStatement` | Multi-period individual statement |
| `FactsView` | Query interface for all XBRL facts |
| `FactQuery` | Fluent fact query builder |
---
## XBRL Class
### Creating an XBRL Object
```python
from edgar.xbrl import XBRL
# From a Filing object (most common)
xbrl = XBRL.from_filing(filing)
# Via filing method
xbrl = filing.xbrl() # returns None if no XBRL
# From directory
xbrl = XBRL.from_directory("/path/to/xbrl/files")
# From file list
xbrl = XBRL.from_files(["/path/instance.xml", "/path/taxonomy.xsd"])
```
### Core Properties
```python
xbrl.statements # Statements object
xbrl.facts # FactsView object
# Convert all facts to DataFrame
df = xbrl.to_pandas()
# Columns: concept, value, period, label, ...
```
### Statement Methods
```python
stmt = xbrl.get_statement("BalanceSheet")
stmt = xbrl.get_statement("IncomeStatement")
stmt = xbrl.get_statement("CashFlowStatement")
stmt = xbrl.get_statement("StatementOfEquity")
# Render with rich formatting
rendered = xbrl.render_statement("BalanceSheet")
rendered = xbrl.render_statement("IncomeStatement", show_percentages=True, max_rows=50)
print(rendered)
```
---
## Statements Access
```python
statements = xbrl.statements
balance_sheet = statements.balance_sheet()
income_stmt = statements.income_statement()
cash_flow = statements.cash_flow_statement()
equity = statements.statement_of_equity()
comprehensive = statements.comprehensive_income()
```
All return `Statement` objects or `None` if not found.
---
## XBRLS — Multi-Period Analysis
```python
from edgar import Company
from edgar.xbrl import XBRLS
company = Company("AAPL")
# Get multiple filings (use amendments=False for clean stitching)
filings = company.get_filings(form="10-K", amendments=False).head(3)
# Stitch together
xbrls = XBRLS.from_filings(filings)
# Access stitched statements
stitched = xbrls.statements
income_stmt = stitched.income_statement()
balance_sheet = stitched.balance_sheet()
cashflow = stitched.cashflow_statement()
equity_stmt = stitched.statement_of_equity()
comprehensive = stitched.comprehensive_income()
```
### StitchedStatements Parameters
All methods accept:
- `max_periods` (int) — max periods to include (default: 8)
- `standard` (bool) — use standardized concept labels (default: True)
- `use_optimal_periods` (bool) — use entity info for period selection (default: True)
- `show_date_range` (bool) — show full date ranges (default: False)
- `include_dimensions` (bool) — include segment data (default: False)
- `view` (str) — `"standard"`, `"detailed"`, or `"summary"` (overrides `include_dimensions`)
```python
# Standard view (default)
income = stitched.income_statement()
# Detailed view with dimensional breakdowns
income_detailed = stitched.income_statement(view="detailed")
# Convert to DataFrame (periods as columns)
df = income.to_dataframe()
```
---
## Facts Querying
### FactsView — Starting a Query
```python
facts = xbrl.facts
# Query by concept
revenue_q = facts.by_concept("Revenue")
revenue_q = facts.by_concept("us-gaap:Revenue", exact=True)
# Query by label
rd_q = facts.by_label("Research", exact=False)
# Query by value range
large_q = facts.by_value(min_value=1_000_000_000)
small_q = facts.by_value(max_value=100_000)
range_q = facts.by_value(min_value=100, max_value=1000)
# Query by period
period_q = facts.by_period(start_date="2023-01-01", end_date="2023-12-31")
```
### FactQuery — Fluent Chaining
```python
# Chain multiple filters
query = (xbrl.facts
.by_concept("Revenue")
.by_period(start_date="2023-01-01")
.by_value(min_value=1_000_000))
# Execute
facts_list = query.execute() # List[Dict]
facts_df = query.to_dataframe() # DataFrame
first_fact = query.first() # Dict or None
count = query.count() # int
# Filter by statement type
income_facts = xbrl.facts.by_statement("IncomeStatement")
```
### Analysis Methods on FactsView
```python
# Pivot: concepts as rows, periods as columns
pivot = facts.pivot_by_period(["Revenue", "NetIncomeLoss"])
# Time series for a concept
revenue_ts = facts.time_series("Revenue") # pandas Series
# Convert all to DataFrame
all_df = facts.to_dataframe()
```
---
## Statement to DataFrame
### Statement.to_dataframe()
```python
statement = xbrl.statements.income_statement()
# Raw mode (default) — exact XML values
df_raw = statement.to_dataframe()
# Presentation mode — matches SEC HTML display
df_presentation = statement.to_dataframe(presentation=True)
# Additional options
df = statement.to_dataframe(
include_dimensions=True, # include segment breakdowns (default: True)
include_unit=True, # include unit column (USD, shares)
include_point_in_time=True # include point-in-time column
)
```
### Columns in output
- Core: `concept`, `label`, period date columns
- Metadata (always): `balance`, `weight`, `preferred_sign`
- Optional: `dimension`, `unit`, `point_in_time`
### Get Concept Value
```python
revenue = statement.get_concept_value("Revenue")
net_income = statement.get_concept_value("NetIncomeLoss")
```
---
## Value Transformations
edgartools provides two layers of values:
**Raw Values (default):** Values exactly as in XML instance document. Consistent across companies, comparable to SEC CompanyFacts API.
**Presentation Values (`presentation=True`):** Transformed to match SEC HTML display. Cash flow outflows shown as negative. Good for investor-facing reports.
```python
statement = xbrl.statements.cash_flow_statement()
# Raw: dividends paid appears as positive
df_raw = statement.to_dataframe()
# Presentation: dividends paid appears as negative (matches HTML)
df_pres = statement.to_dataframe(presentation=True)
```
### Metadata columns explain semantics:
- `balance`: debit/credit from schema
- `weight`: calculation weight (+1.0 or -1.0)
- `preferred_sign`: presentation hint (+1 or -1)
### When to use each:
| Use Raw | Use Presentation |
|---------|-----------------|
| Cross-company analysis | Matching SEC HTML display |
| Data science / ML | Investor-facing reports |
| Comparison with CompanyFacts API | Traditional financial statement signs |
---
## Rendering
```python
# Render single statement
rendered = xbrl.render_statement("BalanceSheet")
print(rendered) # Rich formatted output
# Render Statement object
stmt = xbrl.statements.income_statement()
rendered = stmt.render()
rendered = stmt.render(show_percentages=True, max_rows=50)
print(rendered)
# Multi-period render
stitched_stmt = xbrls.statements.income_statement()
rendered = stitched_stmt.render(show_date_range=True)
print(rendered)
```
---
## Advanced Examples
### Complex Fact Query
```python
from edgar import Company
from edgar.xbrl import XBRL
company = Company("MSFT")
filing = company.latest("10-K")
xbrl = XBRL.from_filing(filing)
# Query with multiple filters
results = (xbrl.facts
.by_concept("Revenue")
.by_value(min_value=50_000_000_000)
.by_period(start_date="2023-01-01")
.to_dataframe())
# Pivot analysis
pivot = xbrl.facts.pivot_by_period([
"Revenue",
"NetIncomeLoss",
"OperatingIncomeLoss"
])
```
### Cross-Company Comparison
```python
from edgar import Company
from edgar.xbrl import XBRL
companies = ["AAPL", "MSFT", "GOOGL"]
for ticker in companies:
company = Company(ticker)
filing = company.latest("10-K")
xbrl = XBRL.from_filing(filing)
if xbrl and xbrl.statements.income_statement():
stmt = xbrl.statements.income_statement()
revenue = stmt.get_concept_value("Revenue")
print(f"{ticker}: ${revenue/1e9:.1f}B")
```
---
## Error Handling
```python
from edgar.xbrl import XBRL, XBRLFilingWithNoXbrlData
try:
xbrl = XBRL.from_filing(filing)
except XBRLFilingWithNoXbrlData:
print("No XBRL data in this filing")
# Check availability
xbrl = filing.xbrl()
if xbrl is None:
print("No XBRL available")
text = filing.text() # fallback
# Check statement availability
if xbrl and xbrl.statements.income_statement():
income = xbrl.statements.income_statement()
df = income.to_dataframe()
```
---
## Import Reference
```python
# Core
from edgar.xbrl import XBRL, XBRLS
# Statements
from edgar.xbrl import Statements, Statement
from edgar.xbrl import StitchedStatements, StitchedStatement
# Facts
from edgar.xbrl import FactsView, FactQuery
from edgar.xbrl import StitchedFactsView, StitchedFactQuery
# Rendering & standardization
from edgar.xbrl import StandardConcept, RenderedStatement
# Utilities
from edgar.xbrl import stitch_statements, render_stitched_statement, to_pandas
```