QuantConnect/Lean · error · AssertionError

Expected no order events for underlying Symbol {security.sym

Error message

Expected no order events for underlying Symbol {security.symbol}

What it means

FutureOptionShortPutOTMExpiryRegressionAlgorithm.on_order_event asserts that no fill order event arrives for the future underlying symbol (es19m20). The regression shorts an OTM put on the ES future and expects only the option contract to transact; an order event on the underlying itself signals an unintended assignment/exercise of the future.

Source

Thrown at Algorithm.Python/FutureOptionShortPutOTMExpiryRegressionAlgorithm.py:82

            if delisting.type == DelistingType.WARNING:
                if delisting.time != datetime(2020, 6, 19):
                    raise AssertionError(f"Delisting warning issued at unexpected date: {delisting.time}")

            if delisting.type == DelistingType.DELISTED:
                if delisting.time != datetime(2020, 6, 20):
                    raise AssertionError(f"Delisting happened at unexpected date: {delisting.time}")

    def on_order_event(self, order_event: OrderEvent):
        if order_event.status != OrderStatus.FILLED:
            # There's lots of noise with OnOrderEvent, but we're only interested in fills.
            return

        if not self.securities.contains_key(order_event.symbol):
            raise AssertionError(f"Order event Symbol not found in Securities collection: {order_event.symbol}")

        security = self.securities[order_event.symbol]
        if security.symbol == self.es19m20:
            raise AssertionError(f"Expected no order events for underlying Symbol {security.symbol}")

        if security.symbol == self.expected_contract:
            self.assert_future_option_contract_order(order_event, security)

        else:
            raise AssertionError(f"Received order event for unknown Symbol: {order_event.symbol}")

        self.log(f"{order_event}")

    def assert_future_option_contract_order(self, order_event: OrderEvent, option_contract: Security):
        if order_event.direction == OrderDirection.SELL and option_contract.holdings.quantity != -1:
            raise AssertionError(f"No holdings were created for option contract {option_contract.symbol}")

        if order_event.direction == OrderDirection.BUY and option_contract.holdings.quantity != 0:
            raise AssertionError("Expected no options holdings after closing position")

        if order_event.is_assignment:
            raise AssertionError(f"Assignment was not expected for {order_event.symbol}")

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Verify the put is genuinely OTM at expiry in the test data (an ITM put would legitimately assign into the future).
  2. If you changed option assignment/exercise or expiration pipeline code, check whether it now incorrectly exercises OTM options.
  3. Confirm self.es19m20 is the correct expected underlying and that no other symbol aliases to it.
Defensive patterns

Strategy: validation

Validate before calling

# In on_order_event, ignore the underlying only when truly OTM; otherwise expect assignment
if order_event.status != OrderStatus.FILLED:
    return
if order_event.symbol == self.es19m20 and not self.put_is_it_at_expiry():
    raise AssertionError(f'Unexpected underlying fill: {order_event}')

Prevention

When it happens

Trigger: on_order_event receives a FILLED OrderEvent whose symbol equals self.es19m20 (the underlying future), which the test treats as an error because the underlying should never fill in this OTM-expiry scenario.

Common situations: Framework/expiration logic changed so the OTM option got assigned or auto-exercised into a future position; a margin/liquidation event forced an underlying trade; or data changes made the put ITM at expiry triggering assignment.

Related errors


AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13). Data as JSON: /api/errors/cb81bf5209ea0845. Report an issue: GitHub.