QuantConnect/Lean · error · ValueError
MaximumSectorExposureRiskManagementModel: the maximum sector
Error message
MaximumSectorExposureRiskManagementModel: the maximum sector exposure cannot be a non-positive value.
What it means
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.
Source
Thrown at Algorithm.Framework/Risk/MaximumSectorExposureRiskManagementModel.py:25
#
# Unless required by applicable law or agreed to in writing, software
# 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 *
from itertools import groupby
class MaximumSectorExposureRiskManagementModel(RiskManagementModel):
'''Provides an implementation of IRiskManagementModel that that limits the sector exposure to the specified percentage'''
def __init__(self, maximum_sector_exposure = 0.20):
'''Initializes a new instance of the MaximumSectorExposureRiskManagementModel class
Args:
maximum_drawdown_percent: The maximum exposure for any sector, defaults to 20% sector exposure.'''
if maximum_sector_exposure <= 0:
raise ValueError('MaximumSectorExposureRiskManagementModel: the maximum sector exposure cannot be a non-positive value.')
self.maximum_sector_exposure = maximum_sector_exposure
self.targets_collection = PortfolioTargetCollection()
def manage_risk(self, algorithm, targets):
'''Manages the algorithm's risk at each time step
Args:
algorithm: The algorithm instance'''
maximum_sector_exposure_value = float(algorithm.portfolio.total_portfolio_value) * self.maximum_sector_exposure
self.targets_collection.add_range(targets)
risk_targets = list()
# Group the securities by their sector
filtered = list(filter(lambda x: x.value.fundamentals is not None and x.value.fundamentals.has_fundamental_data, algorithm.universe_manager.active_securities))
filtered.sort(key = lambda x: x.value.fundamentals.company_reference.industry_template_code)
group_by_sector = groupby(filtered, lambda x: x.value.fundamentals.company_reference.industry_template_code)View on GitHub (pinned to d2c3659f87)
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.
Example fix
# before self.add_risk_management(MaximumSectorExposureRiskManagementModel(0)) # raises # or self.add_risk_management(MaximumSectorExposureRiskManagementModel(20)) # means 2000%, wrong unit # after self.add_risk_management(MaximumSectorExposureRiskManagementModel(0.20)) # 20% per sector
Defensive patterns
Strategy: validation
Validate before calling
def make_sector_model(max_exposure):
max_exposure = float(max_exposure)
if not (0 < max_exposure <= 1):
raise ValueError('maximum_sector_exposure must be a fraction in (0, 1], e.g. 0.20')
return MaximumSectorExposureRiskManagementModel(max_exposure) Type guard
def is_valid_exposure_fraction(v) -> bool:
try:
return 0 < float(v) <= 1
except (TypeError, ValueError):
return False Prevention
- Pass a fraction (0.20), not a percent integer (20).
- Coerce config-sourced values to float and range-check before constructing the model.
When it happens
Trigger: Instantiating MaximumSectorExposureRiskManagementModel(maximum_sector_exposure) with 0 or a negative number. Default is 0.20 (20%).
Common situations: 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.
Related errors
- ShareClassMeanReversionAlphaModel: symbols parameter must co
- Long position must be allowed in MeanReversionPortfolioConst
- Total must be > 0 for Euclidean Projection onto the Simplex.
- Long position must be allowed in RiskParityPortfolioConstruc
- MaximumSectorExposureRiskManagementModel.on_securities_chang
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/270319e803294ca3.
Report an issue: GitHub.