Skip to content

XBRL.entity_info should preserve repeated dei:TradingSymbol facts and expose a deterministic scalar policy #1252

Description

@synfonia-llc

Feature Category

  • New API functionality
  • Performance improvement
  • Developer experience improvement
  • Documentation enhancement
  • Tool/utility addition

Problem Statement

Is your feature request related to a problem? Please describe.

XBRL.entity_info["ticker"] is a scalar, but SEC filings can contain several dei:TradingSymbol facts for different classes and securities. For JPMorgan Chase's 2024 10-K, the filing contains ten symbols in document order:

JPM
JPM PR D
JPM PR C
JPM PR J
JPM PR K
JPM PR L
JPM PR M
AMJ
JPM/32
AMJB

The fact-query API preserves all ten facts and their StatementClassOfStockAxis members, but the entity-info projection retains only AMJB, the last occurrence. The scalar therefore changes with source-document order and loses the evidence callers would need to choose a security.

There is not currently a documented EdgarTools contract or an unambiguous DEI rule establishing which one of several filed symbols must be called the registrant's single "primary" ticker. For that reason, this is a feature request for an explicit multi-symbol/selection contract rather than a bug report asserting that the scalar must equal JPM.

Who would benefit from this feature?

  • Beginner Python users working with SEC filings
  • Financial analysts and researchers
  • Advanced developers building financial applications
  • Data scientists working with financial datasets

Proposed Solution

Describe the solution you'd like

Preserve every dei:TradingSymbol occurrence in entity metadata together with its context and complete class-of-stock dimensions. If EdgarTools continues to expose the convenience scalar entity_info["ticker"], document and implement a deterministic selection policy and expose the selected fact's provenance.

For example, the public model could provide a trading_symbols collection whose entries include:

  • symbol value;
  • context reference;
  • class-of-stock axis/member;
  • source fact ID; and
  • whether and why that occurrence was selected for the scalar convenience field.

The exact primary-selection policy is an API decision for the maintainer. The important invariants are that document order alone does not silently decide the scalar and that callers can recover every filed alternative.

Describe alternatives you've considered

  • Keep only the first or last occurrence. This is deterministic only with respect to document order and discards security identity.
  • Always select the common-stock member. That works for this filing but may not define a universal primary symbol for dual-class, preferred-only, fund, or other multi-security registrants.
  • Return no scalar when several symbols exist. This avoids a false choice but is a compatibility change; retaining a documented scalar alongside the full collection may be more practical.
  • Allow a caller-supplied selection callback over the preserved occurrences.

Use Case Example

How would you use this feature?

from pathlib import Path

from edgar.xbrl import XBRL

root = Path("tests/fixtures/xbrl/jpm/10k_2024")
xbrl = XBRL.from_files(
    instance_file=root / "jpm-20240216_htm.xml",
    schema_file=root / "jpm-20240216.xsd",
    presentation_file=root / "jpm-20240216_pre.xml",
    calculation_file=root / "jpm-20240216_cal.xml",
    definition_file=root / "jpm-20240216_def.xml",
    label_file=root / "jpm-20240216_lab.xml",
)

symbols = (
    xbrl.query()
    .by_concept("dei:TradingSymbol", exact=True)
    .execute()
)

print([fact["value"] for fact in symbols])
print(xbrl.entity_info["ticker"])

# Proposed shape; exact naming is for maintainer design.
for symbol in xbrl.entity_info["trading_symbols"]:
    print(symbol.value, symbol.context_ref, symbol.dimensions)

Current-main output:

['JPM', 'JPM PR D', 'JPM PR C', 'JPM PR J', 'JPM PR K',
 'JPM PR L', 'JPM PR M', 'AMJ', 'JPM/32', 'AMJB']
AMJB

The first occurrence, JPM, uses StatementClassOfStockAxis=CommonStockMember. Each later occurrence has a different filed member covering preferred stock, ETNs, or guaranteed notes. The checked-in fixture metadata identifies the acquisition ticker as JPM, but that metadata is corroborating application context—not a DEI rule that independently defines the scalar selection contract.

Implementation Considerations

Complexity Level:

  • Simple (minor API addition)
  • Moderate (new functionality with existing patterns)
  • Complex (significant architectural changes)

Backwards Compatibility:

  • This feature maintains backwards compatibility
  • This feature might break existing code (please explain below)
  • Unsure about compatibility impact

Adding a full collection can be backward compatible. Changing the existing scalar from the last occurrence to another policy could change current output for multi-security filings, so the selected policy and migration behavior should be documented.

Additional Context

Verified environment: EdgarTools import version 5.55.0; distribution metadata 5.54.0 (stale editable-install metadata); Python 3.14.4 on Microsoft Windows. The reproduction ran on origin/main at a0ff18089c844ddfe81bd21a1c7c56f4ed629e55 from audit worktree HEAD 70c31469dc7e6d4b386a6f8fe4ce1276d48fca51, whose edgar/** tree is identical to origin/main.

The present collapse occurs in InstanceParser._extract_entity_info(). Parsed DEI facts are stored in self.dei_facts under only the concept local name, so each repeated TradingSymbol assignment replaces the prior occurrence before get_dei("TradingSymbol") populates the scalar.

Related Issues/Features:

This request is limited to the repeated-DEI-to-entity-info projection. It does not propose discarding additional symbols or changing the underlying fact-query results.

A live search of the open and closed GitHub tracker is still required immediately before submission to avoid filing a duplicate.


Feature requests are evaluated based on EdgarTools' core principles: Simple yet powerful, accurate financials, beginner-friendly, and joyful UX.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions