call_report.fca.FCAInstitutionRegistry#

class call_report.fca.FCAInstitutionRegistry(*, institutions: Iterable[FCAInstitution])[source]#

Bases: Mapping[int, FCAInstitution]

A read-only mapping of each UNINUM to its FCAInstitution.

Iterating yields UNINUMs in ascending order. Most callers build a registry with from_dataframe or from_rosters rather than from FCAInstitution objects directly.

Parameters:
institutionsIterable[FCAInstitution]

The histories making up the registry, in any order.

Raises:
InstitutionError

If institutions is empty, or two share a UNINUM.

See also

FCAInstitution

One UNINUM’s name and address history.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> texas = {
...     "UNINUM": 610000,
...     "SYSTEM": 6,
...     "DIST": 10,
...     "ASSOC": 0,
...     "SHORTNAME": "FCB of Texas",
...     "MAIL_ADDR": "P.O. Box 202590",
...     "STREET_ADDR": "4801 Plaza on the Lake Drive",
...     "CITY": "Austin",
...     "STATE": "TX",
...     "ZIP": "78746",
... }
>>> agfirst = {
...     "UNINUM": 620000,
...     "SYSTEM": 6,
...     "DIST": 20,
...     "ASSOC": 0,
...     "SHORTNAME": "AgFirst FCB",
...     "MAIL_ADDR": "P. O. Box 1499",
...     "STREET_ADDR": "1901 Main Street",
...     "CITY": "Columbia",
...     "STATE": "SC",
...     "ZIP": "29201",
... }
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2026-03-31", [texas, agfirst])]
... )
>>> list(registry)
[610000, 620000]
>>> registry[620000].most_recent_short_name
'AgFirst FCB'
classmethod from_rosters(*, rosters: Iterable[tuple[str | date | ReportingPeriod, Any]]) → FCAInstitutionRegistry[source]#

Build a registry from FCA institution rosters, one per quarter.

Every row across every roster is grouped by UNINUM, and each group becomes one FCAInstitution. The rosters can arrive in any order.

Parameters:
rostersIterable[tuple[str | datetime.date | ReportingPeriod, Any]]

(period, roster) pairs. A roster is either a native dataframe of any backend narwhals supports, such as the result of call_report.fca.institutions.read_institutions, or an iterable of row mappings. Each row must include UNINUM, SYSTEM, DIST, ASSOC, SHORTNAME, MAIL_ADDR, STREET_ADDR, CITY, STATE, and ZIP. Other columns are ignored.

Returns:
FCAInstitutionRegistry

One FCAInstitution per UNINUM found in rosters.

Raises:
InstitutionError

If rosters holds no rows, names the same quarter twice, or lists a UNINUM more than once in one quarter. Also for any row FCAInstitution.from_roster_rows rejects.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> renamed = {**row, "SHORTNAME": "Farm Credit Mid-America ACA"}
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-12-31", [renamed]), ("2011-09-30", [row])]
... )
>>> [v.value for v in registry[722825].short_name_history]
['Mid-America ACA', 'Farm Credit Mid-America ACA']
classmethod from_dataframe(*, data: Any) → FCAInstitutionRegistry[source]#

Build a registry from rosters stacked into one frame.

data is one row per UNINUM per quarter, with a period column naming each row’s quarter. That is the shape FCACallReport.load_institutions returns, and the shape to_dataframe returns, so a registry round-trips through its own frame. The most_recent_* columns are derived from the history, so they are ignored on the way in.

Parameters:
dataAny

A native dataframe of any backend narwhals supports, eager or lazy, with a period column and the roster columns from_rosters requires.

Returns:
FCAInstitutionRegistry

One FCAInstitution per UNINUM found in data.

Raises:
InstitutionError

If data has no period column, or for any roster from_rosters rejects.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row]), ("2011-12-31", [row])]
... )
>>> FCAInstitutionRegistry.from_dataframe(data=registry.to_dataframe()) == (
...     registry
... )
True
property first_period: ReportingPeriod[source]#

Return the earliest quarter any UNINUM in the registry was reported.

This is the smallest FCAInstitution.first_period in the registry.

Returns:
ReportingPeriod

The earliest quarter reported.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row]), ("2011-12-31", [row])]
... )
>>> registry.first_period.label
'2011Q3'
property last_period: ReportingPeriod[source]#

Return the latest quarter any UNINUM in the registry was reported.

This is the largest FCAInstitution.last_period in the registry.

Returns:
ReportingPeriod

The latest quarter reported.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row]), ("2011-12-31", [row])]
... )
>>> registry.last_period.label
'2011Q4'
as_of(*, period: str | date | ReportingPeriod) → Mapping[int, FCAInstitutionSnapshot][source]#

