QuantConnect/Lean · error · ValueError
optionChainSymbolSelector must return option, index options,
Error message
optionChainSymbolSelector must return option, index options, or futures options symbols.
What it means
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.
Source
Thrown at Algorithm.Framework/Selection/OptionUniverseSelectionModel.py:49
self.option_chain_symbol_selector = optionChainSymbolSelector
self.universe_settings = universeSettings
def get_next_refresh_time_utc(self):
'''Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.'''
return self.next_refresh_time_utc
def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
'''Creates a new fundamental universe using this class's selection functions
Args:
algorithm: The algorithm instance to create universes for
Returns:
The universe defined by this model'''
self.next_refresh_time_utc = (algorithm.utc_time + self.refresh_interval).date()
uniqueUnderlyingSymbols = set()
for option_symbol in self.option_chain_symbol_selector(algorithm.utc_time):
if not Extensions.is_option(option_symbol.security_type):
raise ValueError("optionChainSymbolSelector must return option, index options, or futures options symbols.")
# prevent creating duplicate option chains -- one per underlying
if option_symbol.underlying not in uniqueUnderlyingSymbols:
uniqueUnderlyingSymbols.add(option_symbol.underlying)
selection = self.filter
if hasattr(self, "Filter") and callable(self.Filter):
selection = self.Filter
yield Extensions.create_option_chain(algorithm, option_symbol, selection, self.universe_settings)
def filter(self, filter):
'''Defines the option chain universe filter'''
# NOP
return filter
View on GitHub (pinned to d2c3659f87)
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.
Example fix
# before
def selector(utc):
return [Symbol.Create('SPY', SecurityType.Equity, Market.USA)] # underlying, not option -> raises
# after
def selector(utc):
return [Symbol.Create('SPX', SecurityType.IndexOption, Market.USA)] Defensive patterns
Strategy: validation
Validate before calling
def option_selector(utc):
syms = my_selector(utc)
bad = [s for s in syms if not Extensions.is_option(s.security_type)]
if bad:
raise ValueError(f'Non-option symbols returned: {bad}')
return syms Type guard
def all_are_options(symbols) -> bool:
return all(Extensions.is_option(s.security_type) for s in symbols) Prevention
- Return option canonical symbols (Option, IndexOption, or FutureOption), never the underlying.
- Use Extensions.is_option to pre-validate the security type in your selector.
When it happens
Trigger: 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).
Common situations: Returning the underlying symbol instead of the option canonical, using Symbol.Create with the wrong SecurityType, or mixing option subtypes incorrectly.
Related errors
- futureChainSymbolSelector must return future symbols.
- Expected symbol {expected_symbol} at index {i} on {date}, bu
- ShareClassMeanReversionAlphaModel: symbols parameter must co
- Future contracts did not work up as expected: {addedSecurity
- Future contracts did not work up as expected: {addedSecurity
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/fa832cc6958d327a.
Report an issue: GitHub.