Skip to content

PeriodType Quick Reference

FEAT-003: PeriodType Enum for EdgarTools
Enhanced developer experience through IDE autocomplete and parameter validation for financial reporting periods.

📋 Available Period Types

Enum Value String Value Description Use Case
PeriodType.ANNUAL "annual" Annual reporting periods Full fiscal year financial data
PeriodType.QUARTERLY "quarterly" Quarterly reporting periods 3-month period financial data
PeriodType.MONTHLY "monthly" Monthly reporting periods Monthly financial data (rare)
PeriodType.TTM "ttm" Trailing Twelve Months Rolling 12-month performance
PeriodType.YTD "ytd" Year to Date Current year performance

Convenience Aliases

Alias Same As Notes
PeriodType.YEARLY PeriodType.ANNUAL Alternative naming
PeriodType.QUARTER PeriodType.QUARTERLY Shorter form

🚀 Basic Usage

Import

from edgar.enums import PeriodType, PeriodInput, validate_period_type

Function Parameters (New Style)

from edgar import Company
from edgar.enums import PeriodType

# Enhanced with autocomplete for financial statements
company = Company("AAPL")

# NEW: Direct period type filtering in get_facts()
annual_facts = company.get_facts(period_type=PeriodType.ANNUAL)
quarterly_facts = company.get_facts(period_type=PeriodType.QUARTERLY)

# NEW: Export facts to DataFrame for custom analysis
df = annual_facts.to_dataframe()
print(df.head())

# Filter and analyze
revenue_facts = df[df['concept'].str.contains('Revenue')]
print(revenue_facts[['fiscal_year', 'numeric_value']])

# NEW: Query interface with PeriodType enum
facts = company.get_facts()
annual_facts = facts.query().by_period_type(PeriodType.ANNUAL).execute()
quarterly_facts = facts.query().by_period_type(PeriodType.QUARTERLY).execute()

# Existing methods still work (backward compatibility)
annual_income = facts.income_statement(annual=True)       # Annual periods
quarterly_income = facts.income_statement(annual=False)   # Quarterly periods

Backwards Compatibility (Existing Style)

# Still works - no breaking changes
from edgar import Company

company = Company("AAPL")
facts = company.get_facts()
annual_income = facts.income_statement(annual=True)
quarterly_income = facts.income_statement(annual=False)

🛡️ Enhanced Validation

Smart Error Messages

from edgar.enums import validate_period_type

# Typo detection
try:
    validate_period_type("anual")  # misspelled
except ValueError as e:
    print(e)  # Error: "Invalid period type 'anual'. Did you mean: annual?"

# Invalid input
try:
    validate_period_type("invalid")
except ValueError as e:
    print(e)  # Error: "Invalid period type 'invalid'. Use PeriodType enum for autocomplete..."

🔧 Function Integration

Type Hints

from edgar.enums import PeriodInput, PeriodType, validate_period_type

def analyze_financials(ticker: str, period: PeriodInput = PeriodType.ANNUAL) -> str:
    """Function with PeriodType parameter."""
    validated_period = validate_period_type(period)
    return f"Analyzing {ticker} {validated_period} financials"

# Usage
result1 = analyze_financials("AAPL", PeriodType.QUARTERLY)  # IDE autocomplete
result2 = analyze_financials("MSFT", "ttm")                 # String still works

Migration from Boolean Annual

from edgar.enums import PeriodInput, PeriodType, validate_period_type

# Old pattern
def old_style(annual: bool = True) -> str:
    period = "annual" if annual else "quarterly"
    return f"Getting {period} data"

# New pattern - more expressive
def new_style(period: PeriodInput = PeriodType.ANNUAL) -> str:
    period_str = validate_period_type(period)
    return f"Getting {period_str} data"

# Benefits:
# ✅ Support for TTM, YTD, monthly (not just annual/quarterly)
# ✅ IDE autocomplete 
# ✅ Validation prevents typos
# ✅ Self-documenting code

📚 Convenience Collections

from edgar.enums import STANDARD_PERIODS, SPECIAL_PERIODS, ALL_PERIODS

# Most common periods
for period in STANDARD_PERIODS:
    print(f"Standard: {period}")  # ANNUAL, QUARTERLY

# Special analysis periods  
for period in SPECIAL_PERIODS:
    print(f"Special: {period}")   # TTM, YTD

# All available periods
for period in ALL_PERIODS:
    print(f"Available: {period}") # All 5 period types

🌍 Real-World Examples

Financial Analysis

from edgar.enums import PeriodInput, PeriodType

