{"record":{"id":"de01234c06d10378","repo":"microsoft/qlib","slug":"lack-stock-doesn-t-have-close-price-in-qlib-in-t","errorCode":null,"errorMessage":"{lack_stock} doesn't have close price in qlib in the latest {last_days} days","messagePattern":"(.+?) doesn't have close price in qlib in the latest (.+?) days","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/position.py","lineNumber":318,"sourceCode":"            return\n\n        start_time = pd.Timestamp(start_time)\n        # note that start time is 2020-01-01 00:00:00 if raw start time is \"2020-01-01\"\n        price_end_time = start_time\n        price_start_time = start_time - timedelta(days=last_days)\n        price_df = D.features(\n            stock_list,\n            [\"$close\"],\n            price_start_time,\n            price_end_time,\n            freq=freq,\n            disk_cache=True,\n        ).dropna()\n        price_dict = price_df.groupby([\"instrument\"], group_keys=False).tail(1)[\"$close\"].to_dict()\n\n        if len(price_dict) < len(stock_list):\n            lack_stock = set(stock_list) - set(price_dict)\n            raise ValueError(f\"{lack_stock} doesn't have close price in qlib in the latest {last_days} days\")\n\n        for stock in stock_list:\n            self.position[stock][\"price\"] = price_dict[stock]\n        self.position[\"now_account_value\"] = self.calculate_value()\n\n    def _init_stock(self, stock_id: str, amount: float, price: float | None = None) -> None:\n        \"\"\"\n        initialization the stock in current position\n\n        Parameters\n        ----------\n        stock_id :\n            the id of the stock\n        amount : float\n            the amount of the stock\n        price :\n             the price when buying the init stock\n        \"\"\"","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/position.py#L300-L336","documentation":"Position.fill_stock_value tries to backfill missing prices for the initial holdings by querying D.features for '$close' over the last `last_days` (default 30) days before backtest start. If any instrument has no non-NaN close price in that window, it raises ValueError listing the offending stocks. It almost always means the qlib data provider has no (or only NaN) bars for those instruments before the backtest start date.","triggerScenarios":"Building a Position from a config/dict whose stock entries lack a 'price' key, then running fill_stock_value(start_time, freq). Occurs when: the instrument is not in the local bin data; the backtest start_time is before the instrument's listing date (new IPO); wrong freq passed; delisted/suspended stock with no recent close.","commonSituations":"Warm-starting a backtest with an inherited real portfolio that includes recently listed stocks; using cn_data demo dump that lacks some instruments; passing freq='1min' while only daily data exists; start_time set earlier than data coverage.","solutions":["Provide the 'price' field explicitly for each stock in the initial position config so fill_stock_value skips them","Push the backtest start_time later, past the listing date of every held instrument","Increase last_days (e.g. fill_stock_value(start, freq, last_days=120)) if the stock was suspended longer","Verify the instruments exist in your data: D.features([stock], ['$close'], start, end, freq=freq) and drop delisted names from the initial position"],"exampleFix":"# before\nposition_dict = {\"SH600000\": {\"amount\": 1000, \"price\": None}}\n\n# after\nposition_dict = {\"SH600000\": {\"amount\": 1000, \"price\": 11.5}}","handlingStrategy":"validation","validationCode":"from qlib.data import D\nlack = [s for s, v in position.position.items() if isinstance(v, dict) and v.get(\"price\") is None]\nif lack:\n    df = D.features(lack, [\"$close\"], start_time - pd.Timedelta(days=30), start_time, freq=freq)\n    missing = set(lack) - set(df.dropna().index.get_level_values(\"instrument\").unique())\n    assert not missing, f\"no close price for {missing}\"","typeGuard":null,"tryCatchPattern":"try:\n    position.fill_stock_value(start_time, freq)\nexcept ValueError as e:\n    # drop unpriceable holdings or extend window and retry once\n    position.fill_stock_value(start_time, freq, last_days=120)","preventionTips":["Always set 'price' in initial position configs","Pre-check data coverage with D.features before backtest start","Keep last_days larger than the longest suspension you expect"],"tags":["qlib","backtest","data-quality","position","missing-data"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}