microsoft/qlib · error · NotImplementedError

This type of input is not supported

Error message

This type of input is not supported

What it means

SimulatorExecutor orders the decision's orders according to trade_type, which must equal TT_SERIAL ('serial', execute in order) or TT_PARAL ('parallel', buys sorted first to surface money conflicts). Any other value reaches the else branch and raises NotImplementedError on the first _collect_data step.

Source

Thrown at qlib/backtest/executor.py:587

        Returns
        -------
        List[Order]:
            get a list orders according to `self.trade_type`
        """
        orders = _retrieve_orders_from_decision(trade_decision)

        if self.trade_type == self.TT_SERIAL:
            # Orders will be traded in a parallel way
            order_it = orders
        elif self.trade_type == self.TT_PARAL:
            # NOTE: !!!!!!!
            # Assumption: there will not be orders in different trading direction in a single step of a strategy !!!!
            # The parallel trading failure will be caused only by the conflicts of money
            # Therefore, make the buying go first will make sure the conflicts happen.
            # It equals to parallel trading after sorting the order by direction
            order_it = sorted(orders, key=lambda order: -order.direction)
        else:
            raise NotImplementedError(f"This type of input is not supported")
        return order_it

    def _collect_data(self, trade_decision: BaseTradeDecision, level: int = 0) -> Tuple[List[object], dict]:
        trade_start_time, _ = self.trade_calendar.get_step_time()
        execute_result: list = []

        for order in self._get_order_iterator(trade_decision):
            # Each time we move into a new date, clear `self.dealt_order_amount` since it only maintains intraday
            # information.
            now_deal_day = self.trade_calendar.get_step_time()[0].floor(freq="D")
            if self.deal_day is None or now_deal_day > self.deal_day:
                self.dealt_order_amount = defaultdict(float)
                self.deal_day = now_deal_day

            # execute the order.
            # NOTE: The trade_account will be changed in this function
            trade_val, trade_cost, trade_price = self.trade_exchange.deal_order(
                order,

View on GitHub (pinned to 79633dd950)

Solutions

  1. Set trade_type='serial' or trade_type='parallel' exactly (lowercase)
  2. Use the class constants: SimulatorExecutor.TT_SERIAL / SimulatorExecutor.TT_PARAL
  3. If loading from config, validate the value against {'serial','parallel'} before constructing the executor

Example fix

# before
ex = SimulatorExecutor(..., trade_type='sequential')
# after
ex = SimulatorExecutor(..., trade_type=SimulatorExecutor.TT_SERIAL)  # 'serial'
Defensive patterns

Strategy: validation

Validate before calling

trade_type = str(trade_type).lower()
assert trade_type in (SimulatorExecutor.TT_SERIAL, SimulatorExecutor.TT_PARAL)
executor = SimulatorExecutor(..., trade_type=trade_type)

Type guard

def is_valid_trade_type(t) -> bool:
    return t in (SimulatorExecutor.TT_SERIAL, SimulatorExecutor.TT_PARAL)

Prevention

When it happens

Trigger: SimulatorExecutor(..., trade_type='sequential'), trade_type='Serial' (case-sensitive), or trade_type=None/1 from a config default that was never filled in.

Common situations: Typing free-form strings into backtest config yaml; case mismatches; older tutorials using different trade_type spellings.

Related errors


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