{"record":{"id":"4c7d0229bd764aff","repo":"microsoft/qlib","slug":"factor-and-stock-id-start-time-end-time","errorCode":null,"errorMessage":"`factor` and (`stock_id`, `start_time`, `end_time`) can't both be None","messagePattern":"`factor` and \\(`stock_id`, `start_time`, `end_time`\\) can't both be None","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/exchange.py","lineNumber":724,"sourceCode":"                        direction=direction,\n                    )\n                    * amount_dict[stock_id]\n                )\n        return value\n\n    def _get_factor_or_raise_error(\n        self,\n        factor: float | None = None,\n        stock_id: str | None = None,\n        start_time: pd.Timestamp = None,\n        end_time: pd.Timestamp = None,\n    ) -> float:\n        \"\"\"Please refer to the docs of get_amount_of_trade_unit\"\"\"\n        if factor is None:\n            if stock_id is not None and start_time is not None and end_time is not None:\n                factor = self.get_factor(stock_id=stock_id, start_time=start_time, end_time=end_time)\n            else:\n                raise ValueError(f\"`factor` and (`stock_id`, `start_time`, `end_time`) can't both be None\")\n        assert factor is not None\n        return factor\n\n    def get_amount_of_trade_unit(\n        self,\n        factor: float | None = None,\n        stock_id: str | None = None,\n        start_time: pd.Timestamp = None,\n        end_time: pd.Timestamp = None,\n    ) -> Optional[float]:\n        \"\"\"\n        get the trade unit of amount based on **factor**\n        the factor can be given directly or calculated in given time range and stock id.\n        `factor` has higher priority than `stock_id`, `start_time` and `end_time`\n        Parameters\n        ----------\n        factor : float\n            the adjusted factor","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/exchange.py#L706-L742","documentation":"Exchange._get_factor_or_raise_error resolves the adjustment factor either directly from the `factor` argument or by looking it up via (stock_id, start_time, end_time). If factor is None and any of the three lookup keys is missing, there is no way to obtain a factor, so ValueError is raised. It backs get_amount_of_trade_unit and round_amount_by_trade_unit when rounding order amounts to board lots.","triggerScenarios":"Calling get_amount_of_trade_unit / round_amount_by_trade_unit with factor=None and only a partial key set (e.g. stock_id without start_time/end_time).","commonSituations":"Custom strategies calling the trade-unit API with just a stock id; optional-argument chains where timestamps default to None and are forwarded silently.","solutions":["Pass a complete lookup triple: exch.get_amount_of_trade_unit(stock_id=sid, start_time=t0, end_time=t1)","Or supply the factor directly: exch.get_amount_of_trade_unit(factor=1.0) (1.0 means unadjusted prices)","When calling from order-processing code, forward order.stock_id/order.start_time/order.end_time together"],"exampleFix":"# before\nunit_amt = exch.get_amount_of_trade_unit(stock_id=sid, start_time=t0)  # end_time missing\n# after\nunit_amt = exch.get_amount_of_trade_unit(stock_id=sid, start_time=t0, end_time=t1)","handlingStrategy":"validation","validationCode":"if factor is None:\n    assert stock_id is not None and start_time is not None and end_time is not None, \\\n        'provide factor or all of (stock_id, start_time, end_time)'\nunit = exch.get_amount_of_trade_unit(factor=factor, stock_id=stock_id, start_time=start_time, end_time=end_time)","typeGuard":"def factor_args_complete(factor, stock_id, start_time, end_time) -> bool:\n    return factor is not None or all(x is not None for x in (stock_id, start_time, end_time))","tryCatchPattern":null,"preventionTips":["Forward order.stock_id/start_time/end_time as a complete triple","Pass factor=1.0 explicitly when working with unadjusted prices"],"tags":["qlib","exchange","factor","required-arguments"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}