{"record":{"id":"fa832cc6958d327a","repo":"QuantConnect/Lean","slug":"optionchainsymbolselector-must-return-option-inde","errorCode":null,"errorMessage":"optionChainSymbolSelector must return option, index options, or futures options symbols.","messagePattern":"optionChainSymbolSelector must return option, index options, or futures options symbols\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Algorithm.Framework/Selection/OptionUniverseSelectionModel.py","lineNumber":49,"sourceCode":"        self.option_chain_symbol_selector = optionChainSymbolSelector\n        self.universe_settings = universeSettings\n\n    def get_next_refresh_time_utc(self):\n        '''Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.'''\n        return self.next_refresh_time_utc\n\n    def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:\n        '''Creates a new fundamental universe using this class's selection functions\n        Args:\n            algorithm: The algorithm instance to create universes for\n        Returns:\n            The universe defined by this model'''\n        self.next_refresh_time_utc = (algorithm.utc_time + self.refresh_interval).date()\n\n        uniqueUnderlyingSymbols = set()\n        for option_symbol in self.option_chain_symbol_selector(algorithm.utc_time):\n            if not Extensions.is_option(option_symbol.security_type):\n                raise ValueError(\"optionChainSymbolSelector must return option, index options, or futures options symbols.\")\n\n            # prevent creating duplicate option chains -- one per underlying\n            if option_symbol.underlying not in uniqueUnderlyingSymbols:\n                uniqueUnderlyingSymbols.add(option_symbol.underlying)\n                selection = self.filter\n                if hasattr(self, \"Filter\") and callable(self.Filter):\n                    selection = self.Filter\n                yield Extensions.create_option_chain(algorithm, option_symbol, selection, self.universe_settings)\n\n    def filter(self, filter):\n        '''Defines the option chain universe filter'''\n        # NOP\n        return filter\n","sourceCodeStart":31,"sourceCodeEnd":63,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Framework/Selection/OptionUniverseSelectionModel.py#L31-L63","documentation":"OptionUniverseSelectionModel.create_universes() iterates the user-supplied option_chain_symbol_selector and builds an option chain per underlying. Every returned symbol must be an option type — Extensions.is_option() accepts equity options, index options, and futures options; anything else (equity, future, forex) raises ValueError.","triggerScenarios":"The option_chain_symbol_selector returns a Symbol whose security_type is not an option variant (e.g., the underlying equity, a raw future, or forex).","commonSituations":"Returning the underlying symbol instead of the option canonical, using Symbol.Create with the wrong SecurityType, or mixing option subtypes incorrectly.","solutions":["Return option canonical symbols only, e.g. Symbol.Create('SPX', SecurityType.IndexOption, Market.USA) or an equity Option canonical.","Confirm the security_type passed to Symbol.Create is one of Option, IndexOption, or FutureOption.","If you only have the underlying, use the appropriate option-canonical helper rather than returning the underlying directly."],"exampleFix":"# before\ndef selector(utc):\n    return [Symbol.Create('SPY', SecurityType.Equity, Market.USA)]  # underlying, not option -> raises\n\n# after\ndef selector(utc):\n    return [Symbol.Create('SPX', SecurityType.IndexOption, Market.USA)]","handlingStrategy":"validation","validationCode":"def option_selector(utc):\n    syms = my_selector(utc)\n    bad = [s for s in syms if not Extensions.is_option(s.security_type)]\n    if bad:\n        raise ValueError(f'Non-option symbols returned: {bad}')\n    return syms","typeGuard":"def all_are_options(symbols) -> bool:\n    return all(Extensions.is_option(s.security_type) for s in symbols)","tryCatchPattern":null,"preventionTips":["Return option canonical symbols (Option, IndexOption, or FutureOption), never the underlying.","Use Extensions.is_option to pre-validate the security type in your selector."],"tags":["universe-selection","options","symbol","validation"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}