{"record":{"id":"f1893680673170bf","repo":"microsoft/qlib","slug":"please-implement-the-empty-method","errorCode":null,"errorMessage":"Please implement the `empty` method","messagePattern":"Please implement the `empty` method","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/high_performance_ds.py","lineNumber":278,"sourceCode":"    def sum(self) -> float:\n        raise NotImplementedError(f\"Please implement the `sum` method\")\n\n    def mean(self) -> float:\n        raise NotImplementedError(f\"Please implement the `mean` method\")\n\n    def count(self) -> int:\n        \"\"\"Return the count of the single metric, NaN is not included.\"\"\"\n\n        raise NotImplementedError(f\"Please implement the `count` method\")\n\n    def abs(self) -> BaseSingleMetric:\n        raise NotImplementedError(f\"Please implement the `abs` method\")\n\n    @property\n    def empty(self) -> bool:\n        \"\"\"If metric is empty, return True.\"\"\"\n\n        raise NotImplementedError(f\"Please implement the `empty` method\")\n\n    def add(self, other: BaseSingleMetric, fill_value: float = None) -> BaseSingleMetric:\n        \"\"\"Replace np.nan with fill_value in two metrics and add them.\"\"\"\n\n        raise NotImplementedError(f\"Please implement the `add` method\")\n\n    def replace(self, replace_dict: dict) -> BaseSingleMetric:\n        \"\"\"Replace the value of metric according to replace_dict.\"\"\"\n\n        raise NotImplementedError(f\"Please implement the `replace` method\")\n\n    def apply(self, func: Callable) -> BaseSingleMetric:\n        \"\"\"Replace the value of metric with func (metric).\n        Currently, the func is only qlib/backtest/order/Order.parse_dir.\n        \"\"\"\n\n        raise NotImplementedError(f\"Please implement the 'apply' method\")\n","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/high_performance_ds.py#L260-L296","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Use SingleMetric, where empty checks the underlying storage","Implement @property def empty(self) in your subclass (e.g. return self.storage.empty)","Do not replace it with len(m) == 0 — implement len() too, since both are part of the protocol"],"exampleFix":"# before\nm = BaseSingleMetric(s)\nif m.empty: ...\n# after\nfrom qlib.backtest.high_performance_ds import SingleMetric\nm = SingleMetric(s)\nif m.empty: ...","handlingStrategy":"type-guard","validationCode":"from qlib.backtest.high_performance_ds import BaseSingleMetric\nassert type(m).empty.fget is not BaseSingleMetric.empty.fget, \"object does not implement empty\"","typeGuard":"def supports_empty(m) -> bool:\n    from qlib.backtest.high_performance_ds import BaseSingleMetric\n    fget = getattr(type(m).__dict__.get('empty'), 'fget', None)\n    return fget is not None and fget is not BaseSingleMetric.empty.fget","tryCatchPattern":null,"preventionTips":["Use SingleMetric so .empty is a real property","When overriding in subclasses, keep the @property decorator so `.empty` stays attribute access","Guard aggregation code with .empty checks after confirming a concrete type"],"tags":["python","qlib","abstract-method","property","metrics"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}