microsoft/qlib · error · ValueError

Unknown instrument type {inst}

Error message

Unknown instrument type {inst}

What it means

`InstrumentStorage.get_inst_type` (used by `D.list_instruments`) classifies the `instruments` argument: a dict containing key 'market' is a stockpool CONF, any other dict is a DICT of {instrument: datetime-range}, and list/tuple/pd.Index/np.ndarray is a LIST. Anything else — notably a bare string like 'csi300' — is rejected with this ValueError.

Source

Thrown at qlib/data/data.py:304

        raise NotImplementedError("Subclass of InstrumentProvider must implement `list_instruments` method")

    def _uri(self, instruments, start_time=None, end_time=None, freq="day", as_list=False):
        return hash_args(instruments, start_time, end_time, freq, as_list)

    # instruments type
    LIST = "LIST"
    DICT = "DICT"
    CONF = "CONF"

    @classmethod
    def get_inst_type(cls, inst):
        if "market" in inst:
            return cls.CONF
        if isinstance(inst, dict):
            return cls.DICT
        if isinstance(inst, (list, tuple, pd.Index, np.ndarray)):
            return cls.LIST
        raise ValueError(f"Unknown instrument type {inst}")


class FeatureProvider(abc.ABC):
    """Feature provider class

    Provide feature data.
    """

    @abc.abstractmethod
    def feature(self, instrument, field, start_time, end_time, freq):
        """Get feature data.

        Parameters
        ----------
        instrument : str
            a certain instrument.
        field : str
            a certain field of feature.

View on GitHub (pinned to 79633dd950)

Solutions

  1. Wrap the market string: `D.list_instruments({'market': 'csi300'})` or use `D.instruments('csi300')` which builds the dict for you.
  2. For an explicit set of tickers, pass a list: `D.list_instruments(['SH600000', 'SZ000001'])`.

Example fix

# before
insts = D.list_instruments('csi300')

# after
insts = D.list_instruments({'market': 'csi300'})
# or
insts = D.list_instruments(D.instruments('csi300'))
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd, numpy as np

def valid_instruments(inst) -> bool:
    return (
        isinstance(inst, dict)
        or isinstance(inst, (list, tuple, pd.Index, np.ndarray))
    )

Type guard

import pandas as pd, numpy as np
from typing import Union

def is_supported_instruments(inst) -> bool:
    if isinstance(inst, dict):
        return True  # market config or {inst: range} dict
    return isinstance(inst, (list, tuple, pd.Index, np.ndarray))

Try / catch

try:
    insts = D.list_instruments(instruments)
except ValueError as e:
    if 'Unknown instrument type' in str(e):
        instruments = {'market': str(instruments)}
        insts = D.list_instruments(instruments)
    else:
        raise

Prevention

When it happens

Trigger: Calling `D.list_instruments('csi300')` or passing an int/None/set as `instruments`. Strings are not accepted directly; they must be wrapped in a market config dict.

Common situations: Very common with new qlib users: `D.list_instruments(D.instruments('csi300'))` works but `D.list_instruments('csi300')` raises. Also triggered by passing `market='all'` string directly from a config file.

Related errors


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