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
- 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}.
- 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.
- 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
- Dump financial data together with price data (collector + dump_bin).
- Check provider_uri points at a dir containing financial/ before using $$ fields.
- Note instrument names are lowercased in the financial path layout.
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
- User data for {} already exists
- Expected pd.Timestamp for `cur_time`, got '{cur_time}'. Advi
- period field must ends with '_q' or '_a'
- This recorder is not saved in the local file system.
- calendar does not exist: {self.calendar_path}
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/d7e36eaa0c9c0e18.
Report an issue: GitHub.