{"record":{"id":"38e6fdcc45a586d0","repo":"QuantConnect/Lean","slug":"utctime-we-hold-a-delisted-securities-string","errorCode":null,"errorMessage":"[{UtcTime}] We hold a delisted securities: {string.Join(\",\", delistedSecurity)}","messagePattern":"\\[(.+?)\\] We hold a delisted securities: (.+?)","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"critical","filePath":"Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs","lineNumber":63,"sourceCode":"            // This is required to prevent the algorithm from automatically delisting the underlying. Without this, future options will be subscribed\n            // with resolution default to Minute insted of this.Resolution. This could be replaced after GH issue #6491 is implemented.\n            UniverseSettings.Resolution = Resolution;\n        }\n\n        public override void OnData(Slice slice)\n        {\n            if (Time.Month != _lastMonth)\n            {\n                _lastMonth = Time.Month;\n                var investedSymbols = Securities.Values\n                    .Where(security => security.Invested)\n                    .Select(security => security.Symbol)\n                    .ToList();\n\n                var delistedSecurity = investedSymbols.Where(symbol => symbol.ID.Date.AddDays(1) < Time).ToList();\n                if (delistedSecurity.Count > 0)\n                {\n                    throw new RegressionTestException($\"[{UtcTime}] We hold a delisted securities: {string.Join(\",\", delistedSecurity)}\");\n                }\n                Log($\"Holdings({Time}): {string.Join(\",\", investedSymbols)}\");\n            }\n\n            if (Portfolio.Invested)\n            {\n                return;\n            }\n\n            foreach (var chain in slice.OptionChains.Values)\n            {\n                foreach (var contractsValue in chain.Contracts.Values)\n                {\n                    MarketOrder(contractsValue.Symbol, 1);\n                    _traded = true;\n                }\n            }\n        }","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs#L45-L81","documentation":"Once per month, the algorithm lists all invested securities and flags any whose contract expiry date (symbol.ID.Date) + 1 day is earlier than the current algorithm time. If any delisted/expired contract is still held in the portfolio, the regression fails — Lean should have liquidated or rolled the position at expiry.","triggerScenarios":"Holding a future or future-option position past its expiry/settlement date without Lean's automatic delisting handling closing it. Occurs when delisting processing is delayed, when the position is reopened after expiry, or when symbol.ID.Date is misinterpreted relative to Time.","commonSituations":"A Lean bug where future-option or future delisting does not liquidate on the expiry day, timezone mismatches between symbol.ID.Date and algorithm Time, or a contract-roll logic gap that leaves a stale position.","solutions":["Inspect the logged Holdings line for the previous month to see which symbol persisted past expiry.","Verify Lean's delisting/automatic-position-close logic runs for future options on the expiry date.","Check for a timezone offset: symbol.ID.Date is date-only, so compare against Time.Date rather than AddDays(1) < Time if timezone handling changed.","Ensure the algorithm does not re-enter a position in a symbol that has already expired within the same month window."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var delistedSecurity = investedSymbols\n    .Where(symbol => symbol.ID.Date.AddDays(1) < Time)\n    .ToList();\nif (delistedSecurity.Count > 0)\n{\n    // Log before throwing so the stale position is visible\n    Log($\"Stale positions past expiry: {string.Join(\",\", delistedSecurity)}\");\n    Liquidate(delistedSecurity); // defensive cleanup\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Liquidate positions before contract expiry rather than relying solely on automatic delisting.","Log holdings monthly to detect stale positions early.","Compare expiry dates against algorithm Time.Date to avoid timezone off-by-one."],"tags":["quantconnect","futures","future-options","delisting","position-management","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}