QuantConnect/Lean · error · Exception
IRiskManagementModel.{attribute_names[1]} must be implemente
Error message
IRiskManagementModel.{attribute_names[1]} must be implemented. Please implement this missing method on {model.__class__.__name__} What it means
CompositeRiskManagementModel.__init__ validates that every model passed to it implements the IRiskManagementModel contract. It checks, for each model, both the PascalCase and snake_case spellings of two required methods: ManageRisk/manage_risk and OnSecuritiesChanged/on_securities_changed. If a model has neither spelling of a given method, it raises an Exception naming the model class. This is a contract-enforcement check at composition time, before the algorithm runs.
Source
Thrown at Algorithm/Risk/CompositeRiskManagementModel.py:27
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from AlgorithmImports import *
class CompositeRiskManagementModel(RiskManagementModel):
'''Provides an implementation of IRiskManagementModel that combines multiple risk models
into a single risk management model and properly sets each insights 'SourceModel' property.'''
def __init__(self, *risk_management_models):
'''Initializes a new instance of the CompositeRiskManagementModel class
Args:
risk_management_models: The individual risk management models defining this composite model.'''
for model in risk_management_models:
for attribute_names in [('ManageRisk', 'manage_risk'), ('OnSecuritiesChanged', 'on_securities_changed')]:
if not hasattr(model, attribute_names[0]) and not hasattr(model, attribute_names[1]):
raise Exception(f'IRiskManagementModel.{attribute_names[1]} must be implemented. Please implement this missing method on {model.__class__.__name__}')
self.risk_management_models = risk_management_models
def manage_risk(self, algorithm, targets):
'''Manages the algorithm's risk at each time step
Args:
algorithm: The algorithm instance
targets: The current portfolio targets to be assessed for risk'''
for model in self.risk_management_models:
# take into account the possibility of ManageRisk returning nothing
risk_adjusted = model.manage_risk(algorithm, targets)
# produce a distinct set of new targets giving preference to newer targets
symbols = [x.symbol for x in risk_adjusted]
for target in targets:
if target.symbol not in symbols:
risk_adjusted.append(target)
View on GitHub (pinned to d2c3659f87)
Solutions
- Ensure each passed model subclasses RiskManagementModel (which supplies both methods) OR explicitly defines both manage_risk and on_securities_changed.
- If you wrote a duck-typed model, add the missing method — e.g. def on_securities_changed(self, algorithm, changes): pass.
- Check the contract up front: for each model verify hasattr(model,'manage_risk') and hasattr(model,'on_securities_changed') before constructing the composite.
- After a Lean upgrade, confirm the required-method names (snake_case) did not change.
Example fix
# before — model only defines one method
class MyRiskModel:
def manage_risk(self, algorithm, targets):
return []
# ...
self.set_risk_management(CompositeRiskManagementModel(MyRiskModel())) # raises
# after — implement the full contract (or subclass RiskManagementModel)
class MyRiskModel(RiskManagementModel):
def manage_risk(self, algorithm, targets):
return []
def on_securities_changed(self, algorithm, changes):
pass
self.set_risk_management(CompositeRiskManagementModel(MyRiskModel())) Defensive patterns
Strategy: validation
Validate before calling
# Validate each model implements the contract before composing
def is_valid_risk_model(model):
return ((hasattr(model,'manage_risk') or hasattr(model,'ManageRisk'))
and (hasattr(model,'on_securities_changed') or hasattr(model,'OnSecuritiesChanged')))
for m in models:
if not is_valid_risk_model(m):
raise ValueError(f"{type(m).__name__} does not implement the risk model contract")
composite = CompositeRiskManagementModel(*models) Type guard
def implements_risk_contract(model):
"""True when model exposes both required methods (either spelling)."""
has_manage = hasattr(model, 'manage_risk') or hasattr(model, 'ManageRisk')
has_changed = hasattr(model, 'on_securities_changed') or hasattr(model, 'OnSecuritiesChanged')
return has_manage and has_changed Prevention
- Subclass RiskManagementModel so the base provides both required methods.
- If duck-typing, define both manage_risk and on_securities_changed explicitly.
- Validate the contract before constructing the composite to fail fast with a clear message.
When it happens
Trigger: You construct CompositeRiskManagementModel(model_a, model_b, ...) where at least one model is missing both manage_risk and ManageRisk, or both on_securities_changed and OnSecuritiesChanged. Concretely: passing a plain object or a half-implemented subclass (e.g. one that defines manage_risk but forgets the securities-changed hook) triggers it. Note the check uses `and not hasattr` for both spellings, so defining either spelling satisfies it.
Common situations: A user subclasses RiskManagementModel but only overrides manage_risk, forgetting on_securities_changed (the base provides defaults, but if the object is not a proper subclass it lacks both). Passing a lambda/duck-typed object that does not implement the full interface. A refactor renamed a method and broke the contract.
Related errors
- Types deriving from 'UniverseSelectionModel' must implement
- OrderEvent LimitPrice is Not expected to be 0 for LimitOrder
- OrderEvent StopPrice is Not expected to be 0 for StopMarketO
- OrderEvent Ticket was not set
- OrderEvent.ORDER_ID and order_event.ticket.order_id do not m
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/7d4d598910232448.
Report an issue: GitHub.