QuantConnect/Lean · error · AssertionError
Expected {self.expected_orders_count()} orders to have been
Error message
Expected {self.expected_orders_count()} orders to have been submitted and filled, half for buying the strategy and the other half for the liquidation. Actual {orders_count} What it means
This assertion compares the number of FILLED orders against expected_orders_count(), which a subclass defines as twice the number of strategy legs (one set to open, one set to liquidate). A mismatch means some legs were not filled, were filled twice, or the subclass's expected count constant is wrong relative to the strategy it trades. It runs in on_end_of_algorithm after the no-holdings check.
Source
Thrown at Algorithm.Python/OptionStrategyFactoryMethodsBaseAlgorithm.py:62
if not isinstance(buying_power_model, OptionStrategyPositionGroupBuyingPowerModel):
raise AssertionError("Expected position group buying power model type: OptionStrategyPositionGroupBuyingPowerModel. "
f"Actual: {type(position_group.buying_power_model).__name__}")
self.assert_strategy_position_group(position_group, self._option_symbol)
# Now we should be able to close the position
self.liquidate_strategy()
# We can quit now, no more testing required
self.quit()
def on_end_of_algorithm(self):
if self.portfolio.invested:
raise AssertionError("Expected no holdings at end of algorithm")
orders_count = len(list(self.transactions.get_orders(lambda order: order.status == OrderStatus.FILLED)))
if orders_count != self.expected_orders_count():
raise AssertionError(f"Expected {self.expected_orders_count()} orders to have been submitted and filled, "
f"half for buying the strategy and the other half for the liquidation. Actual {orders_count}")
def expected_orders_count(self) -> int:
raise NotImplementedError("ExpectedOrdersCount method is not implemented")
def trade_strategy(self, chain: OptionChain, option_symbol: Symbol) -> None:
raise NotImplementedError("TradeStrategy method is not implemented")
def assert_strategy_position_group(self, position_group: IPositionGroup, option_symbol: Symbol) -> None:
raise NotImplementedError("AssertStrategyPositionGroup method is not implemented")
def liquidate_strategy(self) -> None:
raise NotImplementedError("LiquidateStrategy method is not implemented")
View on GitHub (pinned to d2c3659f87)
Solutions
- Override expected_orders_count() in the subclass to return 2 * (number of legs in the traded strategy).
- Inspect self.transactions.get_orders(...) statuses to find non-FILLED (canceled/rejected/invalid) orders causing the shortfall.
- Confirm the strategy factory method produces the expected number of leg orders on both open and close.
- If a partial fill occurred, account for it in the expected count or ensure full fills before counting.
Example fix
# before: subclass uses base NotImplementedError or wrong count
# after: override for a 2-leg strategy
def expected_orders_count(self) -> int:
return 4 # 2 legs open + 2 legs liquidate Defensive patterns
Strategy: validation
Validate before calling
# Count filled orders and compare to expected only after all fills settle
filled = list(self.transactions.get_orders(lambda o: o.status == OrderStatus.FILLED))
expected = self.expected_orders_count()
if len(filled) != expected:
non_filled = [o for o in self.transactions.get_orders() if o.status != OrderStatus.FILLED]
raise AssertionError(f'filled={len(filled)} expected={expected} non_filled={non_filled}') Prevention
- Override expected_orders_count() as 2 * leg_count in every subclass.
- Inspect non-FILLED orders before asserting to find rejections.
- Confirm the strategy factory produces the expected number of leg orders.
- Account for partial fills in the expected count.
When it happens
Trigger: len(list(self.transactions.get_orders(lambda o: o.status == OrderStatus.FILLED))) != self.expected_orders_count(). Triggered by a leg order not reaching FILLED (rejected/canceled/partial), an extra order being submitted, or a subclass reporting the wrong expected count for its strategy's leg count.
Common situations: Subclassing for a strategy with a different number of legs but forgetting to override expected_orders_count(); a liquidation order that split into partial fills counted differently; a combo order that the engine expanded into a different number of child orders than expected.
Related errors
- Unexpected order event symbol!
- Expected position group buying power model type: OptionStrat
- Expected no holdings at end of algorithm
- ExpectedOrdersCount method is not implemented
- TradeStrategy method is not implemented
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/bb36b442727611d5.
Report an issue: GitHub.