microsoft/qlib · error · ValueError
only have {} {}, require {}
Error message
only have {} {}, require {} What it means
Position._sell_stock raises ValueError('only have {held} {stock}, require {asked}') when subtracting the sold amount drives the holding below -1e-5, i.e. the sell order amount exceeds what the position holds beyond floating-point tolerance. The message reconstructs the pre-trade holding (final + trade_amount) for debugging.
Source
Thrown at qlib/backtest/position.py:368
self.position["cash"] -= trade_val + cost
def _sell_stock(self, stock_id: str, trade_val: float, cost: float, trade_price: float) -> None:
trade_amount = trade_val / trade_price
if stock_id not in self.position:
raise KeyError("{} not in current position".format(stock_id))
else:
if np.isclose(self.position[stock_id]["amount"], trade_amount):
# Selling all the stocks
# we use np.isclose instead of abs(<the final amount>) <= 1e-5 because `np.isclose` consider both
# relative amount and absolute amount
# Using abs(<the final amount>) <= 1e-5 will result in error when the amount is large
self._del_stock(stock_id)
else:
# decrease the amount of stock
self.position[stock_id]["amount"] -= trade_amount
# check if to delete
if self.position[stock_id]["amount"] < -1e-5:
raise ValueError(
"only have {} {}, require {}".format(
self.position[stock_id]["amount"] + trade_amount,
stock_id,
trade_amount,
),
)
new_cash = trade_val - cost
if self._settle_type == self.ST_CASH:
self.position["cash_delay"] += new_cash
elif self._settle_type == self.ST_NO:
self.position["cash"] += new_cash
else:
raise NotImplementedError(f"This type of input is not supported")
def _del_stock(self, stock_id: str) -> None:
del self.position[stock_id]
View on GitHub (pinned to 79633dd950)
Solutions
- Cap sell amounts at the current holding: amount = min(desired, position.get_stock_amount(stock))
- For full exits rely on np.isclose tolerance: pass the exact current amount, or trade the whole position value
- Align the price used to size the sell with the exchange's deal_price/limit thresholds
Example fix
# before sell_val = position.get_stock_amount(stock) * ref_price # ref_price != deal price # after amount = position.get_stock_amount(stock) sell_val = amount * deal_price # exact full-position sell, hits np.isclose branch
Defensive patterns
Strategy: validation
Validate before calling
held = position.get_stock_amount(order.stock_id)
if order.direction == Order.SELL and abs(order.amount_delta) > held + 1e-5:
order.amount = held # clip to holdings Try / catch
try:
position.update_order(order, trade_val, cost, trade_price)
except ValueError as e:
logger.warning("clipping oversell: %s", e) Prevention
- Size full-exit sells with the exact current amount
- Use the same price source for sizing and dealing
- Clip sell amounts to get_stock_amount before submitting
When it happens
Trigger: update_order with a SELL whose trade_amount (trade_val/trade_price) exceeds self.position[stock_id]['amount'] by more than np.isclose tolerance; typical when the strategy rounds lots (e.g. board lots of 100) upward or sells the full position computed with a different price than the deal price.
Common situations: Amount computed from close price but filled at a slippage-adjusted deal_price so trade_amount > held amount; strategies that sell 'all shares' using yesterday's amount after dividends/splits; numerical drift in repeated fractional sells.
Related errors
- {} not in current position
- do not support order direction {}
- Please implement the `settle_conf` method
- Please implement the `settle_commit` method
- {lack_stock} doesn't have close price in qlib in the latest
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/2bedb87814b11576.
Report an issue: GitHub.