{"record":{"id":"7e5959d21fccf99f","repo":"microsoft/qlib","slug":"period-field-must-ends-with-q-or-a","errorCode":null,"errorMessage":"period field must ends with '_q' or '_a'","messagePattern":"period field must ends with '_q' or '_a'","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/data/data.py","lineNumber":780,"sourceCode":"        VALUE_DTYPE = C.pit_record_type[\"value\"]\n\n        field = str(field).lower()[2:]\n        instrument = code_to_fname(instrument)\n\n        # {For acceleration\n        # start_index, end_index, cur_index = kwargs[\"info\"]\n        # if cur_index == start_index:\n        #     if not hasattr(self, \"all_fields\"):\n        #         self.all_fields = []\n        #     self.all_fields.append(field)\n        #     if not hasattr(self, \"period_index\"):\n        #         self.period_index = {}\n        #     if field not in self.period_index:\n        #         self.period_index[field] = {}\n        # For acceleration}\n\n        if not field.endswith(\"_q\") and not field.endswith(\"_a\"):\n            raise ValueError(\"period field must ends with '_q' or '_a'\")\n        quarterly = field.endswith(\"_q\")\n        index_path = C.dpm.get_data_uri() / \"financial\" / instrument.lower() / f\"{field}.index\"\n        data_path = C.dpm.get_data_uri() / \"financial\" / instrument.lower() / f\"{field}.data\"\n        if not (index_path.exists() and data_path.exists()):\n            raise FileNotFoundError(\"No file is found.\")\n        # NOTE: The most significant performance loss is here.\n        # Does the acceleration that makes the program complicated really matters?\n        # - It makes parameters of the interface complicate\n        # - It does not performance in the optimal way (places all the pieces together, we may achieve higher performance)\n        #    - If we design it carefully, we can go through for only once to get the historical evolution of the data.\n        # So I decide to deprecated previous implementation and keep the logic of the program simple\n        # Instead, I'll add a cache for the index file.\n        data = np.fromfile(data_path, dtype=DATA_RECORDS)\n\n        # find all revision periods before `cur_time`\n        cur_time_int = int(cur_time.year) * 10000 + int(cur_time.month) * 100 + int(cur_time.day)\n        loc = np.searchsorted(data[\"date\"], cur_time_int, side=\"right\")\n        if loc <= 0:","sourceCodeStart":762,"sourceCodeEnd":798,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/data.py#L762-L798","documentation":"PIT period fields encode their period in the suffix: `_q` means quarterly revision data, `_a` annual. `LocalPITProvider.period_feature` branches on that suffix to pick the interpretation, so any other name is meaningless to the storage layer and raises ValueError.","triggerScenarios":"Requesting `P($$roewa)` or `P($$myfield)` where the name does not end in _q/_a; typos like `$$roewa_Q` (capital Q) also fail since the check is case-sensitive lowercase.","commonSituations":"Hand-writing financial field names or porting names from other data vendors; renaming fields in dumped PIT data without keeping the suffix convention.","solutions":["Rename the field to end with `_q` (quarterly) or `_a` (annual), e.g. `$$roewa_q`.","Check the field list in your PIT data directory (`features/financial/<inst>/*.index`) for exact available names and suffixes."],"exampleFix":"# before\ndf = D.features(insts, ['P($$roewa)'])\n\n# after\ndf = D.features(insts, ['P($$roewa_q)'])","handlingStrategy":"validation","validationCode":"def is_valid_period_field(f: str) -> bool:\n    return f.endswith('_q') or f.endswith('_a')\n\nassert all(is_valid_period_field(f.lstrip('P($')) for f in pit_fields)","typeGuard":"def is_valid_period_field(f: str) -> bool:\n    f = f.strip()\n    return f.endswith('_q') or f.endswith('_a')","tryCatchPattern":null,"preventionTips":["Keep _q/_a suffixes when dumping PIT data with dump_bin/get_and_dump_financial_data.","Use lowercase suffixes; the check is case-sensitive."],"tags":["pit-data","naming-convention","validation"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}