def compare_performance(ticker: str, periods: list[PeriodInput]) -> dict:
    """Compare company performance across different periods."""
    from edgar import Company

    company = Company(ticker)
    results = {}

    for period in periods:
        # NEW: Direct period filtering in get_facts()
        try:
            period_facts = company.get_facts(period_type=period)
            if period_facts:
                # Get income statement data from filtered facts
                income_stmt = period_facts.income_statement(periods=1)
                results[str(period)] = income_stmt
        except NotImplementedError:
            # Handle TTM/YTD (not yet implemented)
            facts = company.get_facts()
            if str(period) == "ttm":
                # Get last 4 quarters for TTM calculation
                data = facts.income_statement(annual=False, periods=4)
                results["ttm"] = data

    return results

# Usage with mixed types
analysis = compare_performance("AAPL", [
    PeriodType.ANNUAL,     # Enum
    "quarterly",           # String
    PeriodType.MONTHLY     # Enum - now supported!
])

# NEW: Enhanced query combinations
company = Company("AAPL")
facts = company.get_facts()

# Combine period filtering with concept filtering
annual_revenue = facts.query().by_period_type(PeriodType.ANNUAL).by_concept("Revenue").execute()
quarterly_revenue = facts.query().by_period_type("quarterly").by_concept("Revenue").execute()

# Filter specific period types directly
annual_facts = facts.filter_by_period_type(PeriodType.ANNUAL)
quarterly_facts = facts.filter_by_period_type(PeriodType.QUARTERLY)

Batch Processing

from edgar.enums import PeriodInput, PeriodType

def process_companies(tickers: list[str],
                     period: PeriodInput = PeriodType.QUARTERLY) -> dict:
    """Process multiple companies for specified period."""
    from edgar import Company
    from edgar.enums import validate_period_type

    period_str = validate_period_type(period)
    results = {}

    for ticker in tickers:
        company = Company(ticker)
        facts = company.get_facts()
        statement = None  # Initialize statement variable

        if period_str == "annual":
            statement = facts.income_statement(annual=True, periods=1)
        elif period_str == "quarterly":
            statement = facts.income_statement(annual=False, periods=1)

        if statement is not None:
            results[ticker] = statement

    return results

# Usage
from edgar.enums import PeriodType

tech_stocks = ["AAPL", "MSFT", "GOOGL"]
result = process_companies(tech_stocks, PeriodType.QUARTERLY)

Period Iteration

def comprehensive_analysis(ticker: str) -> dict:
    """Analyze company across all standard periods."""
    from edgar import Company
    from edgar.enums import STANDARD_PERIODS

    company = Company(ticker)
    facts = company.get_facts()
    results = {}

    for period in STANDARD_PERIODS:
        # Each period provides IDE autocomplete when used
        statement = None  # Initialize statement variable

        if period.value == "annual":
            statement = facts.income_statement(annual=True, periods=2)
        elif period.value == "quarterly":
            statement = facts.income_statement(annual=False, periods=4)

        if statement is not None:
            results[period.value] = statement

    return results

💡 IDE Benefits

With PeriodType, your IDE will provide:

Autocomplete

When you type PeriodType., your IDE shows:

PeriodType.ANNUAL     # 'annual' - Full fiscal year
PeriodType.QUARTERLY  # 'quarterly' - 3-month periods  
PeriodType.MONTHLY    # 'monthly' - Monthly periods
PeriodType.TTM        # 'ttm' - Trailing twelve months
PeriodType.YTD        # 'ytd' - Year to date

Documentation

Hover over enum values to see descriptions: - ANNUAL: Annual reporting periods (full fiscal year) - QUARTERLY: Quarterly reporting periods (3-month periods) - TTM: Trailing Twelve Months for rolling performance analysis

Type Safety

Your IDE will warn about: - Invalid period types - Wrong parameter types - Potential typos before runtime

🔄 Migration Guide

From Boolean Annual Parameter

Before:

# Limited to annual/quarterly only
from edgar import Company

company = Company("AAPL")
facts = company.get_facts()
annual_income = facts.income_statement(annual=True)    # Annual data
quarterly_income = facts.income_statement(annual=False)   # Quarterly data

After:

# Rich period support with enhanced querying
from edgar import Company

company = Company("AAPL")
facts = company.get_facts()

# Financial statement methods with boolean parameters
annual_income = facts.income_statement(annual=True)     # Annual
quarterly_income = facts.income_statement(annual=False) # Quarterly

# Advanced period filtering with query interface
ttm_facts = facts.query().by_period_length(12).get()   # Trailing twelve months
quarterly_facts = facts.query().by_period_length(3).get() # Quarterly periods

