{"record":{"id":"95aabf258a3ac39a","repo":"QuantConnect/Lean","slug":"expiry-event-was-not-at-the-correct-time-orderev","errorCode":null,"errorMessage":"Expiry event was not at the correct time, {orderEvent.UtcTime}","messagePattern":"Expiry event was not at the correct time, (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs","lineNumber":96,"sourceCode":"            }\n        }\n\n        /// <summary>\n        /// Order fill event handler. On an order fill update the resulting information is passed to this method.\n        /// </summary>\n        /// <param name=\"orderEvent\">Order event details containing details of the events</param>\n        /// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks>\n        public override void OnOrderEvent(OrderEvent orderEvent)\n        {\n            Log(orderEvent.ToString());\n\n            // 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>","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/BasicTemplateOptionsDailyAlgorithm.cs#L78-L114","documentation":"Thrown in OnOrderEvent when an OTM option-expiration order event has a UtcTime that is not exactly 2016-01-16 05:00:00 UTC. The assertion verifies that option expiry processing fires at the correct time (midnight Eastern = 05:00 UTC for daily-resolution options). A time mismatch indicates the expiry scheduler or timezone conversion changed.","triggerScenarios":"The Lean engine's option-expiry timing logic changed, the algorithm's time zone is configured differently, daylight saving time boundaries shifted the UTC offset, or the option data's expiry date was modified.","commonSituations":"Engine refactoring of the OptionExerciseProcess or expiry scheduling, timezone database updates, changes to how daily-resolution options compute their expiration timestamp, or data file modifications to the AAPL option expiry date.","solutions":["Verify the AAPL option contract expiry date in the data matches 2016-01-15 (expiration processed the following midnight/early morning).","Check the algorithm's SetTimeZone — for daily options the expiry is processed at midnight exchange time.","Inspect the OptionExerciseProcess or expiry event generation code for timing changes.","Log orderEvent.UtcTime alongside the expected value to identify the exact offset difference.","Confirm daylight saving time status for the date (January = EST = UTC-5, so midnight EST = 05:00 UTC)."],"exampleFix":"// before\nif (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// after — compute expected from exchange timezone for robustness\nvar expectedExpiryUtc = new DateTime(2016, 1, 16, 5, 0, 0);\nLog($\"Expiry event UtcTime: {orderEvent.UtcTime}, Expected: {expectedExpiryUtc}\");\nif (orderEvent.UtcTime != expectedExpiryUtc)\n{\n    throw new ArgumentException($\"Expiry event was not at the correct time, {orderEvent.UtcTime}\");\n}","handlingStrategy":"validation","validationCode":"// Validate expiry timing before asserting\nvar expectedUtc = new DateTime(2016, 1, 16, 5, 0, 0);\nif (orderEvent.Message.Contains(\"OTM\") && orderEvent.UtcTime != expectedUtc)\n{\n    Log($\"Expiry timing off: got {orderEvent.UtcTime} (kind={orderEvent.UtcTime.Kind}), expected {expectedUtc}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Document the expected UTC expiry time and its derivation (exchange midnight + UTC offset).","Log all OTM-related order events with full UtcTime to build a trace.","Verify the option contract expiry date in data matches the expected date.","Check for daylight saving time transitions that affect the UTC offset."],"tags":["quantconnect","options","expiration","timezone","utc","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}