{"record":{"id":"270319e803294ca3","repo":"QuantConnect/Lean","slug":"maximumsectorexposureriskmanagementmodel-the-maxi","errorCode":null,"errorMessage":"MaximumSectorExposureRiskManagementModel: the maximum sector exposure cannot be a non-positive value.","messagePattern":"MaximumSectorExposureRiskManagementModel: the maximum sector exposure cannot be a non-positive value\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Algorithm.Framework/Risk/MaximumSectorExposureRiskManagementModel.py","lineNumber":25,"sourceCode":"#\n# Unless required by applicable law or agreed to in writing, software\n# 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 *\nfrom itertools import groupby\n\nclass MaximumSectorExposureRiskManagementModel(RiskManagementModel):\n    '''Provides an implementation of IRiskManagementModel that that limits the sector exposure to the specified percentage'''\n\n    def __init__(self, maximum_sector_exposure = 0.20):\n        '''Initializes a new instance of the MaximumSectorExposureRiskManagementModel class\n        Args:\n            maximum_drawdown_percent: The maximum exposure for any sector, defaults to 20% sector exposure.'''\n        if maximum_sector_exposure <= 0:\n            raise ValueError('MaximumSectorExposureRiskManagementModel: the maximum sector exposure cannot be a non-positive value.')\n\n        self.maximum_sector_exposure = maximum_sector_exposure\n        self.targets_collection = PortfolioTargetCollection()\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        maximum_sector_exposure_value = float(algorithm.portfolio.total_portfolio_value) * self.maximum_sector_exposure\n\n        self.targets_collection.add_range(targets)\n\n        risk_targets = list()\n\n        # Group the securities by their sector\n        filtered = list(filter(lambda x: x.value.fundamentals is not None and x.value.fundamentals.has_fundamental_data, algorithm.universe_manager.active_securities))\n        filtered.sort(key = lambda x: x.value.fundamentals.company_reference.industry_template_code)\n        group_by_sector = groupby(filtered, lambda x: x.value.fundamentals.company_reference.industry_template_code)","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Framework/Risk/MaximumSectorExposureRiskManagementModel.py#L7-L43","documentation":"MaximumSectorExposureRiskManagementModel (Python) caps exposure per sector at a fraction of total portfolio value. A non-positive maximum_sector_exposure (≤ 0) would zero-out or invert the cap, which is meaningless for a risk-limit model, so __init__ raises ValueError before any risk management runs.","triggerScenarios":"Instantiating MaximumSectorExposureRiskManagementModel(maximum_sector_exposure) with 0 or a negative number. Default is 0.20 (20%).","commonSituations":"Passing the value as a whole number (e.g., 20 meaning 20%) instead of a fraction (0.20); passing a config-decoded string/int that resolved to 0; or a percentage field that defaults to 0 when unset.","solutions":["Pass a positive fraction, e.g. 0.20 for 20% — not 20, not 0.","If the value comes from a config/source, validate/coerce it to a positive float before construction.","Confirm units: this is a fraction of total portfolio value, not a percent integer."],"exampleFix":"# before\nself.add_risk_management(MaximumSectorExposureRiskManagementModel(0))     # raises\n# or\nself.add_risk_management(MaximumSectorExposureRiskManagementModel(20))  # means 2000%, wrong unit\n\n# after\nself.add_risk_management(MaximumSectorExposureRiskManagementModel(0.20))  # 20% per sector","handlingStrategy":"validation","validationCode":"def make_sector_model(max_exposure):\n    max_exposure = float(max_exposure)\n    if not (0 < max_exposure <= 1):\n        raise ValueError('maximum_sector_exposure must be a fraction in (0, 1], e.g. 0.20')\n    return MaximumSectorExposureRiskManagementModel(max_exposure)","typeGuard":"def is_valid_exposure_fraction(v) -> bool:\n    try:\n        return 0 < float(v) <= 1\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":null,"preventionTips":["Pass a fraction (0.20), not a percent integer (20).","Coerce config-sourced values to float and range-check before constructing the model."],"tags":["risk-management","configuration","validation"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}