QuantConnect/Lean · error · AssertionError
At {Time}, {_es.symbol} is either in regular hours but curre
Error message
At {Time}, {_es.symbol} is either in regular hours but current time is in extended hours, or viceversa What it means
Intraday hours-consistency assertion in an extended-market-hours regression. For the ES future (extended hours enabled) the test computes whether the engine considers the time regular vs extended (via exchange.hours.is_open) and compares against a hard-coded clock-time breakdown of the CME session. Any disagreement aborts.
Source
Thrown at Algorithm.Python/FuturesExtendedMarketHoursRegressionAlgorithm.py:59
slice_symbols.update([x.canonical for x in slice_symbols])
es_is_in_regular_hours = self._es.exchange.hours.is_open(self.time, False)
es_is_in_extended_hours = not es_is_in_regular_hours and self._es.exchange.hours.is_open(self.time, True)
slice_has_e_s_data = self._es.symbol in slice_symbols
self._es_ran_on_regular_hours |= es_is_in_regular_hours and slice_has_e_s_data
self._es_ran_on_extended_hours |= es_is_in_extended_hours and slice_has_e_s_data
gc_is_in_regular_hours = self._gc.exchange.hours.is_open(self.time, False)
gc_is_in_extended_hours = not gc_is_in_regular_hours and self._gc.exchange.hours.is_open(self.time, True)
slice_has_g_c_data = self._gc.symbol in slice_symbols
self._gc_ran_on_regular_hours |= gc_is_in_regular_hours and slice_has_g_c_data
self._gc_ran_on_extended_hours |= gc_is_in_extended_hours and slice_has_g_c_data
time_of_day = self.time.time()
current_time_is_regular_hours = (time_of_day >= time(9, 30, 0) and time_of_day < time(16, 15, 0)) or (time_of_day >= time(16, 30, 0) and time_of_day < time(17, 0, 0))
current_time_is_extended_hours = not current_time_is_regular_hours and (time_of_day < time(9, 30, 0) or time_of_day >= time(18, 0, 0))
if es_is_in_regular_hours != current_time_is_regular_hours or es_is_in_extended_hours != current_time_is_extended_hours:
raise AssertionError("At {Time}, {_es.symbol} is either in regular hours but current time is in extended hours, or viceversa")
def on_end_of_algorithm(self):
if not self._es_ran_on_regular_hours:
raise AssertionError(f"Algorithm should have run on regular hours for {self._es.symbol} future, which enabled extended market hours")
if not self._es_ran_on_extended_hours:
raise AssertionError(f"Algorithm should have run on extended hours for {self._es.symbol} future, which enabled extended market hours")
if not self._gc_ran_on_regular_hours:
raise AssertionError(f"Algorithm should have run on regular hours for {self._gc.symbol} future, which did not enable extended market hours")
if self._gc_ran_on_extended_hours:
raise AssertionError(f"Algorithm should have not run on extended hours for {self._gc.symbol} future, which did not enable extended market hours")
View on GitHub (pinned to d2c3659f87)
Solutions
- Print self.time (with tz), es_is_in_regular_hours, and current_time_is_regular_hours to find the disagreement.
- Cross-check the MarketHoursDatabase entry for ES against the hard-coded windows.
- Update the hard-coded time windows if CME hours legitimately changed.
- Ensure self.time is in the timezone the hard-coded windows assume.
Defensive patterns
Strategy: validation
Validate before calling
# Cross-check engine hours classification vs clock-time windows
tod = self.time.time()
reg = (time(9,30) <= tod < time(16,15)) or (time(16,30) <= tod < time(17,0))
ext = not reg and (tod < time(9,30) or tod >= time(18,0))
if self._es.exchange.hours.is_open(self.time, False) != reg:
self.debug(f"Hours DB disagrees with clock-time regular window at {self.time}") Type guard
def engine_matches_clock_window(security, t: datetime) -> bool:
tod = t.time()
reg = (time(9,30) <= tod < time(16,15)) or (time(16,30) <= tod < time(17,0))
return security.exchange.hours.is_open(t, False) == reg Prevention
- Keep the hard-coded session windows in sync with MarketHoursDatabase.
- Compare self.time and is_open output in the same timezone.
- Log disagreements before raising.
- Update windows when CME session definitions change.
When it happens
Trigger: MarketHoursDatabase entry for CME ES disagreeing with the hard-coded 09:30-16:15 / 16:30-17:00 / pre-09:30 / post-18:00 windows; self.time timezone differing from the hard-coded times; engine changes to is_open semantics.
Common situations: Updates to MarketHoursDatabase that shift the ES session boundaries; timezone handling changes; new fill-forward behaviour crossing session edges; the hard-coded window being stale relative to current CME hours.
Related errors
- The Exchange hours was closed, verify 'extended_market_hours
- Delisting warning received at an unexpected date: {self.time
- Delisting notice received at an unexpected date: {self.time}
- Algorithm should have run on regular hours for {self._es.sym
- Algorithm should have run on extended hours for {self._es.sy
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/c04d9acdc6bd4c88.
Report an issue: GitHub.