microsoft/qlib · error · ValueError
tradable_weight is {}, can not greater than 1.
Error message
tradable_weight is {}, can not greater than 1. What it means
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.
Source
Thrown at qlib/backtest/exchange.py:567
start_time : the start time point of the step
end_time : the end time point of the step
direction : the direction of the deal price for estimating the amount
# NOTE: this function is used for calculating target position. So the default direction is buy
"""
# calculate the total weight of tradable value
tradable_weight = 0.0
for stock_id, wp in weight_position.items():
if self.is_stock_tradable(stock_id=stock_id, start_time=start_time, end_time=end_time):
# weight_position must be greater than 0 and less than 1
if wp < 0 or wp > 1:
raise ValueError(
"weight_position is {}, " "weight_position is not in the range of (0, 1).".format(wp),
)
tradable_weight += wp
if tradable_weight - 1.0 >= 1e-5:
raise ValueError("tradable_weight is {}, can not greater than 1.".format(tradable_weight))
amount_dict = {}
for stock_id in weight_position:
if weight_position[stock_id] > 0.0 and self.is_stock_tradable(
stock_id=stock_id,
start_time=start_time,
end_time=end_time,
):
amount_dict[stock_id] = (
cash
* weight_position[stock_id]
/ tradable_weight
// self.get_deal_price(
stock_id=stock_id,
start_time=start_time,
end_time=end_time,
direction=direction,
)View on GitHub (pinned to 79633dd950)
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)
Example fix
# before
amounts = exch.get_amount_from_weight({'A': 0.7, 'B': 0.6}, ...)
# after
raw = {'A': 0.7, 'B': 0.6}
total = sum(raw.values())
weights = {k: v / total for k, v in raw.items()}
amounts = exch.get_amount_from_weight(weights, ...) Defensive patterns
Strategy: validation
Validate before calling
total = sum(weight_position.values())
if total > 1.0:
weight_position = {k: v / total for k, v in weight_position.items()}
assert sum(weight_position.values()) <= 1.0 + 1e-5 Type guard
def weights_normalized(w: dict) -> bool:
return sum(w.values()) <= 1.0 + 1e-5 Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- weight_position is {}, weight_position is not in the range o
- Get Unexpected arguments {kwargs}
- This type of input is not supported
- $close is necessray in extra_quote
- This type of `limit_threshold` is not supported
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/cdcee389e8ce18b5.
Report an issue: GitHub.