quantlab.dataset.crsp.market.CrspMarketRoster#

class quantlab.dataset.crsp.market.CrspMarketRoster(reference)[source]#

Bases: object

Every CRSP security and the dates it was listed, from one reference directory.

The roster is point-in-time: it records when each security was listed, not only whether it is listed today. It holds no database connection and needs no login, because it only reads parquet files on disk.

Parameters:
referenceCrspReference

The downloaded CRSP reference tables.

Attributes:
referenceCrspReference

The reference tables given to the constructor.

reportdict

Counts from the most recent permno_intervals call: spells read, dropped by type, dropped or clipped at the product end, and PERMNOs before and after the type filter.

Examples

>>> from quantlab.dataset.crsp.market import CrspMarketRoster
>>> from quantlab.dataset.crsp.reference import CrspReference
>>> ref = CrspReference("data/downloads/us_equity/1d/wrds_crsp/_reference")
>>> roster = CrspMarketRoster(ref)
>>> roster.permnos_in_range("2010-01-01", "2010-12-31")
['10001', '10002']
>>> roster.report["permnos_after_type_filter"]
2
SOURCE_TABLE = 'stksecurityinfohist'#

The table this roster is read from; every reference download has it.

permno_intervals(*, security_filter='equity_common')[source]#

Return the qualifying listing intervals as (permno, start_date, end_date).

There is one row per continuous qualifying interval of one PERMNO, sorted, with both ends inclusive. end_date is never null and never later than CrspReference.product_end (the last date of the downloaded CRSP data). Adjacent qualifying spells are merged, so a common share that changed ticker four times is one interval. Spells that do not qualify are dropped before merging, so a security that was an ADR (a foreign share traded in the US) and later ordinary common stock comes back as the common-stock period only.

Parameters:
security_filterstr or dict, default “equity_common”

A preset name ("equity_common", "shrcd_10_11", "none") or a {column: allowed values} mapping, resolved by resolve_security_filter.

Returns:
pl.DataFrame

Columns permno (Int64), start_date and end_date (Date).

Raises:
ValueError

If security_filter is not a valid preset or mapping, or if a source row has a null PERMNO or start.

Examples

>>> roster.permno_intervals()
shape: (2, 3)
┌────────┬────────────┬────────────┐
│ permno ┆ start_date ┆ end_date   │
│ ---    ┆ ---        ┆ ---        │
│ i64    ┆ date       ┆ date       │
╞════════╪════════════╪════════════╡
│ 10001  ┆ 2000-01-03 ┆ 2025-12-31 │
│ 10002  ┆ 2000-01-03 ┆ 2010-06-30 │
└────────┴────────────┴────────────┘
permnos_in_range(start_date, end_date, *, security_filter='equity_common')[source]#

Return every PERMNO whose qualifying interval overlaps the window.

The window is [start_date, end_date], both ends inclusive. The test is overlap (start_date <= end and end_date >= start), as in CrspMembership.permnos_in_range, so a security delisted inside the window is still included.

The order is numeric, as quantlab.utils.symbol_axis.sort_symbol_axis defines it, not lexicographic: "7000" sorts before "14593".

Parameters:
start_datedate or str

Window start, as a date or ISO string.

end_datedate or str

Window end, inclusive.

security_filterstr or dict, default “equity_common”

As for permno_intervals.

Returns:
list of str

PERMNOs as strings, in numeric order.

Raises:
ValueError

If start_date is after end_date.

Examples

>>> roster.permnos_in_range("2011-01-01", "2011-12-31")
['10001']
>>> roster.permnos_in_range(
...     "2011-01-01", "2011-12-31", security_filter="none"
... )
['10001', '10004']
report#

What the last permno_intervals call excluded, clipped or filtered.