Initial commit

This commit is contained in:
kdusek
2025-12-09 12:13:01 +01:00
commit 8e654ed209
13332 changed files with 2695056 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,557 @@
# EntityFiling Class Documentation
## Overview
The `EntityFiling` class extends the base `Filing` class with additional entity-specific metadata and functionality. When you access filings through a `Company` object, you get `EntityFiling` instances that include enriched information from the SEC's company submissions API.
**Key Differences from Base Filing:**
- Additional metadata (items, acceptance datetime, file number, etc.)
- `related_filings()` method to find filings by file number
- XBRL format indicators (is_xbrl, is_inline_xbrl)
- Report date separate from filing date
- Access to entity context
## Getting EntityFilings
### From Company
```python
from edgar import Company
# Get company
company = Company("AAPL")
# Get filings - returns EntityFiling instances
filings = company.get_filings(form="10-K")
filing = filings.latest()
# filing is now an EntityFiling, not base Filing
print(type(filing)) # <class 'edgar.entity.filings.EntityFiling'>
```
### Automatic Enhancement
When you call `company.get_filings()`, the filings are automatically EntityFiling instances with additional metadata.
## Common Actions
Quick reference for the most frequently used EntityFiling methods:
### Access Filing Content
```python
# Get HTML content
html = filing.html()
# Get plain text
text = filing.text()
# Get markdown formatted content
markdown = filing.markdown()
```
### Get Structured Data
```python
# Get form-specific object (10-K, 10-Q, 8-K, etc.)
report = filing.obj()
# Get XBRL financial data
xbrl = filing.xbrl()
```
### Entity-Specific Features
```python
# Find related filings (amendments, etc.)
related = filing.related_filings()
# Check XBRL availability
if filing.is_xbrl:
xbrl = filing.xbrl()
# Access entity-specific metadata
print(filing.report_date) # Period end date
print(filing.items) # 8-K items
print(filing.file_number) # SEC file number
```
### View in Browser
```python
# Open filing in web browser
filing.open()
```
### Get Attachments
```python
# Access all filing attachments
attachments = filing.attachments
```
## EntityFiling-Specific Attributes
### Additional Metadata
| Attribute | Type | Description |
|-----------|------|-------------|
| `report_date` | str | Period end date for the report (YYYY-MM-DD) |
| `acceptance_datetime` | str | SEC acceptance timestamp |
| `file_number` | str | SEC file number for tracking related filings |
| `items` | str | 8-K items (e.g., "2.02,9.01") |
| `size` | int | Filing size in bytes |
| `primary_document` | str | Primary document filename |
| `primary_doc_description` | str | Description of primary document |
| `is_xbrl` | bool | Whether filing has XBRL data |
| `is_inline_xbrl` | bool | Whether filing uses inline XBRL |
### Accessing Additional Metadata
```python
filing = company.get_filings(form="10-K").latest()
# Entity-specific attributes
print(f"Report Date: {filing.report_date}")
print(f"Accepted: {filing.acceptance_datetime}")
print(f"File Number: {filing.file_number}")
print(f"Has XBRL: {filing.is_xbrl}")
print(f"Inline XBRL: {filing.is_inline_xbrl}")
print(f"Size: {filing.size:,} bytes")
```
## Working with 8-K Items
The `items` attribute is especially useful for 8-K current reports, which can cover multiple topics.
### Understanding 8-K Items
8-K items indicate what events or information the filing reports:
- **2.02** - Results of Operations and Financial Condition
- **5.02** - Departure/Election of Directors or Officers
- **8.01** - Other Events
- **9.01** - Financial Statements and Exhibits
```python
# Get 8-K filings
filings_8k = company.get_filings(form="8-K")
# Filter by items
for filing in filings_8k:
if filing.items and "2.02" in filing.items:
print(f"Earnings 8-K: {filing.filing_date}")
print(f" Items: {filing.items}")
```
### Important Note on Legacy Filings
**Data Source Limitation**: The `items` value comes from SEC metadata, not from parsing the filing document.
**For Legacy SGML Filings (1999-2001)**: The SEC's historical metadata may be incorrect or incomplete. Modern XML filings (2005+) have accurate metadata.
**Workaround**: For accurate item extraction from legacy SGML 8-K filings, parse the filing text directly:
```python
# For legacy filings, parse the document
filing_text = filing.text()
# Use regex to find items (adjust pattern as needed)
import re
items_pattern = r'Item\s+(\d+\.\d+)'
found_items = re.findall(items_pattern, filing_text, re.IGNORECASE)
```
## Related Filings
### Finding Related Filings by File Number
Use the `file_number` to find amendments, related documents, or filings from the same series:
```python
# Get original filing
filing = company.get_filings(form="10-K").latest()
# Find all related filings (amendments, etc.)
related = filing.related_filings()
print(f"Original filing: {filing.accession_no}")
print(f"Related filings: {len(related)}")
for f in related:
print(f" {f.form} - {f.filing_date}")
```
### Use Cases for Related Filings
**1. Find Amendments:**
```python
# Get original 10-K
filing_10k = company.get_filings(form="10-K").latest()
# Find any amendments
related = filing_10k.related_filings()
amendments = related.filter(form="10-K/A")
if len(amendments) > 0:
print("Filing was amended:")
for amendment in amendments:
print(f" {amendment.filing_date}: {amendment.accession_no}")
```
**2. Track Filing Series:**
```python
# Get S-1 registration
s1 = company.get_filings(form="S-1").latest()
# Find all related S-1 amendments
series = s1.related_filings()
print(f"Registration series: {len(series)} filings")
```
## XBRL Indicators
The `is_xbrl` and `is_inline_xbrl` attributes help determine if structured financial data is available.
### Checking XBRL Availability
```python
filing = company.get_filings(form="10-K").latest()
if filing.is_xbrl:
print("Filing has XBRL data")
if filing.is_inline_xbrl:
print(" Uses inline XBRL format")
xbrl = filing.xbrl() # Parse XBRL data
else:
print(" Uses traditional XBRL format")
else:
print("No XBRL data available")
```
### Filtering by XBRL
```python
# Get only filings with XBRL data
filings = company.get_filings(form="10-Q")
xbrl_filings = [f for f in filings if f.is_xbrl]
print(f"{len(xbrl_filings)} of {len(filings)} have XBRL")
# Check inline XBRL adoption
inline_count = sum(1 for f in xbrl_filings if f.is_inline_xbrl)
print(f"{inline_count} use inline XBRL format")
```
## Report Date vs Filing Date
EntityFiling provides both `report_date` and `filing_date`:
- **`report_date`**: Period end date (what the filing reports on)
- **`filing_date`**: When the filing was submitted to SEC
```python
filing = company.get_filings(form="10-Q").latest()
print(f"Period Ended: {filing.report_date}")
print(f"Filed On: {filing.filing_date}")
# Calculate filing lag
from datetime import datetime
report_dt = datetime.strptime(filing.report_date, '%Y-%m-%d')
filing_dt = datetime.strptime(filing.filing_date, '%Y-%m-%d')
lag_days = (filing_dt - report_dt).days
print(f"Filing lag: {lag_days} days")
```
## Common Workflows
### Analyzing 8-K Patterns
```python
# Get all 8-K filings
filings_8k = company.get_filings(form="8-K")
# Categorize by item
from collections import Counter
item_counts = Counter()
for filing in filings_8k:
if filing.items:
for item in filing.items.split(','):
item_counts[item.strip()] += 1
# Show most common 8-K topics
print("Most common 8-K items:")
for item, count in item_counts.most_common(5):
print(f" Item {item}: {count} filings")
```
### Track Amendment Activity
```python
# Get all 10-K filings including amendments
all_10k = company.get_filings(form=["10-K", "10-K/A"])
# Group by year
from collections import defaultdict
by_year = defaultdict(list)
for filing in all_10k:
year = filing.report_date[:4]
by_year[year].append(filing)
# Check which years had amendments
for year in sorted(by_year.keys(), reverse=True):
filings = by_year[year]
has_amendment = any('/A' in f.form for f in filings)
status = "amended" if has_amendment else "original"
print(f"{year}: {len(filings)} filing(s) - {status}")
```
### Find Earnings Announcements
```python
# Find 8-K filings with earnings (Item 2.02)
earnings_8k = []
for filing in company.get_filings(form="8-K"):
if filing.items and "2.02" in filing.items:
earnings_8k.append(filing)
print(f"Found {len(earnings_8k)} earnings 8-K filings")
# Show filing timeline
for filing in earnings_8k[-5:]: # Last 5
print(f"{filing.report_date}: {filing.filing_date}")
```
### Check XBRL Adoption Timeline
```python
# Track when company started using XBRL
filings = company.get_filings(form="10-K")
for filing in filings:
xbrl_status = "inline XBRL" if filing.is_inline_xbrl else "XBRL" if filing.is_xbrl else "no XBRL"
print(f"{filing.filing_date}: {xbrl_status}")
```
## Integration with Base Filing Features
EntityFiling inherits all methods from the base Filing class:
```python
filing = company.get_filings(form="10-K").latest()
# All base Filing methods work
html = filing.html()
text = filing.text()
markdown = filing.markdown()
xbrl = filing.xbrl()
filing.open()
# PLUS entity-specific features
related = filing.related_filings()
print(f"8-K items: {filing.items}")
print(f"Has XBRL: {filing.is_xbrl}")
```
## Comparison: EntityFiling vs Base Filing
### When You Get Each Type
**EntityFiling** - From Company context:
```python
company = Company("AAPL")
filing = company.get_filings(form="10-K").latest()
# Type: EntityFiling (with extra metadata)
```
**Base Filing** - From general search:
```python
from edgar import get_filings
filings = get_filings(2024, 3, form="10-K")
filing = filings[0]
# Type: Filing (base class)
```
### Feature Comparison
| Feature | Base Filing | EntityFiling |
|---------|-------------|--------------|
| Basic metadata | ✅ | ✅ |
| Content access (html, text) | ✅ | ✅ |
| XBRL parsing | ✅ | ✅ |
| Report date | ❌ | ✅ |
| Acceptance datetime | ❌ | ✅ |
| File number | ❌ | ✅ |
| 8-K items | ❌ | ✅ |
| XBRL indicators | ❌ | ✅ |
| related_filings() | ❌ | ✅ |
## Best Practices
### 1. Use EntityFiling for Company Analysis
When working with a specific company, always access filings through the Company object to get EntityFiling benefits:
```python
# Good - get EntityFiling with metadata
company = Company("AAPL")
filing = company.get_filings(form="10-K").latest()
# Less ideal - get base Filing without metadata
filings = get_filings(2024, 3, form="10-K").filter(ticker="AAPL")
filing = filings[0]
```
### 2. Check XBRL Availability Before Parsing
```python
filing = company.get_filings(form="10-K").latest()
if filing.is_xbrl:
xbrl = filing.xbrl()
statements = xbrl.statements
else:
print("No structured financial data available")
```
### 3. Handle Missing Items Gracefully
```python
# Items may be None or empty string
if filing.items:
items_list = filing.items.split(',')
else:
items_list = []
```
### 4. Use Related Filings to Track Changes
```python
# Find if filing was amended
filing = company.get_filings(form="10-K").latest()
related = filing.related_filings()
amendments = [f for f in related if '/A' in f.form]
if amendments:
print(f"This filing has {len(amendments)} amendment(s)")
latest_amendment = amendments[-1]
print(f"Most recent: {latest_amendment.filing_date}")
```
## Error Handling
### Missing Attributes
Not all filings have all attributes populated:
```python
filing = company.get_filings(form="8-K").latest()
# Some filings may not have items
items = filing.items if filing.items else "Not specified"
# File number should always be present for EntityFiling
if filing.file_number:
print(f"File number: {filing.file_number}")
```
### XBRL Parsing Failures
Even if `is_xbrl` is True, parsing can fail:
```python
if filing.is_xbrl:
try:
xbrl = filing.xbrl()
statements = xbrl.statements
except Exception as e:
print(f"XBRL parsing failed: {e}")
# Fall back to text parsing
text = filing.text()
```
## Performance Considerations
### Efficient Filtering
Use EntityFiling metadata to filter before expensive operations:
```python
# Filter by XBRL availability first
filings = company.get_filings(form="10-Q")
xbrl_filings = [f for f in filings if f.is_xbrl]
# Then parse only those with XBRL
for filing in xbrl_filings:
xbrl = filing.xbrl()
# Process XBRL data...
```
### Batch Operations
When processing many filings, check size first:
```python
filings = company.get_filings()
# Process smaller filings first
sorted_filings = sorted(filings, key=lambda f: f.size)
for filing in sorted_filings[:10]: # Process 10 smallest
html = filing.html()
# Process content...
```
## Troubleshooting
### "EntityFiling has no attribute 'X'"
You're trying to use EntityFiling-specific features on a base Filing object:
```python
# Problem: Base filing doesn't have entity attributes
filings = get_filings(2024, 3)
filing = filings[0]
# filing.report_date # AttributeError!
# Solution: Get from company for EntityFiling
company = Company(filing.cik)
entity_filing = company.get_filings(
accession_number=filing.accession_no
)[0]
# entity_filing.report_date # Works!
```
### Related Filings Returns Empty
The file number might not link to other filings:
```python
related = filing.related_filings()
if len(related) == 0:
print("No related filings found")
# This is normal for standalone filings
else:
print(f"Found {len(related)} related filing(s)")
```
### Items Not Showing for 8-K
Check if it's a legacy filing:
```python
filing = company.get_filings(form="8-K")[0]
if not filing.items or filing.items == "":
# Check filing year
filing_year = int(filing.filing_date[:4])
if filing_year < 2005:
print("Legacy SGML filing - items may be missing from metadata")
print("Parse filing text for accurate item identification")
else:
print("Modern filing with no items specified")
```
This comprehensive guide covers the unique features and workflows available when working with EntityFiling objects in edgartools.

