{"record":{"id":"e3d3ca27978fae3c","repo":"OpenBB-finance/OpenBB","slug":"error-stat-could-not-be-generated-because-the","errorCode":null,"errorMessage":"Error: '{stat}' could not be generated because the underlying price was not returned by the provider. Set manually with 'underlying_price' property.","messagePattern":"Error: '(.+?)' could not be generated because the underlying price was not returned by the provider\\. Set manually with 'underlying_price' property\\.","errorType":"exception","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/core/openbb_core/provider/utils/options_chains_properties.py","lineNumber":340,"sourceCode":"        \"\"\"\n        # pylint: disable=import-outside-toplevel\n        from numpy import nan\n        from pandas import DataFrame, concat\n\n        stats = [\"open_interest\", \"volume\", \"dex\", \"gex\"]\n        _stat = stat.upper() if stat in [\"dex\", \"gex\"] else stat\n        by = \"strike\" if date is not None else by\n        if stat is not None:\n            if stat not in stats:\n                raise OpenBBError(f\"Error: stat must be one of {stats}\")\n            if stat in [\"volume\", \"open_interest\"]:\n                return DataFrame(self._get_stat(stat, moneyness=moneyness, date=date)[by]).replace({nan: None})  # type: ignore\n            if (\n                _stat not in self.dataframe.columns\n                and self.has_greeks\n                and \"underlying_price\" not in self.dataframe.columns\n            ):\n                raise OpenBBError(\n                    f\"Error: '{stat}' could not be generated because\"\n                    + \" the underlying price was not returned by the provider.\"\n                    + \" Set manually with 'underlying_price' property.\"\n                )\n            df = DataFrame(self._get_stat(_stat, moneyness=moneyness, date=date)[by])  # type: ignore\n            return df.replace({nan: None})\n\n        df = self.dataframe\n\n        if moneyness is not None:\n            df_calls = DataFrame(\n                df[df.strike >= df.underlying_price].query(\"option_type == 'call'\")\n            )\n            df_puts = DataFrame(\n                df[df.strike <= df.underlying_price].query(\"option_type == 'put'\")\n            )\n            df = concat([df_calls, df_puts])\n","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/core/openbb_core/provider/utils/options_chains_properties.py#L322-L358","documentation":"Raised inside OptionsChainsData.filter_data when stat is 'dex' or 'gex' (uppercased to DEX/GEX), that computed column is absent from the cached dataframe, greeks ARE present, but the underlying price is missing — the DEX/GEX formula multiplies by underlying_price, so it cannot be derived. Setting last_price (or the underlying_price property) injects the price and lets the columns be computed.","triggerScenarios":"result.filter_data(stat='gex') on a chains response whose provider returned greeks but no underlying_price, and where result.last_price was never set. The enriched dataframe therefore lacks the DEX/GEX columns this branch requires.","commonSituations":"Greeks-rich providers without spot quotes (some derivatives-only endpoints); users who fetched with one provider and then set a spot from another source but forgot the last_price override.","solutions":["Set the override before filtering: result.last_price = 585.20; then result.filter_data(stat='gex')","Or request the chains from a provider that returns underlying_price alongside greeks","If exposure stats are optional, wrap the call in a has_greeks + underlying-price check and degrade gracefully"],"exampleFix":"# before\ndf = res.filter_data(stat=\"dex\")  # OpenBBError: 'dex' could not be generated...\n\n# after\nres.last_price = 185.50\ndf = res.filter_data(stat=\"dex\")","handlingStrategy":"validation","validationCode":"def prep_for_exposure(res, spot: float):\n    if spot is not None and res.last_price is None:\n        res.last_price = spot\n    return res\n\n# call before filter_data(stat=\"dex\"/\"gex\") whenever the provider omits the spot","typeGuard":"def can_filter_exposure(res) -> bool:\n    return res.has_greeks and (\"underlying_price\" in res.dataframe.columns or res.last_price is not None)","tryCatchPattern":"from openbb_core.app.model.abstract.error import OpenBBError\n\ntry:\n    df = res.filter_data(stat=\"gex\")\nexcept OpenBBError as e:\n    if \"underlying price was not returned\" in str(e):\n        res.last_price = get_spot(symbol)\n        df = res.filter_data(stat=\"gex\")\n    else:\n        raise","preventionTips":["Set last_price once right after fetching chains if you plan to use dex/gex anywhere downstream","Check has_greeks plus the underlying_price column before exposure filters","Cache a spot-price source (quote endpoint) alongside chains fetching in your pipeline"],"tags":["options","dex","gex","underlying-price","derivatives"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}