Initial commit
This commit is contained in:
1070
venv/lib/python3.10/site-packages/edgar/entity/docs/Company.md
Normal file
1070
venv/lib/python3.10/site-packages/edgar/entity/docs/Company.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user