QuantConnect/Lean · error · AssertionError

Assignment was not expected for {order_event.symbol}

Error message

Assignment was not expected for {order_event.symbol}

What it means

In assert_future_option_contract_order, an OTM short put expiring worthless must NOT be assigned. If order_event.is_assignment is true, the regression treats it as an error — the option was assigned when the test's scenario expects it to expire worthless.

Source

Thrown at Algorithm.Python/FutureOptionShortPutOTMExpiryRegressionAlgorithm.py:100

            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}")

    def on_end_of_algorithm(self):
        if self.portfolio.invested:
            raise AssertionError(f"Expected no holdings at end of algorithm, but are invested in: {', '.join([str(i.id) for i in self.portfolio.keys()])}")

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm the put is genuinely OTM relative to the underlying at expiry in the current data.
  2. If you modified the option assignment/exercise or pricing model, verify OTM options are not assigned.
  3. Check the strike vs underlying settlement price for the test contract.
Defensive patterns

Strategy: validation

Validate before calling

# Compute moneyness at expiry to decide whether assignment is valid
underlying_price = self.securities[self.es19m20].price
is_itm = underlying_price < self.put_strike  # short put ITM if underlying < strike
if order_event.is_assignment and not is_itm:
    raise AssertionError(f'OTM put assigned: underlying={underlying_price}, strike={self.put_strike}')

Prevention

When it happens

Trigger: An OrderEvent with is_assignment == True reaches the assertion. Assignment of an OTM put at expiry indicates the option was treated as ITM, or the assignment pipeline fired incorrectly.

Common situations: Data/pricing change made the put ITM near expiry; the auto-exercise threshold logic changed; or expiration/assignment pipeline was modified to over-assign.

Related errors


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