{"record":{"id":"ed6452812b438899","repo":"QuantConnect/Lean","slug":"algorithm-did-not-process-the-option-expiration-li","errorCode":null,"errorMessage":"Algorithm did not process the option expiration like expected","messagePattern":"Algorithm did not process the option expiration like expected","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs","lineNumber":108,"sourceCode":"            // Check for our expected OTM option expiry\n            if (orderEvent.Message.Contains(\"OTM\", StringComparison.InvariantCulture))\n            {\n                // Assert it is at midnight (5AM UTC)\n                if (orderEvent.UtcTime != new DateTime(2016, 1, 16, 5, 0, 0))\n                {\n                    throw new ArgumentException($\"Expiry event was not at the correct time, {orderEvent.UtcTime}\");\n                }\n\n                _optionExpired = true;\n            }\n        }\n\n        public override void OnEndOfAlgorithm()\n        {\n            // Assert we had our option expire and fill a liquidation order\n            if (_optionExpired != true)\n            {\n                throw new ArgumentException(\"Algorithm did not process the option expiration like expected\");\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, Language.Python };\n\n        /// <summary>\n        /// Data Points count of all timeslices of algorithm\n        /// </summary>\n        public long DataPoints => 308;\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs#L90-L126","documentation":"Thrown in OnEndOfAlgorithm when _optionExpired was never set to true. The flag is set inside OnOrderEvent when an order event message contains 'OTM' (out-of-the-money expiration). If no such event fires, the option expiration was not processed by the engine during the algorithm's lifetime.","triggerScenarios":"The option contract did not expire within the backtest date range (2015-12-15 to 2016-02-01), the expiration event's message does not contain 'OTM', the contract was not held to expiration, or the engine failed to generate the expiration order event.","commonSituations":"Option contract selection logic changes (contract picked has a different expiry), message format changes in the expiration event, the contract was liquidated before expiry, or engine-level option-expiry event generation is broken.","solutions":["Verify the selected option contract expires within the backtest window (log contract.Expiry in OnData).","Ensure the algorithm holds the contract to expiration (no premature Liquidate call).","Check OnOrderEvent for all event messages to confirm whether an OTM expiration event fires at all.","Inspect the Lean engine's option-expiration event message format for changes to the 'OTM' string.","Log every orderEvent.Message to trace the full event sequence."],"exampleFix":"// before — no visibility into event sequence\npublic override void OnOrderEvent(OrderEvent orderEvent)\n{\n    if (orderEvent.Message.Contains(\"OTM\"))\n    {\n        _optionExpired = true;\n    }\n}\n\n// after — log all events for diagnosis\npublic override void OnOrderEvent(OrderEvent orderEvent)\n{\n    Log($\"OrderEvent: status={orderEvent.Status} msg='{orderEvent.Message}' time={orderEvent.UtcTime}\");\n    if (orderEvent.Message.Contains(\"OTM\"))\n    {\n        _optionExpired = true;\n    }\n}","handlingStrategy":"validation","validationCode":"// Log all order events to trace expiration processing\npublic override void OnOrderEvent(OrderEvent orderEvent)\n{\n    Log($\"OrderEvent: status={orderEvent.Status} symbol={orderEvent.Symbol} msg='{orderEvent.Message}' time={orderEvent.UtcTime}\");\n}\n\n// In OnEndOfAlgorithm, check flag with diagnostics\nif (_optionExpired != true)\n{\n    Log(\"Option expiration was not processed — review OnOrderEvent log for expiry events\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Log every OrderEvent message in OnOrderEvent to build an audit trail.","Verify the selected option contract expires within the backtest window.","Ensure no premature Liquidate() closes the position before expiry.","Check the engine's option-expiry message format for the 'OTM' keyword."],"tags":["quantconnect","options","expiration","order-event","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}