QuantConnect/Lean · error · AssertionError

Expected no options holdings after closing position

Error message

Expected no options holdings after closing position

What it means

In assert_future_option_contract_order, after a BUY fill (closing the short put) the option holdings must be flat (quantity == 0). A non-zero quantity means the close didn't fully flatten the position, leaving residual option exposure.

Source

Thrown at Algorithm.Python/FutureOptionShortPutOTMExpiryRegressionAlgorithm.py:97

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

    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. Ensure the closing buy order quantity equals the open short quantity (1 contract here).
  2. Look for intermediate fills that changed the position size before the close.
  3. Verify no auto-exercise/assignment altered holdings between open and close.
Defensive patterns

Strategy: validation

Validate before calling

# Before the close, verify the open short size and submit a matching close
open_qty = abs(option_contract.holdings.quantity)
if open_qty > 0:
    self.market_order(option_contract.symbol, open_qty)  # close

Prevention

When it happens

Trigger: An OrderEvent with direction == OrderDirection.BUY fills but option_contract.holdings.quantity != 0 — e.g., the buy only partially closed a -2 position, or an extra contract was opened.

Common situations: Closing order quantity mismatched the open position, partial fill, or a second contract was opened instead of closing the existing one.

Related errors


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