{"record":{"id":"c62b7ac0bb64be33","repo":"microsoft/qlib","slug":"there-is-no-trade-range-in-this-case","errorCode":null,"errorMessage":"There is no trade_range in this case","messagePattern":"There is no trade_range in this case","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/decision.py","lineNumber":495,"sourceCode":"        -------\n        Tuple[int, int]:\n            the range limit in data calendar\n\n        Raises\n        ------\n        NotImplementedError:\n            If the following criteria meet\n            1) the decision can't provide a unified start and end\n            2) raise_error is True\n        \"\"\"\n        # potential performance issue\n        day_start = pd.Timestamp(self.start_time.date())\n        day_end = epsilon_change(day_start + pd.Timedelta(days=1))\n        freq = self.strategy.trade_exchange.freq\n        _, _, day_start_idx, day_end_idx = Cal.locate_index(day_start, day_end, freq=freq)\n        if self.trade_range is None:\n            if raise_error:\n                raise NotImplementedError(f\"There is no trade_range in this case\")\n            else:\n                return 0, day_end_idx - day_start_idx\n        else:\n            if rtype == \"full\":\n                val_start, val_end = self.trade_range.clip_time_range(day_start, day_end)\n            elif rtype == \"step\":\n                val_start, val_end = self.trade_range.clip_time_range(self.start_time, self.end_time)\n            else:\n                raise ValueError(f\"This type of input {rtype} is not supported\")\n            _, _, start_idx, end_index = Cal.locate_index(val_start, val_end, freq=freq)\n            return start_idx - day_start_idx, end_index - day_start_idx\n\n    def empty(self) -> bool:\n        for obj in self.get_decision():\n            if isinstance(obj, Order):\n                # Zero amount order will be treated as empty\n                if obj.amount > 1e-6:\n                    return False","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/decision.py#L477-L513","documentation":"This method (decision.py ~line 495, the rtype 'full'/'step' range calculator) computes day-relative index bounds for the decision. If trade_range is None and raise_error=True, it raises NotImplementedError to signal that no per-decision execution window exists; with raise_error=False it silently returns the full day range instead.","triggerScenarios":"decision.get_range_limit(...-style call with raise_error=True on a decision whose trade_range is None; typically invoked by order-level or nested-executor logic that needs the decision's time box strictly.","commonSituations":"Strategies that create orders with their own deal_time/trade_range but build the enclosing decision without one; upgraded qlib versions where executors pass raise_error=True when resolving order time ranges.","solutions":["Call with raise_error=False to fall back to the full-day trade calendar range","Attach a trade_range to the decision, e.g. BaseTradeDecision(..., trade_range=TradeRangeByTime('9:30', '14:30'))","Catch NotImplementedError and fall back to the order's own time range if you truly need per-order semantics"],"exampleFix":"// before\nstart_idx, end_idx = decision.get_range_limit(rtype='step', raise_error=True)\n// after\nstart_idx, end_idx = decision.get_range_limit(rtype='step', raise_error=False)","handlingStrategy":"fallback","validationCode":"if decision.trade_range is None:\n    idx_range = decision.get_range_limit(rtype='full', raise_error=False)\nelse:\n    idx_range = decision.get_range_limit(rtype='full', raise_error=True)","typeGuard":"def has_trade_range(decision) -> bool:\n    return decision.trade_range is not None","tryCatchPattern":"try:\n    idx = decision.get_range_limit(rtype='step', raise_error=True)\nexcept NotImplementedError:\n    idx = decision.get_range_limit(rtype='step', raise_error=False)","preventionTips":["Default to raise_error=False unless per-order time boxes are mandatory","Set trade_range on decisions whenever strategies emit time-boxed orders"],"tags":["qlib","backtest","trade-range","not-implemented"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}