{"record":{"id":"30c0a387b719b437","repo":"QuantConnect/Lean","slug":"delisting-notice-received-at-an-unexpected-date","errorCode":null,"errorMessage":"Delisting notice received at an unexpected date: {self.time} - expected {delisting.time}","messagePattern":"Delisting notice received at an unexpected date: (.+?) - expected (.+?)","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.py","lineNumber":66,"sourceCode":"\n        self.es_future = self.add_future_contract(es, Resolution.MINUTE).symbol\n        self.es_future_option = self.add_future_option_contract(es_option, Resolution.MINUTE).symbol\n\n    def on_data(self, data: Slice):\n        for delisting in data.delistings.values():\n            self.delistings_received += 1\n\n            if delisting.type == DelistingType.WARNING and delisting.time != self.expected_expiry_warning_time:\n                raise AssertionError(f\"Expiry warning with time {delisting.time} but is expected to be {self.expected_expiry_warning_time}\")\n\n            if delisting.type == DelistingType.WARNING and delisting.time != datetime(self.time.year, self.time.month, self.time.day):\n                raise AssertionError(f\"Delisting warning received at an unexpected date: {self.time} - expected {delisting.time}\")\n\n            if delisting.type == DelistingType.DELISTED and delisting.time != self.expected_expiry_delisting_time:\n                raise AssertionError(f\"Delisting occurred at unexpected time: {delisting.time} - expected: {self.expected_expiry_delisting_time}\")\n\n            if delisting.type == DelistingType.DELISTED and delisting.time != datetime(self.time.year, self.time.month, self.time.day):\n                raise AssertionError(f\"Delisting notice received at an unexpected date: {self.time} - expected {delisting.time}\")\n\n        if not self.invested and \\\n            (self.es_future in data.bars or self.es_future in data.quote_bars) and \\\n            (self.es_future_option in data.bars or self.es_future_option in data.quote_bars):\n\n            self.invested = True\n\n            self.market_order(self.es_future, 1)\n            self.market_order(self.es_future_option, 1)\n\n    def on_order_event(self, order_event: OrderEvent):\n        if order_event.direction != OrderDirection.SELL or order_event.status != OrderStatus.FILLED:\n            return\n\n        # * Future Liquidation\n        # * Future Option Exercise\n        # * We expect NO Underlying Future Liquidation because we already hold a Long future position so the FOP Put selling leaves us breakeven\n        self.liquidated += 1","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/FuturesAndFuturesOptionsExpiryTimeAndLiquidationRegressionAlgorithm.py#L48-L84","documentation":"Second DELISTED check: delisting.time must also equal datetime(self.time.year, self.time.month, self.time.day). It ensures the delisting notice and the algorithm's current bar share the same calendar day.","triggerScenarios":"delisting.time and self.time disagree on the calendar day (timezone skew); the delisting notice arriving in a backtest bar from a different day than the notice timestamp; fill-forward artefacts.","commonSituations":"Timezone differences between the delisting timestamp and algorithm time; engine changes to when delisting notices are processed; data refreshes shifting notice timing.","solutions":["Print delisting.time and self.time with tz info to find the day skew.","Normalize both to the same timezone before comparing.","Confirm the engine processes the delisting notice in the bar whose date matches.","Update the assertion if notice-processing timing intentionally changed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Cross-check delisted day against algorithm day\nif delisting.type == DelistingType.DELISTED:\n    if delisting.time.date() != self.time.date():\n        self.debug(f\"Delisted day {delisting.time.date()} != algo day {self.time.date()}\")","typeGuard":"def delisted_on_current_day(delisting, algo_time: datetime) -> bool:\n    return delisting.type == DelistingType.DELISTED and delisting.time.date() == algo_time.date()","tryCatchPattern":null,"preventionTips":["Compare dates in a single timezone.","Log both timestamps with tz info when debugging.","Confirm the engine processes the notice in the matching bar.","Re-baseline after engine notice-processing changes."],"tags":["quantconnect","futures","future-options","delisting","timezone","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}