microsoft/qlib · error · NotImplementedError

Please implement the `empty` method

Error message

Please implement the `empty` method

What it means

BaseSingleMetric.empty is an abstract property that should return True when the metric holds no data. The base class property body raises NotImplementedError; SingleMetric implements it. Accessing .empty on a bare BaseSingleMetric — including in truthiness guards like `if m.empty:` — raises this error rather than returning a bool.

Source

Thrown at qlib/backtest/high_performance_ds.py:278

    def sum(self) -> float:
        raise NotImplementedError(f"Please implement the `sum` method")

    def mean(self) -> float:
        raise NotImplementedError(f"Please implement the `mean` method")

    def count(self) -> int:
        """Return the count of the single metric, NaN is not included."""

        raise NotImplementedError(f"Please implement the `count` method")

    def abs(self) -> BaseSingleMetric:
        raise NotImplementedError(f"Please implement the `abs` method")

    @property
    def empty(self) -> bool:
        """If metric is empty, return True."""

        raise NotImplementedError(f"Please implement the `empty` method")

    def add(self, other: BaseSingleMetric, fill_value: float = None) -> BaseSingleMetric:
        """Replace np.nan with fill_value in two metrics and add them."""

        raise NotImplementedError(f"Please implement the `add` method")

    def replace(self, replace_dict: dict) -> BaseSingleMetric:
        """Replace the value of metric according to replace_dict."""

        raise NotImplementedError(f"Please implement the `replace` method")

    def apply(self, func: Callable) -> BaseSingleMetric:
        """Replace the value of metric with func (metric).
        Currently, the func is only qlib/backtest/order/Order.parse_dir.
        """

        raise NotImplementedError(f"Please implement the 'apply' method")

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use SingleMetric, where empty checks the underlying storage
  2. Implement @property def empty(self) in your subclass (e.g. return self.storage.empty)
  3. Do not replace it with len(m) == 0 — implement len() too, since both are part of the protocol

Example fix

# before
m = BaseSingleMetric(s)
if m.empty: ...
# after
from qlib.backtest.high_performance_ds import SingleMetric
m = SingleMetric(s)
if m.empty: ...
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.backtest.high_performance_ds import BaseSingleMetric
assert type(m).empty.fget is not BaseSingleMetric.empty.fget, "object does not implement empty"

Type guard

def supports_empty(m) -> bool:
    from qlib.backtest.high_performance_ds import BaseSingleMetric
    fget = getattr(type(m).__dict__.get('empty'), 'fget', None)
    return fget is not None and fget is not BaseSingleMetric.empty.fget

Prevention

When it happens

Trigger: m.empty on a raw BaseSingleMetric; guard clauses before aggregations (if metric.empty: return 0); subclasses that define other methods but not the empty property (note: it must be decorated @property to keep attribute access semantics).

Common situations: Defensive checks added by user code around aggregation calls; report templates handling empty trading days; custom subclasses missing the property decorator, making .empty return a bound method instead.

Related errors


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