quantlab.dataset.raw.IndexConstituentDataset#

class quantlab.dataset.raw.IndexConstituentDataset(config)[source]#

Bases: RawDataset

Daily point-in-time index-membership panel built from intervals.

A subclass implements two hooks: _pit_coverage_start (the earliest date the source can answer membership for) and _build_intervals (the membership intervals). Everything else is shared. Config normalisation raises start_date to the coverage start, _densify turns the intervals into the is_member grid, and _clean validates the panel instead of running the price-data (OHLCV) cleaner. The class derives from BaseDataset directly, so it has no KunQuant export.

Two conventions matter to a consumer. The timestamp axis covers every calendar day, weekends and holidays included, so to combine it with a trading-day price panel, select it onto the price timestamps rather than assuming the axes line up. Intervals include both end dates: a symbol removed on date D reads True on D and False on D + 1.

Parameters:
configConstituentDatasetConfig

The dataset config. as_of pins the right edge of the panel when some membership is still open; see _densify.

Examples

A minimal index over an in-memory interval table:

class DemoPanel(IndexConstituentDataset):
    def _pit_coverage_start(self, config) -> str:
        return "2020-01-01"

    def _build_intervals(self) -> pl.DataFrame:
        return pl.DataFrame(
            [
                ("AAA", "2020-01-01", None),
                ("BBB", "2020-01-01", "2020-01-05"),
                ("CCC", "2020-01-04", None),
            ],
            schema=["symbol", "start_date", "end_date"],
            orient="row",
        )
>>> config = ConstituentDatasetConfig(
...     zarr_file_path="data/demo.zarr",
...     start_date="2020-01-01",
...     end_date="2020-01-08",
...     as_of="2020-01-08",
... )
>>> panel = DemoPanel(config).from_raw_data().get_xarray_dataset()
>>> panel["is_member"].to_pandas().astype(int)
symbol      AAA  BBB  CCC
timestamp
2020-01-01    1    1    0
2020-01-02    1    1    0
2020-01-03    1    1    0
2020-01-04    1    1    1
2020-01-05    1    1    1
2020-01-06    1    0    1
2020-01-07    1    0    1
2020-01-08    1    0    1
config_cls#

The config class a saved config.json is rebuilt with.

alias of ConstituentDatasetConfig

is_member_at(timestamps, symbols, *, owner=None)[source]#

Return whether each symbol is a member on each timestamp’s date.

Each timestamp is matched to the membership panel by its calendar date, so the answer at bar t reads the membership of t’s date and nothing later. A symbol missing from the panel is not a member. A date the panel does not cover (before its first or after its last day) is refused, because unknown membership is not “not a member”.

Parameters:
timestampsarray-like of datetime64

The bars to answer for, such as a panel’s timestamp axis.

symbolsarray-like

The symbols to answer for, on the membership panel’s symbol axis.

ownerstr, optional

Who asks, named in the error message; defaults to this class.

Returns:
xr.DataArray

Booleans on (timestamp, symbol) with exactly the given coordinates.

Raises:
ValueError

If a timestamp’s date lies outside the membership panel, or none of symbols is on the membership store’s symbol axis (an integer permaticker against a text one), which would answer every symbol as a non-member.

Examples

With membership a DemoPanel (as in the class docstring) in which AAA is a member from 2024-01-01 on and BBB from 2024-01-01 to 2024-01-02, saved with as_of="2024-01-05":

>>> bars = pd.bdate_range("2024-01-02", periods=3)
>>> membership.is_member_at(bars, ["AAA", "BBB", "ZZZ"]).to_pandas()
symbol       AAA    BBB    ZZZ
timestamp
2024-01-02  True   True  False
2024-01-03  True  False  False
2024-01-04  True  False  False
mask(panel, *, owner=None)[source]#

Return panel with every cell of a symbol that is not a member on its bar’s date NaN.

This is the membership rule every masked factor, label and prediction applies (MembershipMaskedFactor, MembershipMaskedLabel, MembershipMaskedPredictor): a cell is kept when is_member_at is true for its bar and symbol. A panel without bars is returned as it is.

Parameters:
panelxr.Dataset

A panel on (timestamp, symbol).

ownerstr, optional

Who asks, named in the error messages; defaults to this class.

Returns:
xr.Dataset

panel, NaN where the symbol is not a member on the bar’s date.

Raises:
ValueError

If a bar’s date lies outside the membership panel, or no symbol of panel is on the membership store’s symbol axis (an integer permaticker against a text one), which would mask every cell.

Examples

With membership the DemoPanel of is_member_at’s example and panel a panel of ones on AAA and BBB over its three bars:

>>> membership.mask(panel)["x"].to_pandas()
symbol      AAA  BBB
timestamp
2024-01-02  1.0  1.0
2024-01-03  1.0  NaN
2024-01-04  1.0  NaN