{"record":{"id":"b4accdba31c2a388","repo":"microsoft/qlib","slug":"update-model-is-not-implemented","errorCode":null,"errorMessage":"_update_model is not implemented!","messagePattern":"_update_model is not implemented!","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/signal.py","lineNumber":85,"sourceCode":"\nclass ModelSignal(SignalWCache):\n    def __init__(self, model: BaseModel, dataset: Dataset) -> None:\n        self.model = model\n        self.dataset = dataset\n        pred_scores = self.model.predict(dataset)\n        if isinstance(pred_scores, pd.DataFrame):\n            pred_scores = pred_scores.iloc[:, 0]\n        super().__init__(pred_scores)\n\n    def _update_model(self) -> None:\n        \"\"\"\n        When using online data, update model in each bar as the following steps:\n            - update dataset with online data, the dataset should support online update\n            - make the latest prediction scores of the new bar\n            - update the pred score into the latest prediction\n        \"\"\"\n        # TODO: this method is not included in the framework and could be refactor later\n        raise NotImplementedError(\"_update_model is not implemented!\")\n\n\ndef create_signal_from(\n    obj: Union[Signal, Tuple[BaseModel, Dataset], List, Dict, Text, pd.Series, pd.DataFrame],\n) -> Signal:\n    \"\"\"\n    create signal from diverse information\n    This method will choose the right method to create a signal based on `obj`\n    Please refer to the code below.\n    \"\"\"\n    if isinstance(obj, Signal):\n        return obj\n    elif isinstance(obj, (tuple, list)):\n        return ModelSignal(*obj)\n    elif isinstance(obj, (dict, str)):\n        return init_instance_by_config(obj)\n    elif isinstance(obj, (pd.DataFrame, pd.Series)):\n        return SignalWCache(signal=obj)","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/signal.py#L67-L103","documentation":"ModelSignal (qlib/backtest/signal.py) is created from a (model, dataset) tuple and is supposed to lazily produce prediction scores. Updating the model with freshly arriving online data each bar (online/mobile backtest mode) is planned but not implemented — the docstring explicitly says the online update path is a TODO. Calling _update_model raises NotImplementedError by design.","triggerScenarios":"Running an online/incremental simulation where the executor loop calls signal update hooks each bar (e.g. nested execution with online data via signal.update_score/update paths), while the signal was built from a (model, dataset) tuple via create_signal_from.","commonSituations":"Users run qlib's online serving / mobile backtest examples that expect SignalWCache (precomputed scores) but pass a model+dataset tuple instead; or they upgrade to a qlib version where the online loop now invokes _update_model unconditionally.","solutions":["Use precomputed prediction scores: call model.predict(dataset) first and pass the resulting Series/DataFrame to create_signal_from, which yields SignalWCache instead of ModelSignal.","Save predictions to a file and create the signal from a dict config pointing at that file (SignalWCache from a pickle path).","If per-bar model updates are genuinely needed, subclass ModelSignal and implement _update_model yourself (update dataset with online data, re-predict, refresh scores).","Check whether your executor/strategy config sets an online-update flag you can disable."],"exampleFix":"# before\nsignal = create_signal_from((model, dataset))  # ModelSignal -> NotImplementedError on update\n# after\npred = model.predict(dataset)\nsignal = create_signal_from(pred)  # SignalWCache, safe in online loops","handlingStrategy":"validation","validationCode":"from qlib.backtest.signal import SignalWCache, ModelSignal\n# before starting an online/looped simulation, reject ModelSignal\nassert not isinstance(signal, ModelSignal) or not online_mode, 'ModelSignal cannot update online; precompute scores'","typeGuard":"from qlib.backtest.signal import SignalWCache\n\ndef is_precomputed_signal(s) -> bool:\n    return isinstance(s, SignalWCache)","tryCatchPattern":"try:\n    signal.update(...)  # online loop\nexcept NotImplementedError as e:\n    if '_update_model' in str(e):\n        raise RuntimeError('Precompute model.predict() and use SignalWCache for online simulation') from e\n    raise","preventionTips":["For online simulations, always create signals from precomputed pandas scores.","Run model.predict(dataset) once and cache results to disk before entering the execution loop."],"tags":["qlib","signal","online-sim","not-implemented"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}