{"record":{"id":"cdad2310e79637a5","repo":"QuantConnect/Lean","slug":"total-must-be-0-for-euclidean-projection-onto-th","errorCode":null,"errorMessage":"Total must be > 0 for Euclidean Projection onto the Simplex.","messagePattern":"Total must be > 0 for Euclidean Projection onto the Simplex\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Algorithm.Framework/Portfolio/MeanReversionPortfolioConstructionModel.py","lineNumber":165,"sourceCode":"\n        for symbol in symbols:\n            if symbol not in self.symbol_data:\n                self.symbol_data[symbol] = self.MeanReversionSymbolData(algorithm, symbol, self.window_size, self.resolution)\n\n    def SimplexProjection(self, vector, total=1):\n        \"\"\"Normalize the updated portfolio into weight vector:\n        v_{t+1} = arg min || v - v_{t+1} || ^ 2\n        Implementation from:\n        Duchi, J., Shalev-Shwartz, S., Singer, Y., & Chandra, T. (2008, July). \n            Efficient projections onto the l 1-ball for learning in high dimensions.\n            In Proceedings of the 25th international conference on Machine learning \n            (pp. 272-279).\n        Args:\n            vector: unnormalized weight vector\n            total: total weight of output, default to be 1, making it a probabilistic simplex\n        \"\"\"\n        if total <= 0:\n            raise ArgumentException(\"Total must be > 0 for Euclidean Projection onto the Simplex.\")\n            \n        vector = np.asarray(vector)\n\n        # Sort v into u in descending order\n        mu = np.sort(vector)[::-1]\n        sv = np.cumsum(mu)\n\n        rho = np.where(mu > (sv - total) / np.arange(1, len(vector) + 1))[0][-1]\n        theta = (sv[rho] - total) / (rho + 1)\n        w = (vector - theta)\n        w[w < 0] = 0\n        return w\n\n    class MeanReversionSymbolData:\n        def __init__(self, algo, symbol, window_size, resolution):\n            # Indicator of price\n            self.Identity = algo.Identity(symbol, resolution)\n            # Moving average indicator for mean reversion level","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Framework/Portfolio/MeanReversionPortfolioConstructionModel.py#L147-L183","documentation":"MeanReversionPortfolioConstructionModel.normalize() projects a weight vector onto the L1 simplex (sum-to-total) via the Duchi et al. algorithm. A non-positive 'total' makes the projection undefined (it cannot normalize onto a negative/zero-mass simplex), so it raises ArgumentException before running the sort/cumsum logic.","triggerScenarios":"normalize(vector, total) is called with total <= 0. In normal use total defaults to 1; this fires only if a caller overrides total with zero or a negative number, or passes a degenerate budget.","commonSituations":"Subclass overriding normalize() and forwarding a computed total that became 0/negative (e.g., a sum of signed targets that cancelled out), or passing a budget parameter derived from total portfolio value when that value is zero/under-margin.","solutions":["Do not override the 'total' argument; let it default to 1 so weights sum to 100%.","If computing total dynamically, clamp/guard it to a positive minimum before calling normalize().","Ensure the algorithm has positive total portfolio value / budget before rebalancing."],"exampleFix":"# before\ntotal = sum_of_signed_targets  # could be <= 0\nw = self.normalize(vector, total)\n\n# after\ntotal = sum_of_signed_targets\nif total <= 0:\n    raise ValueError('normalize requires positive total')\nw = self.normalize(vector, total)","handlingStrategy":"validation","validationCode":"def safe_normalize(model, vector, total=1):\n    if total is None or total <= 0:\n        total = 1.0\n    return model.normalize(vector, total)","typeGuard":"def valid_total(total) -> bool:\n    return isinstance(total, (int, float)) and total > 0","tryCatchPattern":null,"preventionTips":["Don't override the 'total' argument unless you understand the simplex projection.","Keep total portfolio value positive before rebalancing so any derived budget stays positive."],"tags":["portfolio-construction","linear-algebra","numpy","validation"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}