microsoft/qlib · error · ValueError

not found executor

Error message

not found executor

What it means

Raised in OnlineOperator.check when type is not 'SIM' (the only branch that constructs an executor). Practically this means type='YC': it passes the earlier type-in-['SIM','YC'] gate but has no executor implementation on this code path, so the else branch raises. It is effectively dead-end functionality rather than a user input typo — the supported value is 'SIM' only.

Source

Thrown at qlib/contrib/online/operator.py:193

        Parameters
        ----------
        date : str (YYYY-MM-DD)
            Trade date, that the generated order list will be traded.
        path : str
            Path to save user account.
        type : str
            which executor was been used to execute the order list
            'SIM': SimulatorExecutor()
        """
        if type not in ["SIM", "YC"]:
            raise ValueError("type is invalid, {}".format(type))
        um, pred_date, trade_date = self.init(self.client, path, date)
        for user_id, user in um.users.items():
            dates, trade_exchange = prepare(um, trade_date, user_id)
            if type == "SIM":
                executor = SimulatorExecutor(trade_exchange=trade_exchange)
            else:
                raise ValueError("not found executor")
            # dates[0] is the last_trading_date
            if str(dates[0].date()) > str(pred_date.date()):
                raise ValueError(
                    "The account data is not newest! last trading date {}, today {}".format(
                        dates[0].date(), trade_date.date()
                    )
                )
            # load trade info and update account
            trade_info = executor.load_trade_info_from_executed_file(
                user_path=(pathlib.Path(path) / user_id), trade_date=trade_date
            )
            score_series = load_score_series((pathlib.Path(path) / user_id), trade_date)
            update_account(user.account, trade_info, trade_exchange, trade_date)

            portfolio_metrics = user.account.portfolio_metrics.generate_portfolio_metrics_dataframe()
            self.logger.info(portfolio_metrics)
            um.save_user_data(user_id)
            self.logger.info("Update account state {} for {}".format(trade_date, user_id))

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use type='SIM'.
  2. If you need a different executor, implement/patch the branch in operator.py to construct it, or call the executor API directly instead of through check().
  3. Track upstream qlib for a YC executor implementation before relying on that value.

Example fix

# before
op.check(date=d, path=p, type="YC")  # ValueError: not found executor

# after
op.check(date=d, path=p, type="SIM")
Defensive patterns

Strategy: type-guard

Validate before calling

if type != "SIM":
    raise ValueError("only the 'SIM' executor is implemented in OnlineOperator.check")
op.check(date=d, path=p, type=type)

Type guard

def is_implemented_executor(t) -> bool:
    return t == "SIM"

Prevention

When it happens

Trigger: Calling op.check(..., type='YC') — the second allowed value — which reaches the else branch and raises 'not found executor'.

Common situations: Users following the docstring ('SIM': SimulatorExecutor()) and trying the other whitelisted value; leftover half-implemented executor support in this contrib module.

Related errors


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