QuantConnect/Lean · error · AssertionError
Expected the portfolio to have holdings and to have {self.tr
Error message
Expected the portfolio to have holdings and to have {self.trade_count} trades, but had {self.transactions.orders_count} What it means
On algorithm end, OrderTicketAssignmentDemoAlgorithm asserts the portfolio holds a position (self.portfolio.invested) and that the number of orders submitted equals the number of trades the consolidator fired (self.trade_count == self.transactions.orders_count). A failure means either no position was ever opened (orders not filled) or the order count diverged (orders duplicated, rejected, or the consolidator fired a different number of times than expected).
Source
Thrown at Algorithm.Python/OrderTicketAssignmentDemoAlgorithm.py:53
self.ticket = self.market_order(self._symbol, 1, asynchronous=True)
self.debug(f"{self.time}: Buy: Price {bar.price}, order_id: {self.ticket.order_id}")
self.trade_count += 1
def on_order_event(self, order_event: OrderEvent):
# We cannot access self.ticket directly because it is assigned asynchronously:
# this order event could be triggered before self.ticket is assigned.
ticket = order_event.ticket
if ticket is None:
raise AssertionError("Expected order ticket in order event to not be null")
if order_event.status == OrderStatus.SUBMITTED and self.ticket is not None:
raise AssertionError("Field self.ticket not expected no be assigned on the first order event")
self.debug(ticket.to_string())
def on_end_of_algorithm(self):
# Just checking that orders were placed
if not self.portfolio.invested or self.trade_count != self.transactions.orders_count:
raise AssertionError(f"Expected the portfolio to have holdings and to have {self.trade_count} trades, but had {self.transactions.orders_count}")
View on GitHub (pinned to d2c3659f87)
Solutions
- Extend the backtest date range so every hourly consolidator bar fires and orders fill.
- Confirm SPY minute/second data exists for the full period so consolidators trigger.
- Check order tickets for rejections/cancellations inflating or deflating orders_count.
- Ensure the consolidator registration and trade_count increment stay in sync (one increment per order).
Example fix
# before: end date too short -> under-filled self.set_end_date(2013, 10, 8) # after: enough bars for consolidator fills and invested portfolio self.set_end_date(2013, 10, 11)
Defensive patterns
Strategy: validation
Validate before calling
# Verify holdings and order count with diagnostics before asserting
if not self.portfolio.invested:
self.log(f'not invested; orders={self.transactions.orders_count} trades={self.trade_count}')
if self.trade_count != self.transactions.orders_count:
pending = [o for o in self.transactions.get_orders() if o.status not in (OrderStatus.FILLED,)]
self.log(f'pending/unfilled orders: {pending}')
if not self.portfolio.invested or self.trade_count != self.transactions.orders_count:
raise AssertionError(...) Prevention
- Ensure the backtest window is long enough for all consolidator bars to fire and fill.
- Confirm underlying data exists for the full period.
- Check order tickets for rejections/cancellations.
- Keep trade_count increments in sync with order submissions.
When it happens
Trigger: on_end_of_algorithm with self.portfolio.invested False, or self.trade_count != self.transactions.orders_count. Caused by asynchronous market orders not filling within the backtest window, the hourly consolidator firing fewer/more times than expected, or orders being rejected/canceled so orders_count differs from trade_count.
Common situations: Backtest end date too short for all hourly bars to fire; the equity (SPY) data missing bars so the consolidator under-fires; asynchronous orders pending/unfilled at termination; a duplicate order path inflating orders_count.
Related errors
- Expected order ticket in order event to not be null
- Field self.ticket not expected no be assigned on the first o
- OrderEvent quantity is Not expected to be 0, it should hold
- OrderEvent quantity should hold the current order Quantity
- Algorithm should have been invested at the end of the algori
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/5e416e4051dd6d01.
Report an issue: GitHub.