microsoft/qlib · error · ValueError

query_trade_dates respond error_msg: {rs.error_msg}

Error message

query_trade_dates respond error_msg: {rs.error_msg}

What it means

Raised by CollectorFutureCalendarCN.collector (scripts/data_collector/future_calendar_collector.py:79) when bs.query_trade_dates(start_date, end_date) returns a non-'0' error_code after a successful bs.login(). It signals the baostock API rejected or failed the trade-date query itself, commonly due to malformed/upper-bound date ranges or server-side errors.

Source

Thrown at scripts/data_collector/future_calendar_collector.py:79

        """

        Returns
        -------

        """
        raise NotImplementedError(f"Please implement the `collector` method")


class CollectorFutureCalendarCN(CollectorFutureCalendar):
    def collector(self) -> Iterable[pd.Timestamp]:
        lg = bs.login()
        if lg.error_code != "0":
            raise ValueError(f"login respond error_msg: {lg.error_msg}")
        rs = bs.query_trade_dates(
            start_date=self._format_datetime(self.start_date), end_date=self._format_datetime(self.end_date)
        )
        if rs.error_code != "0":
            raise ValueError(f"query_trade_dates respond error_msg: {rs.error_msg}")
        data_list = []
        while (rs.error_code == "0") & rs.next():
            data_list.append(rs.get_row_data())
        calendar = pd.DataFrame(data_list, columns=rs.fields)
        calendar["is_trading_day"] = calendar["is_trading_day"].astype(int)
        return pd.to_datetime(calendar[calendar["is_trading_day"] == 1]["calendar_date"]).to_list()


class CollectorFutureCalendarUS(CollectorFutureCalendar):
    def collector(self) -> Iterable[pd.Timestamp]:
        # TODO: US future calendar
        raise ValueError("Us calendar is not supported")


def run(qlib_dir: Union[str, Path], region: str = "cn", start_date: str = None, end_date: str = None):
    """Collect future calendar(day)

    Parameters

View on GitHub (pinned to 79633dd950)

Solutions

  1. Pass an explicit, modest --end_date within baostock's published range instead of relying on the +2-year default.
  2. Confirm start_date/end_date are valid yyyy-MM-dd strings after _format_datetime.
  3. Wrap the run in a retry that re-executes bs.login() before query_trade_dates (session expiry).

Example fix

# before
cal = CollectorFutureCalendarCN(qlib_dir, start_date=None, end_date=None)  # end = last + 730d

# after
cal = CollectorFutureCalendarCN(qlib_dir, start_date='2026-01-01', end_date='2026-12-31')
Defensive patterns

Strategy: retry

Validate before calling

import baostock as bs
rs = bs.query_trade_dates(start_date=start, end_date=end)
if rs.error_code != '0':
    raise SystemExit(f'query_trade_dates failed: {rs.error_msg}')

Try / catch

try:
    dates = CollectorFutureCalendarCN(qd, start_date=s, end_date=e).collector()
except ValueError as e:
    if 'query_trade_dates' in str(e):
        # narrow range or re-login then retry once
        raise

Prevention

When it happens

Trigger: Calling collector() where _format_datetime(self.start_date)/end_date produce dates baostock rejects — e.g. end_date beyond baostock's published calendar (the class defaults end_date to latest calendar date + 365*2 days), or a stale session. Any rs.error_code != '0' from query_trade_dates triggers it.

Common situations: Using the default end_date (calendar tail + 2 years) when baostock only publishes dates nearer term; date format mismatches from a custom start_date; long-running processes whose baostock session expired between login and query.

Related errors


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