microsoft/qlib · error · ValueError

direction {direction} is not supported!

Error message

direction {direction} is not supported!

What it means

Exchange.check_stock_limit(stop_time...) queries the limit_buy/limit_sell quote fields based on the requested direction: None checks either side, Order.BUY checks limit_buy, Order.SELL checks limit_sell. Any other value for direction cannot select a field, so ValueError is raised. Order.BUY/Order.SELL are integers (1/-1), so arbitrary ints or strings fail.

Source

Thrown at qlib/backtest/exchange.py:376

        -------
        True: the trading of the stock is limited (maybe hit the highest/lowest price), hence the stock is not tradable
        False: the trading of the stock is not limited, hence the stock may be tradable
        """
        # NOTE:
        # **all** is used when checking limitation.
        # For example, the stock trading is limited in a day if every minute is limited in a day if every minute is limited.
        if direction is None:
            # The trading limitation is related to the trading direction
            # if the direction is not provided, then any limitation from buy or sell will result in trading limitation
            buy_limit = self.quote.get_data(stock_id, start_time, end_time, field="limit_buy", method="all")
            sell_limit = self.quote.get_data(stock_id, start_time, end_time, field="limit_sell", method="all")
            return bool(buy_limit or sell_limit)
        elif direction == Order.BUY:
            return cast(bool, self.quote.get_data(stock_id, start_time, end_time, field="limit_buy", method="all"))
        elif direction == Order.SELL:
            return cast(bool, self.quote.get_data(stock_id, start_time, end_time, field="limit_sell", method="all"))
        else:
            raise ValueError(f"direction {direction} is not supported!")

    def check_stock_suspended(
        self,
        stock_id: str,
        start_time: pd.Timestamp,
        end_time: pd.Timestamp,
    ) -> bool:
        """if stock is suspended(hence not tradable), True will be returned"""
        # is suspended
        if stock_id in self.quote.get_all_stock():
            # suspended stocks are represented by None $close stock
            # The $close may contain NaN,
            close = self.quote.get_data(stock_id, start_time, end_time, "$close")
            if close is None:
                # if no close record exists
                return True
            elif isinstance(close, IndexData):
                # **any** non-NaN $close represents trading opportunity may exist

View on GitHub (pinned to 79633dd950)

Solutions

  1. Pass direction=None (either-side check), Order.BUY (=1), or Order.SELL (=-1)
  2. Import Order/OrderDir from the same qlib version as the Exchange: from qlib.backtest.exchange import Exchange, OrderDir
  3. If direction comes from an order object, pass order.direction directly rather than re-encoding it

Example fix

# before
tradable = exch.is_stock_tradable(sid, t0, t1, direction='buy')
# after
from qlib.backtest.exchange import Order
tradable = exch.is_stock_tradable(sid, t0, t1, direction=Order.BUY)
Defensive patterns

Strategy: validation

Validate before calling

from qlib.backtest.order import Order
assert direction is None or direction in (Order.BUY, Order.SELL)
exch.is_stock_tradable(sid, t0, t1, direction=direction)

Type guard

def is_valid_direction(d) -> bool:
    from qlib.backtest.order import Order
    return d is None or d in (Order.BUY, Order.SELL)

Prevention

When it happens

Trigger: is_stock_tradable(stock_id, start, end, direction=0), direction='buy', or passing an OrderDir-like enum from a different/older qlib version with different values.

Common situations: Custom strategies passing direction as a string; mixing qlib versions where Order.BUY/SELL constants or OrderDir enum members were imported from mismatched modules.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/c748c0f9ac896cba. Report an issue: GitHub.