{"record":{"id":"7b57502d8cf56def","repo":"QuantConnect/Lean","slug":"the-exchange-hours-was-closed-verify-extended-ma","errorCode":null,"errorMessage":"The Exchange hours was closed, verify 'extended_market_hours' flag in Initialize() when added new security(ies)","messagePattern":"The Exchange hours was closed, verify 'extended_market_hours' flag in Initialize\\(\\) when added new security\\(ies\\)","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/FutureStopMarketOrderOnExtendedHoursRegressionAlgorithm.py","lineNumber":63,"sourceCode":"    def on_data(self, slice: Slice) -> None:\n        if (self._stop_market_ticket == None or self._stop_market_ticket.status != OrderStatus.SUBMITTED):\n            return None\n\n        self.stop_price = self._stop_market_ticket.get(OrderField.STOP_PRICE)\n        self.bar = self.securities[self._stop_market_ticket.symbol].cache.get_data()\n\n    # An order fill update the resulting information is passed to this method.\n    def on_order_event(self, order_event: OrderEvent) -> None:\n        if self.transactions.get_order_by_id(order_event.order_id).type is not OrderType.STOP_MARKET:\n            return None\n\n        if order_event.status == OrderStatus.FILLED:\n            # Get Exchange Hours for specific security\n            exchange_hours = self.market_hours_database.get_exchange_hours(self._sp_500_e_mini.subscription_data_config)\n\n            # Validate, Exchange is opened explicitly\n            if (not exchange_hours.is_open(order_event.utc_time, self._sp_500_e_mini.is_extended_market_hours)):\n                raise AssertionError(\"The Exchange hours was closed, verify 'extended_market_hours' flag in Initialize() when added new security(ies)\")\n\n    def on_end_of_algorithm(self) -> None:\n        self.stop_market_orders = self.transactions.get_orders(lambda o: o.type is OrderType.STOP_MARKET)\n\n        for o in self.stop_market_orders:\n            if o.status != OrderStatus.FILLED:\n                raise AssertionError(\"The Algorithms was not handled any StopMarketOrders\")\n","sourceCodeStart":45,"sourceCodeEnd":71,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/FutureStopMarketOrderOnExtendedHoursRegressionAlgorithm.py#L45-L71","documentation":"Assertion in on_order_event of a future stop-market-order regression. After a STOP_MARKET order fills, the test fetches the security's exchange-hours entry from market_hours_database and calls is_open(order_event.utc_time, is_extended_market_hours). If the fill timestamp falls outside the declared open session the test aborts. Its purpose is to prove the extended_market_hours=True flag on add_future actually allowed fills in extended hours.","triggerScenarios":"A stop-market fill whose utc_time lands in a session gap; extended_market_hours being False (or defaulting) while the test expects extended-hours fills; a market_hours_database entry for the ES CME future that does not mark the extended window as open; fill timestamp timezone/mapping drift.","commonSituations":"Forgetting to pass extended_market_hours=True in add_future; updating MarketHoursDatabase entries for CME that narrow the extended session; data-driven fills landing exactly on a session boundary that is_open treats as closed; timezone handling changes in the engine.","solutions":["Ensure add_future(..., extended_market_hours=True) is set for the security whose fills are asserted.","Check the MarketHoursDatabase entry for the symbol's market (CME) covers the extended hours window containing order_event.utc_time.","Log order_event.utc_time and the exchange_hours output to confirm whether the gap is real or a TZ bug.","If the database entry changed intentionally, update the regression's expected fill window rather than the assertion."],"exampleFix":"// before\nself._sp_500_e_mini = self.add_future(Futures.Indices.SP_500_E_MINI, Resolution.MINUTE)\n// after\nself._sp_500_e_mini = self.add_future(Futures.Indices.SP_500_E_MINI, Resolution.MINUTE, extended_market_hours=True)","handlingStrategy":"validation","validationCode":"# Pre-check exchange hours before asserting on a fill\nexchange_hours = self.market_hours_database.get_exchange_hours(\n    self._sp_500_e_mini.subscription_data_config)\nif not exchange_hours.is_open(order_event.utc_time, self._sp_500_e_mini.is_extended_market_hours):\n    self.debug(f\"Fill at {order_event.utc_time} outside open session; investigate hours DB\")","typeGuard":"def is_fill_session_open(mhdb, security, utc_time: datetime) -> bool:\n    eh = mhdb.get_exchange_hours(security.subscription_data_config)\n    return eh.is_open(utc_time, security.is_extended_market_hours)","tryCatchPattern":null,"preventionTips":["Always pass extended_market_hours=True to add_future when extended fills are expected.","Cross-check the MarketHoursDatabase entry for the symbol's market.","Log order_event.utc_time alongside is_open results when debugging.","Normalize timezones before comparing fill time against session windows."],"tags":["quantconnect","futures","stop-market-order","extended-market-hours","market-hours-database","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}