QuantConnect/Lean · error · ValueError
MinimumVariancePortfolioOptimizer.portfolio_variance: Volati
Error message
MinimumVariancePortfolioOptimizer.portfolio_variance: Volatility cannot be zero. Weights: {weights} What it means
MinimumVariancePortfolioOptimizer (Python) shares the same variance guard as the Sharpe optimizer: wᵀ·Σ·w must be > 0 whenever weights are non-zero. A zero variance with non-zero weights indicates a degenerate (all-zero or rank-deficient) covariance matrix, which would make the minimum-variance objective meaningless.
Source
Thrown at Algorithm.Framework/Portfolio/MinimumVariancePortfolioOptimizer.py:81
bounds = self.get_boundary_conditions(size), # Bounds for variables
constraints = constraints, # Constraints definition
method='SLSQP') # Optimization method: Sequential Least Squares Programming (SLSQP)
if not opt['success']: return x0
# Scale the solution to ensure that the sum of the absolute weights is 1
sum_of_absolute_weights = np.sum(np.abs(opt['x']))
return opt['x'] / sum_of_absolute_weights
def portfolio_variance(self, weights, covariance):
'''Computes the portfolio variance
Args:
weighs: Portfolio weights
covariance: Covariance matrix of historical returns'''
variance = np.dot(weights.T, np.dot(covariance, weights))
if variance == 0 and np.any(weights):
# variance can't be zero, with non zero weights
raise ValueError(f'MinimumVariancePortfolioOptimizer.portfolio_variance: Volatility cannot be zero. Weights: {weights}')
return variance
def get_boundary_conditions(self, size):
'''Creates the boundary condition for the portfolio weights'''
return tuple((self.minimum_weight, self.maximum_weight) for x in range(size))
def get_budget_constraint(self, weights):
'''Defines a budget constraint: the sum of the weights equals unity'''
return np.sum(weights) - 1
def get_target_constraint(self, weights, expected_returns):
'''Ensure that the portfolio return target a given return'''
return np.dot(np.matrix(expected_returns), np.matrix(weights).T).item() - self.target_return
View on GitHub (pinned to d2c3659f87)
Solutions
- Enlarge the lookback/period so the covariance has real dispersion.
- Filter out symbols with zero return variance (np.std of returns == 0) before constructing the covariance.
- Verify the returns DataFrame used for covariance is non-empty and finite.
- Return fallback weights (e.g., equal-weight) when the covariance is degenerate instead of feeding it to the optimizer.
Example fix
# before
return opt['x'] / sum_of_absolute_weights # optimizer calls portfolio_variance -> raises
# guard: bail out before optimization on degenerate input
if not np.any(np.diag(covariance)):
algorithm.Debug('MinimumVariance: zero covariance, using equal weights')
return np.full(size, 1.0 / size) Defensive patterns
Strategy: validation
Validate before calling
import numpy as np
def safe_min_variance(optimizer, weights, covariance, size):
if covariance.size == 0 or not np.any(np.diag(covariance)) or np.any(np.isnan(covariance)):
return np.full(size, 1.0 / size) # equal-weight fallback
return optimizer.optimize(weights, covariance) Type guard
def covariance_is_valid(covariance: np.ndarray) -> bool:
return covariance.ndim == 2 and covariance.shape[0] == covariance.shape[1] and np.any(np.diag(covariance) > 0) and np.all(np.isfinite(covariance)) Prevention
- Verify returns are non-constant across the lookback before optimizing.
- Use a lookback long enough to give the covariance matrix real rank.
- Fall back to equal weights when dispersion is zero instead of letting the optimizer raise.
When it happens
Trigger: portfolio_variance() is invoked during scipy optimization with a covariance matrix that yields exactly zero variance for a non-zero weights vector — e.g., covariance is all zeros because historical returns were flat or unavailable.
Common situations: History window too short or empty, securities with constant prices, duplicate/correlated-zero symbols, or NaN-filled covariance after a failed History() pull.
Related errors
- MaximumSharpeRatioPortfolioOptimizer.portfolio_variance: Vol
- Total must be > 0 for Euclidean Projection onto the Simplex.
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/9925c219cd5cf3d1.
Report an issue: GitHub.