quantlab.dataset.crsp#

CRSP Stock v2 daily price panel with PERMNOs as the symbol axis.

CRSP (the Center for Research in Security Prices) is a US stock database sold through WRDS (Wharton Research Data Services); dsf_v2 is its daily stock file. A PERMNO is CRSP’s permanent integer id for one security; unlike a ticker it never changes and is never reused, so a renamed or delisted company keeps one column for its whole history. A panel is an xarray.Dataset indexed by timestamp and symbol, the format every quantlab layer exchanges.

The acquisition step stores the dsf_v2 rows unchanged as the raw tier, one parquet file (shard) per PERMNO. CrspStockDataset converts it into the same dense (timestamp, symbol) Zarr panel that StockDataset produces for Tiingo: the twelve Tiingo variables plus the CRSP extras in CRSP_EXTRA_VARIABLES. A factor, label or backtester can therefore read a CRSP store without knowing the vendor. The symbol coordinate is the integer PERMNO. The ticker each PERMNO had on each date is written to a sidecar JSON file next to the store and read back by quantlab.dataset.crsp.tickers.

For each PERMNO, sorted by date, the conversion derives:

  • close = abs(dlyprc), except that a delisting-amount row (dlyprcflg in _NO_PRICE_FLAGS, or dlyprc == 0) carries no price and is NaN.

  • adjClose (the split- and dividend-adjusted close): the PERMNO’s first usable close inside the window (the anchor row), grown by prod(1 + dlyret) since that row. A null return counts as a factor of 1, because a CRSP return already spans any gap back to the previous valid price. adjClose is NaN on a row without a close, except on a delisting row (dlydelflg == "Y") with a non-null dlyret: there it is the previous adjClose times 1 + dlyret, the delisting return, so the delisting row is the security’s last valuation. dlyret is a total return, so merger cash on that row (in divCash) is counted once. A no-price delisting row without a return keeps adjClose NaN; none is imputed. A priced delisting row (CRSP’s dlyprcflg = DP) without a return gets the return CRSP’s own definition gives from its recorded prices, (close * dlyfacprc + divCash) / close_prev - 1 with close_prev the last earlier close, so the delisting price’s loss reaches adjClose; ret itself stays NaN there. adjOpen/adjHigh/adjLow are scaled by adjClose / close, and adjVolume by dlycumfacshr (CRSP’s cumulative share-adjustment factor) relative to the anchor row.

  • splitFactor = dlycumfacpr[t-1] / dlycumfacpr[t] (1.0 on the first row) and divCash = dlyorddivamt + dlynonorddivamt on the ex-date.

The adjustment is computed once over the whole configured window before any date slicing, so converting in chunks and converting in one go produce the same store. ret keeps a missing CRSP return as NaN rather than 0. The delisting return is applied exactly once: CRSP already puts it on the delisting day’s row, so nothing adds stkdelists.delret on top. A security filter keeps only the security types asked for (for example common stock) and writes a report of what it dropped next to the store. See docs/user-guide/wrds.md.

Classes

CrspStockDataset

Dense daily panel built from the CRSP raw files, keyed by PERMNO.

Functions

resolve_security_filter

Resolve a security_filter value to {column: allowed values}.

Modules

market

The CRSP market roster: every listed security, not an index's members.

membership

Point-in-time index membership from the CRSP reference tables, keyed by PERMNO.

reference

Readers for the CRSP reference tables, six whole tables stored next to the raw daily data.

symbology

PERMNO-to-ticker intervals derived from CRSP's security-information history.

tickers

Read the ticker sidecar to show a CRSP PERMNO as a readable ticker.