{"record":{"id":"1ab68d0cd27eed93","repo":"microsoft/qlib","slug":"none-in-trade-start-time-account-value-cash-re","errorCode":null,"errorMessage":"None in [trade_start_time, account_value, cash, return_rate, total_turnover, turnover_rate, total_cost, cost_rate, stock_value]","messagePattern":"None in \\[trade_start_time, account_value, cash, return_rate, total_turnover, turnover_rate, total_cost, cost_rate, stock_value\\]","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/backtest/report.py","lineNumber":179,"sourceCode":"        turnover_rate: float | None = None,\n        total_cost: float | None = None,\n        cost_rate: float | None = None,\n        stock_value: float | None = None,\n        bench_value: float | None = None,\n    ) -> None:\n        # check data\n        if None in [\n            trade_start_time,\n            account_value,\n            cash,\n            return_rate,\n            total_turnover,\n            turnover_rate,\n            total_cost,\n            cost_rate,\n            stock_value,\n        ]:\n            raise ValueError(\n                \"None in [trade_start_time, account_value, cash, return_rate, total_turnover, turnover_rate, \"\n                \"total_cost, cost_rate, stock_value]\",\n            )\n\n        if trade_end_time is None and bench_value is None:\n            raise ValueError(\"Both trade_end_time and bench_value is None, benchmark is not usable.\")\n        elif bench_value is None:\n            bench_value = self._sample_benchmark(self.bench, trade_start_time, trade_end_time)\n\n        # update pm data\n        self.accounts[trade_start_time] = account_value\n        self.returns[trade_start_time] = return_rate\n        self.total_turnovers[trade_start_time] = total_turnover\n        self.turnovers[trade_start_time] = turnover_rate\n        self.total_costs[trade_start_time] = total_cost\n        self.costs[trade_start_time] = cost_rate\n        self.values[trade_start_time] = stock_value\n        self.cashes[trade_start_time] = cash","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/backtest/report.py#L161-L197","documentation":"PortfolioMetric.fill (the per-step record API) requires complete accounting inputs; if any of trade_start_time, account_value, cash, return_rate, total_turnover, turnover_rate, total_cost, cost_rate, stock_value is None it raises ValueError listing them. The method writes one row per trade step into the accounts/returns/turnover/cost dicts, and None would poison all derived report metrics.","triggerScenarios":"Calling pm.fill(...) with a forgotten keyword argument (defaults None) or a computed metric that evaluated to None — most often bench_value-related returns or cost fields left unset by custom executors; also positional-argument mix-ups.","commonSituations":"Custom executors/nested flows calling fill with only a few fields; porting old code to a newer qlib signature that added stock_value; account fields returned as None when the exchange produced no deals.","solutions":["Supply every required field: default missing numeric fields to 0.0 and a valid trade_start_time","Trace which argument is None: print/log the tuple before calling fill","If a step genuinely had no trades, still pass zeros rather than None so reports stay consistent"],"exampleFix":"# before\npm.fill(trade_start_time=t, account_value=v, cash=c)  # rest default to None\n\n# after\npm.fill(trade_start_time=t, account_value=v, cash=c, return_rate=r or 0.0,\n        total_turnover=tov or 0.0, turnover_rate=tr or 0.0,\n        total_cost=tc or 0.0, cost_rate=cr or 0.0, stock_value=sv or 0.0)","handlingStrategy":"validation","validationCode":"required = dict(trade_start_time=trade_start_time, account_value=account_value, cash=cash,\n    return_rate=return_rate, total_turnover=total_turnover, turnover_rate=turnover_rate,\n    total_cost=total_cost, cost_rate=cost_rate, stock_value=stock_value)\nnone_fields = [k for k, v in required.items() if v is None]\nassert not none_fields, f\"fill() missing: {none_fields}\"","typeGuard":null,"tryCatchPattern":"try:\n    pm.fill(...)\nexcept ValueError as e:\n    raise RuntimeError(f\"incomplete metrics for step: {e}\") from e","preventionTips":["Default numeric metrics to 0.0, never None","Log the full metric tuple once per backtest to catch missing fields early","Pin keyword names when calling fill — avoid positional args"],"tags":["qlib","backtest","report","missing-argument","portfolio-metric"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}