microsoft/qlib · error · NotImplementedError

Please implement the `prepare_tasks` method.

Error message

Please implement the `prepare_tasks` method.

What it means

OnlineStrategy.prepare_tasks is an abstract hook: the base class intentionally raises NotImplementedError telling you to override it. It fires whenever the online workflow calls strategy.prepare_tasks(cur_time) on a subclass that did not provide the method — i.e. you instantiated a custom OnlineStrategy (or a subclass) that is still incomplete.

Source

Thrown at qlib/workflow/online/strategy.py:44

        Init OnlineStrategy.
        This module **MUST** use `Trainer <../reference/api.html#qlib.model.trainer.Trainer>`_ to finishing model training.

        Args:
            name_id (str): a unique name or id.
            trainer (qlib.model.trainer.Trainer, optional): a instance of Trainer. Defaults to None.
        """
        self.name_id = name_id
        self.logger = get_module_logger(self.__class__.__name__)
        self.tool = OnlineTool()

    def prepare_tasks(self, cur_time, **kwargs) -> List[dict]:
        """
        After the end of a routine, check whether we need to prepare and train some new tasks based on cur_time (None for latest)..
        Return the new tasks waiting for training.

        You can find the last online models by OnlineTool.online_models.
        """
        raise NotImplementedError(f"Please implement the `prepare_tasks` method.")

    def prepare_online_models(self, trained_models, cur_time=None) -> List[object]:
        """
        Select some models from trained models and set them to online models.
        This is a typical implementation to online all trained models, you can override it to implement the complex method.
        You can find the last online models by OnlineTool.online_models if you still need them.

        NOTE: Reset all online models to trained models. If there are no trained models, then do nothing.

        **NOTE**:
            Current implementation is very naive. Here is a more complex situation which is more closer to the
            practical scenarios.
            1. Train new models at the day before `test_start` (at time stamp `T`)
            2. Switch models at the `test_start` (at time timestamp `T + 1` typically)

        Args:
            models (list): a list of models.
            cur_time (pd.Dataframe): current time from OnlineManger. None for the latest.

View on GitHub (pinned to 79633dd950)

Solutions

  1. Implement prepare_tasks(cur_time, **kwargs) -> List[dict] in your subclass that decides whether new tasks should be trained based on cur_time (None = latest) and returns them
  2. If you do not need custom logic, use the provided RollingStrategy which implements prepare_tasks via its rolling_gen
  3. Verify the override signature and spelling match exactly (prepare_tasks, plural) so Python actually overrides the base method

Example fix

# before
class MyStrategy(OnlineStrategy):
    def __init__(self):
        super().__init__('my_strat')
    # prepare_tasks missing -> NotImplementedError

# after
class MyStrategy(OnlineStrategy):
    def __init__(self):
        super().__init__('my_strat')
    def prepare_tasks(self, cur_time, **kwargs) -> List[dict]:
        last_models = self.tool.online_models()
        # decide + return new task dicts
        return [self.task_template] if len(last_models) == 0 else []
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.workflow.online.strategy import OnlineStrategy

def assert_strategy_complete(strategy):
    if strategy.prepare_tasks.__func__ is OnlineStrategy.prepare_tasks:
        raise TypeError(f'{type(strategy).__name__} must implement prepare_tasks')

Type guard

from qlib.workflow.online.strategy import OnlineStrategy

def has_prepare_tasks(strategy) -> bool:
    return strategy.prepare_tasks.__func__ is not OnlineStrategy.prepare_tasks

Try / catch

try:
    strategy.prepare_tasks(cur_time)
except NotImplementedError as e:
    raise TypeError(f'{type(strategy).__name__} is abstract: {e}') from e

Prevention

When it happens

Trigger: Defining a class inheriting OnlineStrategy without overriding prepare_tasks, then running OnlineManager.routine or calling prepare_tasks directly; instantiating OnlineStrategy itself (it is effectively abstract); a typo in the override name (e.g. prepare_task) so the base method runs.

Common situations: Writing a custom online strategy for the first time and forgetting one of the required hooks; copying an example strategy but renaming the method incorrectly; upgrading qlib and missing that a new hook method is required.

Related errors


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