Return the roster values for every UNINUM reported in one quarter.

Charters that did not file in period are left out.

Parameters:
periodstr, datetime.date, or ReportingPeriod

The quarter-end to take the snapshot at.

Returns:
Mapping[int, FCAInstitutionSnapshot]

A read-only mapping of UNINUM to its snapshot for period, in ascending UNINUM order.

Raises:
PeriodNotAvailableError

If no UNINUM in the registry was reported in period.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> renamed = {**row, "SHORTNAME": "Farm Credit Mid-America ACA"}
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row]), ("2011-12-31", [renamed])]
... )
>>> registry.as_of(period="2011-09-30")[722825].short_name
'Mid-America ACA'
to_dataframe(*, latest_only: bool = False, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: None = None) → NativeDataFrame[source]#
to_dataframe(*, latest_only: bool = False, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['pandas']) → pandas.DataFrame
to_dataframe(*, latest_only: bool = False, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['pyarrow_table']) → pyarrow.Table
to_dataframe(*, latest_only: bool = False, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['polars_dataframe']) → polars.DataFrame
to_dataframe(*, latest_only: bool = False, backend: Literal['pandas', 'polars', 'pyarrow'] | None = None, dataframe_type: Literal['polars_lazyframe']) → polars.LazyFrame

Return every UNINUM’s history as one dataframe.

By default this stacks FCAInstitution.to_dataframe for every UNINUM, giving one row per UNINUM per quarter. Join it onto FCACallReport.to_long_format or FCACallReport.to_wide_format output on UNINUM and period to label each row with the name and address in effect that quarter.

Parameters:
latest_onlybool, default False

Keep only each UNINUM’s last reported quarter, giving one row per UNINUM. The period column then holds that last quarter.

backend{“pandas”, “polars”, “pyarrow”}, optional

The dataframe library used to build the frame. If omitted, uses whatever backend is currently configured via call_report.config.get_config. Most users can leave this at its default.

dataframe_type{“pandas”, “pyarrow_table”, “polars_lazyframe”, “polars_dataframe”}, optional

The dataframe type to convert the result to as a final step, regardless of backend. Leave this None (the default) to get back whatever backend produced. Set it when the code that consumes this result needs a specific type, for example a pandas DataFrame while the package is configured to use polars. The conversion is zero-copy when the requested type already matches.

Returns:
NativeDataFrame

A native dataframe with the columns FCAInstitution.to_dataframe returns, ordered by UNINUM and then period.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> renamed = {**row, "SHORTNAME": "Farm Credit Mid-America ACA"}
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row]), ("2011-12-31", [renamed])]
... )
>>> frame = registry.to_dataframe(dataframe_type="polars_dataframe")
>>> frame.height
2
>>> latest = registry.to_dataframe(
...     latest_only=True, dataframe_type="polars_dataframe"
... )
>>> latest.select("UNINUM", "period", "SHORTNAME").rows()
[(722825, datetime.date(2011, 12, 31), 'Farm Credit Mid-America ACA')]
to_json(*, indent: int | None = 2) → str[source]#

Return the registry as a JSON string.

Each UNINUM’s history is stored in the shape FCAInstitution.to_json produces, in ascending UNINUM order.

Parameters:
indentint, optional

Passed through to json.dumps. The default of 2 produces human-readable, diffable output. Pass None for the most compact representation.

Returns:
str

A JSON object with one key, institutions, holding a list of histories.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> registry = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row])]
... )
>>> FCAInstitutionRegistry.from_json(text=registry.to_json()) == registry
True
classmethod from_json(*, text: str) → FCAInstitutionRegistry[source]#

Reconstruct a registry from JSON built by to_json.

The inverse of to_json. Every history is validated the same way direct construction validates it.

Parameters:
textstr

A JSON string in the shape to_json produces.

Returns:
FCAInstitutionRegistry

The reconstructed registry.

Raises:
InstitutionError

If text is not valid JSON, is not a JSON object, or does not otherwise match the shape to_json produces.

Examples

>>> from call_report.fca import FCAInstitutionRegistry
>>> row = {
...     "UNINUM": 722825,
...     "SYSTEM": 7,
...     "DIST": 22,
...     "ASSOC": 825,
...     "SHORTNAME": "Mid-America ACA",
...     "MAIL_ADDR": "P.O. Box 34390",
...     "STREET_ADDR": "1601 UPS Drive",
...     "CITY": "Louisville",
...     "STATE": "KY",
...     "ZIP": "40223-4390",
... }
>>> text = FCAInstitutionRegistry.from_rosters(
...     rosters=[("2011-09-30", [row])]
... ).to_json()
>>> list(FCAInstitutionRegistry.from_json(text=text))
[722825]