# Individual fact retrieval with period specification
# Use XBRL concept names or lowercase labels (not simplified names like "Revenue")
revenue_2024 = facts.get_fact("us-gaap:RevenueFromContractWithCustomerExcludingAssessedTax", period="2024-FY")
net_income = facts.get_fact("net income (loss) attributable to parent", period="2024-Q1")

From String Parameters

Before:

# Typo-prone, no autocomplete
def analyze_data(period: str) -> str:
    return f"Analyzing {period} data"

analyze_data("annual")     # Could typo as "anual"
analyze_data("quarterly")  # Could typo as "quartly"

After:

# Autocomplete prevents typos
from edgar.enums import PeriodType, PeriodInput, validate_period_type

def analyze_data(period: PeriodInput) -> str:
    validated_period = validate_period_type(period)
    return f"Analyzing {validated_period} data"

analyze_data(PeriodType.ANNUAL)     # IDE autocomplete
analyze_data(PeriodType.QUARTERLY)  # IDE autocomplete

# Strings still work with validation
analyze_data("annual")     # Validated, helpful errors if typo

⚖️ Consistency with FormType

PeriodType follows the same design pattern as FormType:

Feature FormType PeriodType
Enum Type StrEnum StrEnum
Validation validate_form_type() validate_period_type()
Type Hints FormInput PeriodInput
Collections PERIODIC_FORMS, etc. STANDARD_PERIODS, etc.
Error Handling Smart suggestions Smart suggestions
Backwards Compat ✅ Union types ✅ Union types

🎯 Best Practices

1. Use Enums for New Code

# Recommended: Enhanced developer experience
from edgar.enums import PeriodInput, PeriodType

def analyze_trends(period: PeriodInput = PeriodType.ANNUAL) -> str:
    return f"Analyzing trends for {period}"

2. Maintain String Compatibility

# Support both for flexibility
from edgar.enums import PeriodInput, validate_period_type

def flexible_function(period: PeriodInput) -> str:
    validated = validate_period_type(period)  # Handles both
    return f"Processing {validated} data"

3. Leverage Collections

# Use predefined collections
from edgar.enums import STANDARD_PERIODS

def process_period(period_type):
    return f"Processing {period_type}"

for period in STANDARD_PERIODS:
    result = process_period(period)
    print(result)

4. Provide Good Defaults

# Use meaningful defaults
from edgar.enums import PeriodInput, PeriodType

def get_financials(period: PeriodInput = PeriodType.ANNUAL) -> str:
    """Default to annual for most financial analysis."""
    return f"Getting {period} financials"

🚦 Error Handling

Common Errors and Solutions

from edgar.enums import validate_period_type, PeriodType

# Typo in string
try:
    validate_period_type("anual")
except ValueError as e:
    print(e)  # "Did you mean: annual?"

# Wrong type
try:
    validate_period_type("123")  # Use string instead of int
except ValueError as e:
    print(e)  # "Invalid period type '123'..."

# Completely invalid
try:
    validate_period_type("invalid")
except ValueError as e:
    print(e)  # "Use PeriodType enum for autocomplete..."

🆕 API Enhancements

Period-Type Filtering Feature adds direct filtering capabilities:

New Methods

# Direct filtering in get_facts()
annual_facts = company.get_facts(period_type=PeriodType.ANNUAL)

# Query interface filtering
facts.query().by_period_type(PeriodType.QUARTERLY)

# EntityFacts filtering
facts.filter_by_period_type(PeriodType.ANNUAL)

Enhanced Workflow

from edgar import Company
from edgar.enums import PeriodType

# Before: Multi-step process
company = Company("AAPL")
facts = company.get_facts()
annual_income = facts.income_statement(annual=True)

# After: Direct, intuitive filtering
annual_facts = company.get_facts(period_type=PeriodType.ANNUAL)
annual_income = annual_facts.income_statement()

# Advanced: Query combinations
revenue_annual = company.get_facts().query()\
    .by_concept("Revenue")\
    .by_period_type(PeriodType.ANNUAL)\
    .execute()

📈 Impact Summary

Period-Type Filtering delivers on EdgarTools principles:

  • Simple yet powerful: Direct filtering eliminates multi-step processes
  • Beginner-friendly: IDE autocomplete reveals filtering options
  • Joyful UX: Intuitive API that works as expected
  • Accurate financials: Type-safe period specification

Key improvements: - 🎯 IDE autocomplete for period types - 🛡️ Enhanced validation with smart error messages - ⚡ Direct period filtering in get_facts() - 🔍 Query interface period filtering - 🔧 Seamless integration with existing API - 🔄 Clear migration path from boolean parameters - ⚖️ Consistent design with FormType enum