{"record":{"id":"7195d8ec8f7b6129","repo":"microsoft/qlib","slug":"limit-0-is-not-supported","errorCode":null,"errorMessage":"{limit[0]} is not supported","messagePattern":"(.+?) is not supported","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/exchange.py","lineNumber":825,"sourceCode":"                limit_value = self.quote.get_data(\n                    order.stock_id,\n                    order.start_time,\n                    order.end_time,\n                    field=limit[1],\n                    method=\"sum\",\n                )\n                vol_limit_num.append(cast(float, limit_value))\n            elif limit[0] == \"cum\":\n                limit_value = self.quote.get_data(\n                    order.stock_id,\n                    order.start_time,\n                    order.end_time,\n                    field=limit[1],\n                    method=\"ts_data_last\",\n                )\n                vol_limit_num.append(limit_value - dealt_order_amount[order.stock_id])\n            else:\n                raise ValueError(f\"{limit[0]} is not supported\")\n        vol_limit_min = min(vol_limit_num)\n        orig_deal_amount = order.deal_amount\n        order.deal_amount = max(min(vol_limit_min, orig_deal_amount), 0)\n        if vol_limit_min < orig_deal_amount:\n            self.logger.debug(f\"Order clipped due to volume limitation: {order}, {list(zip(vol_limit_num, vol_limit))}\")\n\n        return None\n\n    def _get_buy_amount_by_cash_limit(self, trade_price: float, cash: float, cost_ratio: float) -> float:\n        \"\"\"return the real order amount after cash limit for buying.\n        Parameters\n        ----------\n        trade_price : float\n        cash : float\n        cost_ratio : float\n\n        Return\n        ----------","sourceCodeStart":807,"sourceCodeEnd":843,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/exchange.py#L807-L843","documentation":"Volume-limit rules (volume_threshold on Exchange) are tuples whose first element selects the rule: 'current' limits by a quote field summed over the current bar range, 'cum' limits by cumulative volume minus already-dealt amount. Any other first element raises ValueError. Each rule's remaining elements name the quote field (and the dealt-amount bookkeeping uses dealt_order_amount).","triggerScenarios":"volume_threshold=(('total', '$volume', 0.2),) or (('avg', ...),); also misspelling 'current'/'cum' or passing bare strings/floats (an assert on tuple also guards shape).","commonSituations":"Writing custom volume-limit expressions without following the nested-tuple schema; older examples using a different rule vocabulary.","solutions":["Use rule prefix 'current': (('current', '$volume', 0.2),) style tuples where limit[1] is a $-field summed over the order window","Use 'cum' for cumulative-style caps based on a running field minus dealt amount","Double-check spelling and that volume_threshold is a tuple of tuples"],"exampleFix":"# before\nexch = Exchange(volume_threshold=(('total', '$volume', 0.2),))\n# after\nexch = Exchange(volume_threshold=(('current', '$volume', 0.2),))","handlingStrategy":"validation","validationCode":"for limit in volume_threshold or ():\n    assert isinstance(limit, tuple) and limit[0] in ('current', 'cum'), \\\n        f\"bad volume limit rule: {limit}\"\nexch = Exchange(volume_threshold=volume_threshold)","typeGuard":"def vol_rules_valid(rules) -> bool:\n    return all(isinstance(r, tuple) and r[0] in ('current', 'cum') for r in (rules or ()))","tryCatchPattern":null,"preventionTips":["Only rule prefixes 'current' and 'cum' are supported","Keep volume_threshold as a tuple of tuples with $-prefixed field names"],"tags":["qlib","exchange","volume-threshold","value-error"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}