View File

@@ -0,0 +1,671 @@
# EntityFilings Class Documentation
## Overview
The `EntityFilings` class extends the base `Filings` class with entity-specific functionality. When you access filings through a `Company` object, you get an `EntityFilings` collection that maintains entity context (CIK and company name) and returns `EntityFiling` instances with enriched metadata.
**Key Differences from Base Filings:**
- Maintains entity context (CIK, company name)
- Returns `EntityFiling` instances (not base `Filing`)
- All filtering/selection methods preserve `EntityFilings` type
- Additional metadata from SEC company submissions API
- Direct access to entity-specific features
## Getting EntityFilings
### From Company
```python
from edgar import Company
# Get company
company = Company("AAPL")
# Get filings - returns EntityFilings collection
filings = company.get_filings()
# filings is EntityFilings, not base Filings
print(type(filings)) # <class 'edgar.entity.filings.EntityFilings'>
# Each filing in the collection is EntityFiling
filing = filings[0]
print(type(filing)) # <class 'edgar.entity.filings.EntityFiling'>
```
### With Form Filters
```python
# Get specific form types
filings_10k = company.get_filings(form="10-K")
filings_8k = company.get_filings(form="8-K")
filings_multi = company.get_filings(form=["10-K", "10-Q"])
```
## Common Actions
Quick reference for the most frequently used EntityFilings methods:
### Get Individual Filings
```python
# Get most recent filing
latest = filings.latest()
# Get multiple recent filings
latest_5 = filings.latest(5)
# Get filing by index
filing = filings[0]
filing = filings.get_filing_at(5)
```
### Filter the Collection
```python
# Filter by form type
annual_reports = filings.filter(form="10-K")
# Filter by date
recent = filings.filter(filing_date="2024-01-01:")
# Exclude amendments
originals_only = filings.filter(amendments=False)
# Combined filters
filtered = filings.filter(
form=["10-K", "10-Q"],
filing_date="2023-01-01:2023-12-31",
amendments=False
)
```
### Navigate Pages
```python
# For large collections (multiple pages)
next_page = filings.next()
prev_page = filings.previous()
```
### Convert to DataFrame
```python
# Export to pandas
df = filings.to_pandas()
# Select specific columns
df = filings.to_pandas('form', 'filing_date', 'accession_number')
```
### Select Subsets
```python
# Get first/last n filings
first_10 = filings.head(10)
last_10 = filings.tail(10)
# Random sample
sample = filings.sample(20)
```
## EntityFilings-Specific Features
### Entity Context
EntityFilings maintains the entity context throughout operations:
```python
filings = company.get_filings()
# Access entity information
print(filings.cik) # Company CIK
print(filings.company_name) # Company name
# Context preserved through operations
filtered = filings.filter(form="10-K")
print(filtered.cik) # Same CIK
print(filtered.company_name) # Same company name
```
### Returns EntityFiling Instances
All methods that return individual filings return `EntityFiling` (not base `Filing`):
```python
# Get latest returns EntityFiling
filing = filings.latest()
print(type(filing)) # EntityFiling
# Indexing returns EntityFiling
filing = filings[0]
print(type(filing)) # EntityFiling
# Access EntityFiling-specific attributes
print(filing.report_date) # Period end date
print(filing.items) # 8-K items
print(filing.is_xbrl) # XBRL indicator
```
### Type Preservation
All collection methods preserve the `EntityFilings` type:
```python
# filter() returns EntityFilings
filtered = filings.filter(form="10-K")
print(type(filtered)) # EntityFilings
# head() returns EntityFilings
first_10 = filings.head(10)
print(type(first_10)) # EntityFilings
# latest(n) with n>1 returns EntityFilings
latest_5 = filings.latest(5)
print(type(latest_5)) # EntityFilings
```
## Core Methods
### latest(n=1)
Get the most recent filing(s):
```python
# Get single latest filing (returns EntityFiling)
latest = filings.latest()
print(f"Most recent: {latest.form} on {latest.filing_date}")
# Get multiple latest filings (returns EntityFilings)
latest_5 = filings.latest(5)
for filing in latest_5:
print(f"{filing.form}: {filing.filing_date}")
```
### filter()
Filter filings by various criteria:
```python
# Filter by form type
filings_10k = filings.filter(form="10-K")
filings_8k = filings.filter(form="8-K")
filings_annual = filings.filter(form=["10-K", "10-K/A"])
# Filter by date
recent = filings.filter(filing_date="2024-01-01:")
date_range = filings.filter(filing_date="2023-01-01:2023-12-31")
specific_date = filings.filter(filing_date="2024-03-15")
# Exclude amendments
no_amendments = filings.filter(amendments=False)
# Filter by accession number
specific = filings.filter(accession_number="0000320193-24-000123")
# Combined filters
filtered = filings.filter(
form="10-Q",
filing_date="2024-01-01:",
amendments=False
)
```
**Note**: Unlike base `Filings.filter()`, `EntityFilings.filter()` doesn't support `cik` or `ticker` parameters since the collection is already scoped to a single entity.
### head(n) / tail(n)
Get first or last n filings:
```python
# Get first 10 filings
first_10 = filings.head(10)
# Get last 10 filings
last_10 = filings.tail(10)
# Both return EntityFilings collections
print(type(first_10)) # EntityFilings
print(type(last_10)) # EntityFilings
```
### sample(n)
Get random sample of filings:
```python
# Get random sample of 20 filings
sample = filings.sample(20)
# Returns EntityFilings collection
print(type(sample)) # EntityFilings
```
### Access by Index
```python
# Direct indexing
first_filing = filings[0]
tenth_filing = filings[9]
# Explicit method
filing = filings.get_filing_at(5)
# All return EntityFiling instances
```
## Pagination
For large filing collections, EntityFilings supports pagination:
### next() / previous()
```python
# Display shows page info if multiple pages
print(filings)
# Shows: "Showing 1 to 50 of 250 filings. Page using ← prev() and next() →"
# Navigate to next page
next_page = filings.next()
# Navigate to previous page
prev_page = filings.previous()
# Both return EntityFilings with new page of data
```
### Page Navigation Example
```python
# Start with first page
current_page = company.get_filings()
print(current_page)
# Move through pages
page_2 = current_page.next()
page_3 = page_2.next()
# Go back
page_2_again = page_3.previous()
# At end of pages
last_page = current_page
while True:
next_page = last_page.next()
if next_page is None:
break
last_page = next_page
```
## Data Conversion & Export
### to_pandas()
Convert to pandas DataFrame:
```python
# All columns
df = filings.to_pandas()
# Specific columns
df = filings.to_pandas('form', 'filing_date', 'accession_number')
# Shows entity-specific columns:
# form, filing_date, reportDate, acceptanceDateTime, fileNumber,
# items, size, primaryDocument, isXBRL, isInlineXBRL, etc.
```
### to_dict()
Convert to dictionary:
```python
# Convert to dict
data = filings.to_dict()
# Limit rows
data = filings.to_dict(max_rows=100)
```
### save() / save_parquet()
Save to Parquet file:
```python
# Save as Parquet
filings.save_parquet("company_filings.parquet")
# Alternative
filings.save("company_filings.parquet")
```
## Common Workflows
### Get Most Recent Annual Report
```python
company = Company("AAPL")
# Get all 10-K filings
filings_10k = company.get_filings(form="10-K")
# Get most recent
latest_10k = filings_10k.latest()
print(f"Latest 10-K: {latest_10k.filing_date}")
print(f"Period: {latest_10k.report_date}")
# Access XBRL if available
if latest_10k.is_xbrl:
xbrl = latest_10k.xbrl()
```
### Analyze Quarterly Reports
```python
# Get all 10-Q filings
filings_10q = company.get_filings(form="10-Q")
# Get last 4 quarters
last_4_quarters = filings_10q.latest(4)
# Analyze each quarter
for filing in last_4_quarters:
print(f"Quarter ending {filing.report_date}:")
print(f" Filed: {filing.filing_date}")
print(f" XBRL: {filing.is_xbrl}")
```
### Find 8-K Earnings Announcements
```python
# Get all 8-K filings
filings_8k = company.get_filings(form="8-K")
# Filter for earnings-related items
earnings_filings = []
for filing in filings_8k:
if filing.items and "2.02" in filing.items:
earnings_filings.append(filing)
print(f"Found {len(earnings_filings)} earnings 8-Ks")
# Show recent earnings dates
for filing in earnings_filings[:5]:
print(f"{filing.filing_date}: Items {filing.items}")
```
### Track Amendment Activity
```python
# Get all 10-K filings including amendments
all_10k = company.get_filings(form=["10-K", "10-K/A"])
# Separate originals from amendments
originals = all_10k.filter(amendments=False)
amendments = all_10k.filter(form="10-K/A")
print(f"Original 10-Ks: {len(originals)}")
print(f"Amended 10-Ks: {len(amendments)}")
# Show amendment details
for amendment in amendments:
print(f"{amendment.filing_date}: {amendment.accession_no}")
```
### Export Filings to DataFrame
```python
# Get recent filings
filings = company.get_filings(form=["10-K", "10-Q"])
# Filter to recent year
recent = filings.filter(filing_date="2024-01-01:")
# Convert to DataFrame
df = recent.to_pandas()
# Analyze
print(f"Total filings: {len(df)}")
print(f"Forms: {df['form'].value_counts()}")
print(f"XBRL filings: {df['isXBRL'].sum()}")
# Export
df.to_csv("aapl_recent_filings.csv", index=False)
```
### Compare XBRL Adoption
```python
# Get all annual reports
filings_10k = company.get_filings(form="10-K")
# Convert to DataFrame
df = filings_10k.to_pandas()
# Group by year
df['year'] = pd.to_datetime(df['filing_date']).dt.year
# Check XBRL adoption by year
xbrl_by_year = df.groupby('year').agg({
'isXBRL': 'sum',
'isInlineXBRL': 'sum',
'form': 'count'
}).rename(columns={'form': 'total'})
print(xbrl_by_year)
```
## Display & Representation
### Rich Display
EntityFilings displays as a rich table with pagination info:
```python
print(filings)
```
Shows:
- Table of filings with: #, Form, Description, Filing Date, Accession Number
- Pagination info (if multiple pages): "Showing 1 to 50 of 250 filings"
- Panel title: "Filings for [Company Name] [CIK]"
- Panel subtitle: Date range of filings
### Properties
```python
# Check if empty
if filings.empty:
print("No filings found")
# Get date range
start, end = filings.date_range
print(f"Filings from {start} to {end}")
# Get summary
print(filings.summary)
```
## Comparison: EntityFilings vs Base Filings
### When You Get Each Type
**EntityFilings** - From Company context:
```python
company = Company("AAPL")
filings = company.get_filings()
# Type: EntityFilings (with entity context)
```
**Base Filings** - From general search:
```python
from edgar import get_filings
filings = get_filings(2024, 1, form="10-K")
# Type: Filings (base class)
```
### Feature Comparison
| Feature | Base Filings | EntityFilings |
|---------|-------------|---------------|
| Filter by form | ✅ | ✅ |
| Filter by date | ✅ | ✅ |
| Filter by CIK/ticker | ✅ | ❌ (already scoped to entity) |
| Returns EntityFiling | ❌ | ✅ |
| Entity context (CIK, name) | ❌ | ✅ |
| Type preserved in operations | Filings | EntityFilings |
| From Company.get_filings() | ❌ | ✅ |
## Best Practices
### 1. Use EntityFilings for Company Analysis
When working with a specific company, always use `Company.get_filings()`:
```python
# Good - get EntityFilings with context
company = Company("AAPL")
filings = company.get_filings(form="10-K")
# Less ideal - get base Filings, requires filtering
from edgar import get_filings
all_filings = get_filings(2024, 1, form="10-K")
apple_filings = all_filings.filter(ticker="AAPL")
```
### 2. Check Empty Collections
```python
filings = company.get_filings(form="RARE-FORM")
if filings.empty:
print("No filings found")
else:
latest = filings.latest()
```
### 3. Use latest() for Single Most Recent
```python
# Get single filing
filing = filings.latest()
# Not this (gets collection of 1)
filings_one = filings.head(1)
filing = filings_one[0]
```
### 4. Preserve Type Through Operations
```python
# All these return EntityFilings
filtered = filings.filter(form="10-K")
recent = filtered.filter(filing_date="2024-01-01:")
sample = recent.sample(10)
# All maintain entity context
print(sample.cik) # Still accessible
print(sample.company_name) # Still accessible
```
## Error Handling
### Empty Collections
```python
filings = company.get_filings(form="NONEXISTENT")
if filings.empty:
print("No filings found")
else:
# Safe to access
latest = filings.latest()
```
### Pagination at Boundaries
```python
# At end of pages
last_page = filings
while True:
next_page = last_page.next()
if next_page is None:
print("Reached end of filings")
break
last_page = next_page
```
### Invalid Index
```python
# Check length first
if len(filings) > 5:
filing = filings[5]
else:
print("Collection has fewer than 6 filings")
```
## Performance Considerations
### Efficient Filtering
Filter early to reduce data size:
```python
# Good: filter first, then process
recent_10k = company.get_filings(form="10-K", filing_date="2023-01-01:")
for filing in recent_10k:
process(filing)
# Less efficient: get all, then filter in Python
all_filings = company.get_filings()
for filing in all_filings:
if filing.form == "10-K" and filing.filing_date >= "2023-01-01":
process(filing)
```
### Use Pagination
For very large collections, use pagination:
```python
# Process page by page
current_page = company.get_filings()
while current_page:
# Process current page
for filing in current_page:
process(filing)
# Move to next page
current_page = current_page.next()
```
### DataFrame Conversion
Only convert to pandas when needed:
```python
# Good: operate on EntityFilings directly
filings_10k = filings.filter(form="10-K")
latest = filings_10k.latest()
# Less efficient: convert to DataFrame first
df = filings.to_pandas()
df_10k = df[df['form'] == '10-K']
# Now you've lost EntityFiling functionality
```
## Integration with Company
EntityFilings is the primary interface between Company and Filing objects:
```python
company = Company("AAPL")
# Company.get_filings() returns EntityFilings
filings = company.get_filings()
# EntityFilings contains EntityFiling instances
filing = filings[0]
# EntityFiling knows its entity
entity = filing.get_entity()
# entity is the same Company object
```
This creates a seamless workflow for entity-focused analysis while maintaining proper type separation and functionality at each level.