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

  1. Enlarge the lookback/period so the covariance has real dispersion.
  2. Filter out symbols with zero return variance (np.std of returns == 0) before constructing the covariance.
  3. Verify the returns DataFrame used for covariance is non-empty and finite.
  4. 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

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


AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13). Data as JSON: /api/errors/9925c219cd5cf3d1. Report an issue: GitHub.