microsoft/qlib · error · ValueError

{freq} is not supported in NumpyQuote

Error message

{freq} is not supported in NumpyQuote

What it means

NumpyQuote.__init__ parses the freq string with Freq.parse(freq) and only accepts units in Freq.SUPPORT_CAL_LIST, which is currently just minute and day (qlib/utils/time.py:119). Any other calendar unit (week, month, quarter, year, or unknown tokens) raises this ValueError at construction time. NumpyQuote can therefore only serve intraday-minute or daily quote data.

Source

Thrown at qlib/backtest/high_performance_ds.py:149

        Parameters
        ----------
        quote_df : pd.DataFrame
            the init dataframe from qlib.
        self.data : Dict(stock_id, IndexData.DataFrame)
        """
        super().__init__(quote_df=quote_df, freq=freq)
        quote_dict = {}
        for stock_id, stock_val in quote_df.groupby(level="instrument", group_keys=False):
            quote_dict[stock_id] = idd.MultiData(stock_val.droplevel(level="instrument"))
            quote_dict[stock_id].sort_index()  # To support more flexible slicing, we must sort data first
        self.data = quote_dict

        n, unit = Freq.parse(freq)
        if unit in Freq.SUPPORT_CAL_LIST:
            self.freq = Freq.get_timedelta(1, unit)
        else:
            raise ValueError(f"{freq} is not supported in NumpyQuote")
        self.region = region

    def get_all_stock(self):
        return self.data.keys()

    @lru_cache(maxsize=512)
    def get_data(self, stock_id, start_time, end_time, field, method=None):
        # check stock id
        if stock_id not in self.get_all_stock():
            return None

        # single data
        # If it don't consider the classification of single data, it will consume a lot of time.
        if is_single_value(start_time, end_time, self.freq, self.region):
            # this is a very special case.
            # skip aggregating function to speed-up the query calculation

            # FIXME:

View on GitHub (pinned to 79633dd950)

Solutions

  1. Resample your data to daily or minute granularity and use freq="day" or freq="<n>min" (e.g. "1min", "5min")
  2. If you need week/month bars with the same interface, fall back to PandasQuote, which accepts any freq string
  3. Pre-validate with Freq.parse(freq) and assert the unit is in Freq.SUPPORT_CAL_LIST before constructing NumpyQuote

Example fix

# before
quote = NumpyQuote(quote_df, freq="week")
# after
quote_df_day = quote_df.groupby([pd.Grouper(level="datetime", freq="D"), pd.Grouper(level="instrument")]).last().dropna()
quote = NumpyQuote(quote_df_day, freq="day")
Defensive patterns

Strategy: validation

Validate before calling

from qlib.utils.time import Freq
_, unit = Freq.parse(freq)
assert unit in Freq.SUPPORT_CAL_LIST, (
    f"NumpyQuote only supports {Freq.SUPPORT_CAL_LIST}; got {unit!r} from freq {freq!r}")

Type guard

def numpyquote_supports(freq: str) -> bool:
    from qlib.utils.time import Freq
    try:
        _, unit = Freq.parse(freq)
    except Exception:
        return False
    return unit in Freq.SUPPORT_CAL_LIST  # currently ['minute', 'day']

Try / catch

try:
    quote = NumpyQuote(quote_df, freq=freq)
except ValueError as e:
    if "is not supported in NumpyQuote" in str(e):
        quote = PandasQuote(quote_df, freq=freq)  # documented fallback with wider freq support
    else:
        raise

Prevention

When it happens

Trigger: NumpyQuote(quote_df, freq="week"), freq="1month", freq="15min" is fine but freq="2h"/freq="1tick" is not; passing an exchange-level config freq (e.g. from an executor config like "day" vs "30min" mismatch) that isn't minute- or day-granular.

Common situations: Upgrading pipelines that previously used PandasQuote (which does not validate freq) to the faster NumpyQuote; configs ported from top-level workflow freq settings such as "week"; typos like "days" or "minutel" that Freq.parse cannot normalize.

Related errors


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