{"record":{"id":"28ad32102770795c","repo":"QuantConnect/Lean","slug":"assignment-was-not-expected-for-order-event-symbo","errorCode":null,"errorMessage":"Assignment was not expected for {order_event.symbol}","messagePattern":"Assignment was not expected for (.+?)","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/FutureOptionShortPutOTMExpiryRegressionAlgorithm.py","lineNumber":100,"sourceCode":"            raise AssertionError(f\"Expected no order events for underlying Symbol {security.symbol}\")\n\n        if security.symbol == self.expected_contract:\n            self.assert_future_option_contract_order(order_event, security)\n\n        else:\n            raise AssertionError(f\"Received order event for unknown Symbol: {order_event.symbol}\")\n\n        self.log(f\"{order_event}\")\n\n    def assert_future_option_contract_order(self, order_event: OrderEvent, option_contract: Security):\n        if order_event.direction == OrderDirection.SELL and option_contract.holdings.quantity != -1:\n            raise AssertionError(f\"No holdings were created for option contract {option_contract.symbol}\")\n\n        if order_event.direction == OrderDirection.BUY and option_contract.holdings.quantity != 0:\n            raise AssertionError(\"Expected no options holdings after closing position\")\n\n        if order_event.is_assignment:\n            raise AssertionError(f\"Assignment was not expected for {order_event.symbol}\")\n\n    def on_end_of_algorithm(self):\n        if self.portfolio.invested:\n            raise AssertionError(f\"Expected no holdings at end of algorithm, but are invested in: {', '.join([str(i.id) for i in self.portfolio.keys()])}\")\n","sourceCodeStart":82,"sourceCodeEnd":105,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/FutureOptionShortPutOTMExpiryRegressionAlgorithm.py#L82-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"Data/pricing change made the put ITM near expiry; the auto-exercise threshold logic changed; or expiration/assignment pipeline was modified to over-assign.","solutions":["Confirm the put is genuinely OTM relative to the underlying at expiry in the current data.","If you modified the option assignment/exercise or pricing model, verify OTM options are not assigned.","Check the strike vs underlying settlement price for the test contract."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Compute moneyness at expiry to decide whether assignment is valid\nunderlying_price = self.securities[self.es19m20].price\nis_itm = underlying_price < self.put_strike  # short put ITM if underlying < strike\nif order_event.is_assignment and not is_itm:\n    raise AssertionError(f'OTM put assigned: underlying={underlying_price}, strike={self.put_strike}')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Encode the ITM condition explicitly so the test fails with a clear moneyness message instead of a bare assignment error.","When modifying the exercise/assignment pipeline, re-run OTM-expiry regressions to catch over-assignment."],"tags":["regression-test","future-options","assignment","exercise"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}