{"record":{"id":"cdcee389e8ce18b5","repo":"microsoft/qlib","slug":"tradable-weight-is-can-not-greater-than-1","errorCode":null,"errorMessage":"tradable_weight is {}, can not greater than 1.","messagePattern":"tradable_weight is (.+?), can not greater than 1\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/exchange.py","lineNumber":567,"sourceCode":"        start_time : the start time point of the step\n        end_time : the end time point of the step\n        direction : the direction of the deal price for estimating the amount\n                    # NOTE: this function is used for calculating target position. So the default direction is buy\n        \"\"\"\n\n        # calculate the total weight of tradable value\n        tradable_weight = 0.0\n        for stock_id, wp in weight_position.items():\n            if self.is_stock_tradable(stock_id=stock_id, start_time=start_time, end_time=end_time):\n                # weight_position must be greater than 0 and less than 1\n                if wp < 0 or wp > 1:\n                    raise ValueError(\n                        \"weight_position is {}, \" \"weight_position is not in the range of (0, 1).\".format(wp),\n                    )\n                tradable_weight += wp\n\n        if tradable_weight - 1.0 >= 1e-5:\n            raise ValueError(\"tradable_weight is {}, can not greater than 1.\".format(tradable_weight))\n\n        amount_dict = {}\n        for stock_id in weight_position:\n            if weight_position[stock_id] > 0.0 and self.is_stock_tradable(\n                stock_id=stock_id,\n                start_time=start_time,\n                end_time=end_time,\n            ):\n                amount_dict[stock_id] = (\n                    cash\n                    * weight_position[stock_id]\n                    / tradable_weight\n                    // self.get_deal_price(\n                        stock_id=stock_id,\n                        start_time=start_time,\n                        end_time=end_time,\n                        direction=direction,\n                    )","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/exchange.py#L549-L585","documentation":"After summing the weights of tradable stocks, the method rejects weight books whose tradable total exceeds 1 (tolerance 1e-5) with ValueError. Because amounts are computed as cash * weight / tradable_weight, a total above 1 would over-allocate the cash; weights of non-tradable stocks are excluded from the sum, so the error means the tradable subset alone is over-allocated.","triggerScenarios":"weight_position summing to more than 1 (e.g. 0.6 + 0.6), or all-in allocations where a data error makes extra stocks count as tradable.","commonSituations":"Model outputs not normalized (raw softmax with temperature, unnormalized scores); hand-built weight dicts; currency/rounding issues where 100 tiny weights sum to 1.00001 (below the 1e-5 tolerance usually, but marginal cases slip).","solutions":["Normalize weights to sum <= 1: total = sum(w.values()); weights = {k: v / total for k, v in weights.items()}","Scale down: weights = {k: v * 0.99 / total for k, v in weights.items()} if you want a cash buffer","Verify which stocks count as tradable if the sum looks fine but still fails (suspended/limit-hit stocks change the tradable subset only by exclusion, so recheck the raw sum)"],"exampleFix":"# before\namounts = exch.get_amount_from_weight({'A': 0.7, 'B': 0.6}, ...)\n# after\nraw = {'A': 0.7, 'B': 0.6}\ntotal = sum(raw.values())\nweights = {k: v / total for k, v in raw.items()}\namounts = exch.get_amount_from_weight(weights, ...)","handlingStrategy":"validation","validationCode":"total = sum(weight_position.values())\nif total > 1.0:\n    weight_position = {k: v / total for k, v in weight_position.items()}\nassert sum(weight_position.values()) <= 1.0 + 1e-5","typeGuard":"def weights_normalized(w: dict) -> bool:\n    return sum(w.values()) <= 1.0 + 1e-5","tryCatchPattern":null,"preventionTips":["Normalize model outputs before using them as target weights","Keep a cash buffer (scale weights by e.g. 0.99/total) to dodge float edge cases"],"tags":["qlib","exchange","weights","normalization"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}