{"record":{"id":"7d4d598910232448","repo":"QuantConnect/Lean","slug":"iriskmanagementmodel-attribute-names-1-must-be","errorCode":null,"errorMessage":"IRiskManagementModel.{attribute_names[1]} must be implemented. Please implement this missing method on {model.__class__.__name__}","messagePattern":"IRiskManagementModel\\.(.+?) must be implemented\\. Please implement this missing method on (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Algorithm/Risk/CompositeRiskManagementModel.py","lineNumber":27,"sourceCode":"# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom AlgorithmImports import *\n\nclass CompositeRiskManagementModel(RiskManagementModel):\n    '''Provides an implementation of IRiskManagementModel that combines multiple risk models\n    into a single risk management model and properly sets each insights 'SourceModel' property.'''\n\n    def __init__(self, *risk_management_models):\n        '''Initializes a new instance of the CompositeRiskManagementModel class\n        Args:\n            risk_management_models: The individual risk management models defining this composite model.'''\n        for model in risk_management_models:\n            for attribute_names in [('ManageRisk', 'manage_risk'), ('OnSecuritiesChanged', 'on_securities_changed')]:\n                if not hasattr(model, attribute_names[0]) and not hasattr(model, attribute_names[1]):\n                    raise Exception(f'IRiskManagementModel.{attribute_names[1]} must be implemented. Please implement this missing method on {model.__class__.__name__}')\n\n        self.risk_management_models = risk_management_models\n\n    def manage_risk(self, algorithm, targets):\n        '''Manages the algorithm's risk at each time step\n        Args:\n            algorithm: The algorithm instance\n            targets: The current portfolio targets to be assessed for risk'''\n        for model in self.risk_management_models:\n            # take into account the possibility of ManageRisk returning nothing\n            risk_adjusted = model.manage_risk(algorithm, targets)\n\n            # produce a distinct set of new targets giving preference to newer targets\n            symbols = [x.symbol for x in risk_adjusted]\n            for target in targets:\n                if target.symbol not in symbols:\n                    risk_adjusted.append(target)\n","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm/Risk/CompositeRiskManagementModel.py#L9-L45","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before — model only defines one method\nclass MyRiskModel:\n    def manage_risk(self, algorithm, targets):\n        return []\n# ...\nself.set_risk_management(CompositeRiskManagementModel(MyRiskModel()))  # raises\n\n# after — implement the full contract (or subclass RiskManagementModel)\nclass MyRiskModel(RiskManagementModel):\n    def manage_risk(self, algorithm, targets):\n        return []\n    def on_securities_changed(self, algorithm, changes):\n        pass\nself.set_risk_management(CompositeRiskManagementModel(MyRiskModel()))","handlingStrategy":"validation","validationCode":"# Validate each model implements the contract before composing\ndef is_valid_risk_model(model):\n    return ((hasattr(model,'manage_risk') or hasattr(model,'ManageRisk'))\n            and (hasattr(model,'on_securities_changed') or hasattr(model,'OnSecuritiesChanged')))\nfor m in models:\n    if not is_valid_risk_model(m):\n        raise ValueError(f\"{type(m).__name__} does not implement the risk model contract\")\ncomposite = CompositeRiskManagementModel(*models)","typeGuard":"def implements_risk_contract(model):\n    \"\"\"True when model exposes both required methods (either spelling).\"\"\"\n    has_manage = hasattr(model, 'manage_risk') or hasattr(model, 'ManageRisk')\n    has_changed = hasattr(model, 'on_securities_changed') or hasattr(model, 'OnSecuritiesChanged')\n    return has_manage and has_changed","tryCatchPattern":null,"preventionTips":["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."],"tags":["quantconnect","lean","risk-management","composite","interface-contract","python"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}