microsoft/qlib · error · NotImplementedError

Subclass of SeriesDFilter must reimplement `getFilterSeries`

Error message

Subclass of SeriesDFilter must reimplement `getFilterSeries` method

What it means

Raised by SeriesDFilter.getFilterSeries (qlib/data/filter.py), the abstract template method of the series-based instrument filter family. The base class intentionally raises NotImplementedError; every concrete subclass (e.g. SeriesTrendFilter) must override getFilterSeries to return the {pd.Timestamp => bool} series used to drop instruments. Hitting it means a subclass was used without implementing the required method.

Source

Thrown at qlib/data/filter.py:214

        """Get filter series based on the rules assigned during the initialization and the input time range.

        Parameters
        ----------
        instruments : dict
            the dict of instruments to be filtered.
        fstart : pd.Timestamp
            start time of filter.
        fend : pd.Timestamp
            end time of filter.

        .. note:: fstart/fend indicates the intersection of instruments start/end time and filter start/end time.

        Returns
        ----------
        pd.Dataframe
            a series of {pd.Timestamp => bool}.
        """
        raise NotImplementedError("Subclass of SeriesDFilter must reimplement `getFilterSeries` method")

    def filter_main(self, instruments, start_time=None, end_time=None):
        """Implement this method to filter the instruments.

        Parameters
        ----------
        instruments: dict
            input instruments to be filtered.
        start_time: str
            start of the time range.
        end_time: str
            end of the time range.

        Returns
        ----------
        dict
            filtered instruments, same structure as input instruments.
        """

View on GitHub (pinned to 79633dd950)

Solutions

  1. Implement getFilterSeries(self, instruments, fstart, fend) in your subclass, returning a pd.Series of booleans indexed by pd.Timestamp.
  2. Alternatively derive from a concrete filter such as SeriesTrendFilter and override only what changes.
  3. Do not instantiate the abstract SeriesDFilter itself; pick or implement a concrete subclass.

Example fix

# before
class MyFilter(SeriesDFilter):
    def __init__(self, ...):
        ...
    # getFilterSeries missing

# after
class MyFilter(SeriesDFilter):
    def __init__(self, ...):
        ...
    def getFilterSeries(self, instruments, fstart, fend):
        # build and return pd.Series({timestamp: bool, ...})
        return self._compute_series(instruments, fstart, fend)
Defensive patterns

Strategy: validation

Validate before calling

import inspect
if not (
    hasattr(cls, "getFilterSeries") and cls.getFilterSeries is not SeriesDFilter.getFilterSeries
):
    raise TypeError(f"{cls.__name__} must override getFilterSeries")

Type guard

def implements_get_filter_series(cls) -> bool:
    return getattr(cls, "getFilterSeries", None) is not SeriesDFilter.getFilterSeries

Prevention

When it happens

Trigger: Instantiating SeriesDFilter directly, or subclassing it (class MyFilter(SeriesDFilter)) without overriding getFilterSeries, then calling filter_main — which internally calls getFilterSeries.

Common situations: Writing custom instrument filters for qlib and forgetting the override; renaming the method (e.g. get_filter_series) so the override no longer matches; copy-pasting a filter class and deleting the 'boilerplate' method.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/bde168984db0a5ba. Report an issue: GitHub.