microsoft/qlib · error · FileNotFoundError

No file is found.

Error message

No file is found.

What it means

`LocalPITProvider.period_feature` looks for `<provider_uri>/financial/<instrument>/<field>.index` and `.data` files. If either binary file is missing, it raises FileNotFoundError — the requested PIT field simply is not on disk for that instrument.

Source

Thrown at qlib/data/data.py:785

        # {For acceleration
        # start_index, end_index, cur_index = kwargs["info"]
        # if cur_index == start_index:
        #     if not hasattr(self, "all_fields"):
        #         self.all_fields = []
        #     self.all_fields.append(field)
        #     if not hasattr(self, "period_index"):
        #         self.period_index = {}
        #     if field not in self.period_index:
        #         self.period_index[field] = {}
        # For acceleration}

        if not field.endswith("_q") and not field.endswith("_a"):
            raise ValueError("period field must ends with '_q' or '_a'")
        quarterly = field.endswith("_q")
        index_path = C.dpm.get_data_uri() / "financial" / instrument.lower() / f"{field}.index"
        data_path = C.dpm.get_data_uri() / "financial" / instrument.lower() / f"{field}.data"
        if not (index_path.exists() and data_path.exists()):
            raise FileNotFoundError("No file is found.")
        # NOTE: The most significant performance loss is here.
        # Does the acceleration that makes the program complicated really matters?
        # - It makes parameters of the interface complicate
        # - It does not performance in the optimal way (places all the pieces together, we may achieve higher performance)
        #    - If we design it carefully, we can go through for only once to get the historical evolution of the data.
        # So I decide to deprecated previous implementation and keep the logic of the program simple
        # Instead, I'll add a cache for the index file.
        data = np.fromfile(data_path, dtype=DATA_RECORDS)

        # find all revision periods before `cur_time`
        cur_time_int = int(cur_time.year) * 10000 + int(cur_time.month) * 100 + int(cur_time.day)
        loc = np.searchsorted(data["date"], cur_time_int, side="right")
        if loc <= 0:
            return pd.Series(dtype=C.pit_record_type["value"])
        last_period = data["period"][:loc].max()  # return the latest quarter
        first_period = data["period"][:loc].min()
        period_list = get_period_list(first_period, last_period, quarterly)
        if period is not None:

View on GitHub (pinned to 79633dd950)

Solutions

  1. Dump PIT data: use scripts/data_collector/utils/dump_bin.py with financial data (collector `get_and_dump_financial_data`), which writes financial/<inst>/<field>.{index,data}.
  2. Verify the path exists: `ls $(python -c 'import qlib;from qlib.config import C;print(C.dpm.get_data_uri())')/financial/<inst>/` and confirm the field files.
  3. If only some instruments lack the field, restrict instruments to those with the file.

Example fix

# before
qlib.init(provider_uri='./data/qlib_data')  # only day bins dumped
D.features(insts, ['P($$roewa_q)'])

# after
# dump financial PIT data first
# python dump_bin.py --data_type financial ... (or collector flow)
qlib.init(provider_uri='./data/qlib_data_with_financial')
D.features(insts, ['P($$roewa_q)'])
Defensive patterns

Strategy: validation

Validate before calling

from qlib.config import C
import os

def pit_data_exists(instrument: str, field: str) -> bool:
    base = C.dpm.get_data_uri() / 'financial' / instrument.lower()
    return (base / f'{field}.index').exists() and (base / f'{field}.data').exists()

Type guard

import os
from pathlib import Path

def pit_files_present(base_dir: Path, inst: str, field: str) -> bool:
    d = base_dir / 'financial' / inst.lower()
    return (d / f'{field}.index').is_file() and (d / f'{field}.data').is_file()

Try / catch

try:
    df = D.features(insts, [f'P({field})'])
except FileNotFoundError:
    # PIT data absent for this field/instrument: skip or use fallback fields
    df = D.features(insts, ['$close'])

Prevention

When it happens

Trigger: Requesting `P($$roewa_q)` when the qlib data directory contains no financial/ subfolder (price-only data was dumped), or the field exists for some instruments but not the requested one (e.g. a delisted or new stock).

Common situations: Using `qlib.init(provider_uri=...)` with data from `dump_bin.py` on prices only (no `--data_type financial` / get_and_dump_financial_data step); pointing provider_uri at a different machine's data dir; case mismatches because the path is lowercased.

Related errors


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