quantlab.dataset.crsp.symbology.CrspSymbology#

class quantlab.dataset.crsp.symbology.CrspSymbology(security_info)[source]#

Bases: object

Ticker intervals per PERMNO, computed once from stksecurityinfohist.

The one public method, symbol_intervals, caches its result on the instance because a conversion reads it more than once.

Parameters:
security_infopl.DataFrame

The stksecurityinfohist table as CrspReference.table returns it.

Attributes:
security_infopl.DataFrame

The table given to the constructor.

Examples

>>> from quantlab.dataset.crsp.reference import CrspReference
>>> from quantlab.dataset.crsp.symbology import CrspSymbology
>>> ref = CrspReference("data/downloads/us_equity/1d/wrds_crsp/_reference")
>>> symbology = CrspSymbology(ref.table("stksecurityinfohist"))
>>> symbology.symbol_intervals().filter(pl.col("permno") == 13407)
shape: (2, 4)
┌────────┬────────┬────────────┬────────────┐
│ permno ┆ symbol ┆ start_date ┆ end_date   │
│ ---    ┆ ---    ┆ ---        ┆ ---        │
│ i64    ┆ str    ┆ date       ┆ date       │
╞════════╪════════╪════════════╪════════════╡
│ 13407  ┆ FB     ┆ 2012-05-18 ┆ 2022-06-08 │
│ 13407  ┆ META   ┆ 2022-06-09 ┆ 2025-12-31 │
└────────┴────────┴────────────┴────────────┘
static empty_sidecar_payload(product_end)[source]#

Return a sidecar payload with no intervals for the given product end.

Examples

>>> CrspSymbology.empty_sidecar_payload(date(2025, 12, 31))
{'generated_from': 'stksecurityinfohist', 'vintage_product_end': '2025-12-31', 'intervals': {}}
resolve(pairs)[source]#

Return the PERMNO each (date, symbol) pair named on that date.

A pair whose symbol no PERMNO used on that date is left out of the result rather than raising: a ticker that trades on TAQ but is not in CRSP (a security CRSP does not cover) is a fact about the data, and the caller decides whether to warn about it. A pair that two PERMNOs claim on the same date is an error in the reference table, so it raises.

Parameters:
pairspl.DataFrame

Columns date (Date) and symbol (String), in the dot notation symbol_intervals produces (BRK.B).

Returns:
pl.DataFrame

Columns date, symbol and permno (Int64), one row per resolved input pair, sorted by (date, symbol).

Raises:
ValueError

If a (date, symbol) pair resolves to more than one PERMNO.

Examples

>>> from datetime import date
>>> pairs = pl.DataFrame(
...     {"date": [date(2022, 6, 8), date(2022, 6, 9)], "symbol": ["FB", "META"]}
... )
>>> symbology.resolve(pairs)
shape: (2, 3)
┌────────────┬────────┬────────┐
│ date       ┆ symbol ┆ permno │
│ ---        ┆ ---    ┆ ---    │
│ date       ┆ str    ┆ i64    │
╞════════════╪════════╪════════╡
│ 2022-06-08 ┆ FB     ┆ 13407  │
│ 2022-06-09 ┆ META   ┆ 13407  │
└────────────┴────────┴────────┘
sidecar_payload(permnos, product_end)[source]#

Build the ticker sidecar payload for permnos.

The payload is {"generated_from", "vintage_product_end", "intervals"}. intervals maps str(permno) to that PERMNO’s named intervals in ascending start order, each {"ticker", "start", "end"} with both ends inclusive. It stores intervals rather than one name per PERMNO because a renamed company keeps its PERMNO, and a single latest name would label its early years with the later name. Only permnos are written, not the whole reference table. vintage_product_end (the last date of the CRSP data version) is included because a newer CRSP version can add a later interval for the same PERMNO. Intervals with no ticker are dropped: the sidecar answers “what is it called”, and a missing interval and a nameless one give the same answer.

quantlab.dataset.crsp.tickers.CrspTickerLookup reads the file this payload is written to.

Parameters:
permnositerable of int

The panel’s PERMNOs.

product_enddate or str

The CRSP product end of the reference tables.

Returns:
dict

The JSON-ready sidecar payload.

Examples

>>> symbology.sidecar_payload([83443], date(2025, 12, 31))["intervals"]
{'83443': [{'ticker': 'BRK', 'start': '1996-05-09', 'end': '2002-01-01'},
           {'ticker': 'BRK.B', 'start': '2002-01-02', 'end': '2025-12-31'}]}
symbol_intervals()[source]#

Return (permno, symbol, start_date, end_date), one row per interval.

The rows are sorted by (permno, start_date). permno is Int64, symbol is String and both dates are Date. The result is computed once and cached. These four columns are also the schema of the ticker sidecar written next to a converted store.

symbol is null only where a PERMNO’s first interval already has no ticker, so there is no earlier name to carry forward. The nulls are kept so “this PERMNO had no ticker yet” stays visible; call .drop_nulls("symbol") to keep only named intervals.

Returns:
pl.DataFrame

One row per interval with columns permno, symbol, start_date and end_date.

Examples

>>> symbology.symbol_intervals().filter(pl.col("permno") == 83443)
shape: (2, 4)
┌────────┬────────┬────────────┬────────────┐
│ permno ┆ symbol ┆ start_date ┆ end_date   │
│ ---    ┆ ---    ┆ ---        ┆ ---        │
│ i64    ┆ str    ┆ date       ┆ date       │
╞════════╪════════╪════════════╪════════════╡
│ 83443  ┆ BRK    ┆ 1996-05-09 ┆ 2002-01-01 │
│ 83443  ┆ BRK.B  ┆ 2002-01-02 ┆ 2025-12-31 │
└────────┴────────┴────────────┴────────────┘