{"record":{"id":"9925c219cd5cf3d1","repo":"QuantConnect/Lean","slug":"minimumvarianceportfoliooptimizer-portfolio-varian","errorCode":null,"errorMessage":"MinimumVariancePortfolioOptimizer.portfolio_variance: Volatility cannot be zero. Weights: {weights}","messagePattern":"MinimumVariancePortfolioOptimizer\\.portfolio_variance: Volatility cannot be zero\\. Weights: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Algorithm.Framework/Portfolio/MinimumVariancePortfolioOptimizer.py","lineNumber":81,"sourceCode":"                       bounds = self.get_boundary_conditions(size),               # Bounds for variables\n                       constraints = constraints,                                 # Constraints definition\n                       method='SLSQP')     # Optimization method:  Sequential Least Squares Programming (SLSQP)\n\n        if not opt['success']: return x0\n\n        # Scale the solution to ensure that the sum of the absolute weights is 1\n        sum_of_absolute_weights = np.sum(np.abs(opt['x']))\n        return opt['x'] / sum_of_absolute_weights\n\n    def portfolio_variance(self, weights, covariance):\n        '''Computes the portfolio variance\n        Args:\n            weighs: Portfolio weights\n            covariance: Covariance matrix of historical returns'''\n        variance = np.dot(weights.T, np.dot(covariance, weights))\n        if variance == 0 and np.any(weights):\n            # variance can't be zero, with non zero weights\n            raise ValueError(f'MinimumVariancePortfolioOptimizer.portfolio_variance: Volatility cannot be zero. Weights: {weights}')\n        return variance\n\n    def get_boundary_conditions(self, size):\n        '''Creates the boundary condition for the portfolio weights'''\n        return tuple((self.minimum_weight, self.maximum_weight) for x in range(size))\n\n    def get_budget_constraint(self, weights):\n        '''Defines a budget constraint: the sum of the weights equals unity'''\n        return np.sum(weights) - 1\n\n    def get_target_constraint(self, weights, expected_returns):\n        '''Ensure that the portfolio return target a given return'''\n        return np.dot(np.matrix(expected_returns), np.matrix(weights).T).item() - self.target_return\n","sourceCodeStart":63,"sourceCodeEnd":95,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Framework/Portfolio/MinimumVariancePortfolioOptimizer.py#L63-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"History window too short or empty, securities with constant prices, duplicate/correlated-zero symbols, or NaN-filled covariance after a failed History() pull.","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."],"exampleFix":"# before\nreturn opt['x'] / sum_of_absolute_weights  # optimizer calls portfolio_variance -> raises\n\n# guard: bail out before optimization on degenerate input\nif not np.any(np.diag(covariance)):\n    algorithm.Debug('MinimumVariance: zero covariance, using equal weights')\n    return np.full(size, 1.0 / size)","handlingStrategy":"validation","validationCode":"import numpy as np\n\ndef safe_min_variance(optimizer, weights, covariance, size):\n    if covariance.size == 0 or not np.any(np.diag(covariance)) or np.any(np.isnan(covariance)):\n        return np.full(size, 1.0 / size)  # equal-weight fallback\n    return optimizer.optimize(weights, covariance)","typeGuard":"def covariance_is_valid(covariance: np.ndarray) -> bool:\n    return covariance.ndim == 2 and covariance.shape[0] == covariance.shape[1] and np.any(np.diag(covariance) > 0) and np.all(np.isfinite(covariance))","tryCatchPattern":null,"preventionTips":["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."],"tags":["portfolio-optimizer","numpy","scipy","covariance"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}