{"record":{"id":"ab5f9813b82e52d6","repo":"QuantConnect/Lean","slug":"portfolio-should-have-the-stock","errorCode":null,"errorMessage":"Portfolio should have the stock","messagePattern":"Portfolio should have the stock","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs","lineNumber":199,"sourceCode":"            {\n                throw new RegressionTestException(\"Order was not canceled\");\n            }\n\n            var openOrders = Transactions.GetOpenOrders();\n            if (openOrders.Count != 0)\n            {\n                throw new RegressionTestException(\"There should be no open orders\");\n            }\n\n            if (!Portfolio.Invested)\n            {\n                throw new RegressionTestException(\"Portfolio should be invested\");\n            }\n\n            // We should have the stock since the option was assigned\n            if (Portfolio.Positions.Groups.Single().Single().Symbol != _stock)\n            {\n                throw new RegressionTestException(\"Portfolio should have the stock\");\n            }\n        }\n\n        /// <summary>\n        /// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.\n        /// </summary>\n        public bool CanRunLocally { get; } = true;\n\n        /// <summary>\n        /// This is used by the regression test system to indicate which languages this algorithm is written in.\n        /// </summary>\n        public List<Language> Languages { get; } = new() { Language.CSharp };\n\n        /// <summary>\n        /// Data Points count of all timeslices of algorithm\n        /// </summary>\n        public long DataPoints => 2850;\n","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs#L181-L217","documentation":"Asserts the final portfolio contains exactly one position group with exactly one position whose symbol is _stock. It uses Positions.Groups.Single().Single(). This enforces that the only thing left in the portfolio is the assigned stock. A failure means either there is more than one group/position, or the single position is not the stock symbol.","triggerScenarios":"Multiple position groups remain (option + stock), or the lone position is a different symbol. The delisting did not remove the option from the portfolio.","commonSituations":"The option position was not removed after delisting (extra position remains); the stock symbol SID does not match _stock; a duplicate security lingers; .Single() throws InvalidOperationException (which surfaces differently) when there are zero or multiple.","solutions":["Enumerate Portfolio.Positions and each group's positions to see what remains besides the stock.","Confirm the option position was removed when the option delisted.","Check that _stock SID equality holds against the delivered position symbol."],"exampleFix":"// before\nif (Portfolio.Positions.Groups.Single().Single().Symbol != _stock)\n{\n    throw new RegressionTestException(\"Portfolio should have the stock\");\n}\n\n// after (enumerate to avoid Single() masking the real state)\nvar positions = Portfolio.Positions.Groups.SelectMany(g => g).ToList();\nif (positions.Count != 1 || positions[0].Symbol != _stock)\n{\n    throw new RegressionTestException(\n        $\"Portfolio should have only the stock. Got: {string.Join(\", \", positions.Select(p => p.Symbol))}\");\n}","handlingStrategy":"validation","validationCode":"var positions = Portfolio.Positions.Select(p => (p.Symbol, p.Quantity)).ToList();\nif (positions.Count != 1 || positions[0].Symbol != _stock)\n{\n    foreach (var p in positions) Log($\"Position: {p.Symbol} qty={p.Quantity}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid .Single().Single() chains that throw InvalidOperationException before your message runs; enumerate first.","Log every remaining position so leftover option positions are visible.","Confirm delisting removes the option from Portfolio.Positions."],"tags":["quantconnect","lean","regression-test","portfolio","position-groups","postcondition"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}