QuantConnect/Lean · error · NotImplementedError

Types deriving from 'UniverseSelectionModel' must implement

Error message

Types deriving from 'UniverseSelectionModel' must implement the 'def CreateUniverses(QCAlgorithm) method.

What it means

UniverseSelectionModel.create_universes is the entry point Lean calls (after Initialize) to obtain the algorithm's universes. The base class supports both the legacy PascalCase spelling CreateUniverses(algorithm) and the snake_case create_universes. If a subclass defines neither, it raises NotImplementedError telling you to implement CreateUniverses(QCAlgorithm). This is a contract-enforcement check that fires the first time Lean asks the model for its universes.

Source

Thrown at Algorithm/Selection/UniverseSelectionModel.py:33

class UniverseSelectionModel:
    '''Provides a base class for universe selection models.'''

    def get_next_refresh_time_utc(self) -> datetime:
        '''Gets the next time the framework should invoke the `CreateUniverses` method to refresh the set of universes.'''
        if hasattr(self, "GetNextRefreshTimeUtc") and callable(self.GetNextRefreshTimeUtc):
            return self.GetNextRefreshTimeUtc()
        return datetime.max

    def create_universes(self, algorithm: QCAlgorithm) -> list[Universe]:
        '''Creates the universes for this algorithm. Called once after <see cref="IAlgorithm.Initialize"/>
        Args:
            algorithm: The algorithm instance to create universes for</param>
        Returns:
            The universes to be used by the algorithm'''
        if hasattr(self, "CreateUniverses") and callable(self.CreateUniverses):
            return self.CreateUniverses(algorithm)
        raise NotImplementedError("Types deriving from 'UniverseSelectionModel' must implement the 'def CreateUniverses(QCAlgorithm) method.")

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Implement def create_universes(self, algorithm) in your subclass returning a list[Universe].
  2. If you are porting from an older Lean API, you may already have CreateUniverses — either keep it (the base supports it) or rename it to create_universes.
  3. Verify the method name spelling exactly; a typo (e.g. create_universe) means neither spelling matches.
  4. Ensure the method returns a list of Universe instances, not None.

Example fix

# before — subclass with no create method
class MyUniverseSelectionModel(UniverseSelectionModel):
    pass
self.set_universe_selection(MyUniverseSelectionModel())  # raises when Lean calls it

# after — implement the contract
class MyUniverseSelectionModel(UniverseSelectionModel):
    def create_universes(self, algorithm):
        return [algorithm.universe.add(MyUniverseSelectionModel.my_func)]
self.set_universe_selection(MyUniverseSelectionModel())
Defensive patterns

Strategy: validation

Validate before calling

# Verify the subclass implements the method before passing it to Lean
def has_create_universes(model):
    return hasattr(model, 'create_universes') and callable(model.create_universes)
model = MyUniverseSelectionModel()
assert has_create_universes(model), "Subclass must implement create_universes(self, algorithm)"
self.set_universe_selection(model)

Type guard

def implements_universe_contract(model):
    """True when the selection model exposes create_universes (or legacy CreateUniverses)."""
    return ((hasattr(model, 'create_universes') and callable(model.create_universes))
            or (hasattr(model, 'CreateUniverses') and callable(model.CreateUniverses)))

Prevention

When it happens

Trigger: You subclass UniverseSelectionModel and pass an instance to set_universe_selection, but your subclass does not define create_universes (snake_case) nor CreateUniverses (PascalCase). Lean calls the base create_universes, finds neither attribute via hasattr+callable, and raises. It also fires if you misspell the method (e.g. create_universe) or make it a non-callable attribute.

Common situations: A user subclasses UniverseSelectionModel intending to provide custom selection but forgets to implement the create_universes method. A Lean version migration changed the expected method name (PascalCase vs snake_case) and the subclass only had the old spelling. The method was defined but with a typo, so neither spelling is found.

Related errors


AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13). Data as JSON: /api/errors/7f405c227991b684. Report an issue: GitHub.