QuantConnect/Lean · error · AssertionError
OrderEvent LimitPrice is Not expected to be 0 for LimitOrder
Error message
OrderEvent LimitPrice is Not expected to be 0 for LimitOrder and StopLimitOrder
What it means
This is a self-test assertion inside OrderTicketDemoAlgorithm.on_order_event. It verifies that when Lean emits an OrderEvent for a LimitOrder or StopLimitOrder, the OrderEvent.LimitPrice field carries the order's real limit price rather than 0. OrderEvent.LimitPrice is a nullable decimal (decimal?) populated by the transaction/fill pipeline from the originating order. The assertion fires only when the field reads as exactly numeric zero for one of these two order types.
Source
Thrown at Algorithm.Python/OrderTicketDemoAlgorithm.py:399
update_order_fields = UpdateOrderFields()
update_order_fields.quantity = quantity
update_order_fields.tag = "Update #{0}".format(len(ticket.update_requests) + 1)
ticket.update(update_order_fields)
def on_order_event(self, order_event):
order = self.transactions.get_order_by_id(order_event.order_id)
self.log("{0}: {1}: {2}".format(self.time, order.type, order_event))
if order_event.quantity == 0:
raise AssertionError("OrderEvent quantity is Not expected to be 0, it should hold the current order Quantity")
if order_event.quantity != order.quantity:
raise AssertionError("OrderEvent quantity should hold the current order Quantity")
if (type(order) is LimitOrder and order_event.limit_price == 0 or
type(order) is StopLimitOrder and order_event.limit_price == 0):
raise AssertionError("OrderEvent LimitPrice is Not expected to be 0 for LimitOrder and StopLimitOrder")
if type(order) is StopMarketOrder and order_event.stop_price == 0:
raise AssertionError("OrderEvent StopPrice is Not expected to be 0 for StopMarketOrder")
# We can access the order ticket from the order event
if order_event.ticket is None:
raise AssertionError("OrderEvent Ticket was not set")
if order_event.order_id != order_event.ticket.order_id:
raise AssertionError("OrderEvent.ORDER_ID and order_event.ticket.order_id do not match")
def check_pair_orders_for_fills(self, long_order, short_order):
if long_order.status == OrderStatus.FILLED:
self.log("{0}: Cancelling short order, long order is filled.".format(short_order.order_type))
short_order.cancel("Long filled.")
return True
if short_order.status == OrderStatus.FILLED:
self.log("{0}: Cancelling long order, short order is filled.".format(long_order.order_type))View on GitHub (pinned to d2c3659f87)
Solutions
- If you are running Lean's own regression test: treat this as an engine regression — find where the OrderEvent for LimitOrder/StopLimitOrder is built and ensure LimitPrice is copied from order.LimitPrice (see the OrderEvent(Order,...) constructor path and fill models).
- If you copied the assertion into your own algorithm: replace the equality-with-zero check with a nullable-aware guard that compares against the order's actual limit price, since LimitPrice is decimal? and can be None rather than 0.
- If the event came from a custom/brokerage fill model, set order_event.LimitPrice = order.LimitPrice before emitting the event.
- If the event is deserialized from a stored/live packet, confirm the source sets LimitPrice; otherwise re-attach it from the live order in OnOrderEvent.
Example fix
# before
if (type(order) is LimitOrder and order_event.limit_price == 0 or
type(order) is StopLimitOrder and order_event.limit_price == 0):
raise AssertionError("OrderEvent LimitPrice is Not expected to be 0 for LimitOrder and StopLimitOrder")
# after (nullable-aware, compares to the originating order's limit price)
if type(order) in (LimitOrder, StopLimitOrder):
if order_event.limit_price in (None, 0) or order_event.limit_price != order.limit_price:
raise AssertionError(
f"OrderEvent LimitPrice mismatch for {type(order).__name__}: "
f"event={order_event.limit_price}, order={order.limit_price}") Defensive patterns
Strategy: validation
Validate before calling
# Before relying on order_event.limit_price for a limit-type order, validate it is set and matches the order
order = self.transactions.get_order_by_id(order_event.order_id)
if type(order) in (LimitOrder, StopLimitOrder):
if order_event.limit_price in (None, 0):
self.debug(f"Skipping event: limit_price unset for {type(order).__name__}")
return
# safe to use order_event.limit_price Type guard
def has_valid_limit_price(order, order_event):
"""True only for limit-type orders whose event limit price is present and non-zero."""
if type(order) not in (LimitOrder, StopLimitOrder):
return True
lp = order_event.limit_price
return lp is not None and lp != 0 Prevention
- Treat OrderEvent.LimitPrice as nullable (decimal?); compare with is None and against order.limit_price, never assume it is 0.
- Do not copy regression-algorithm assertions verbatim into production algorithms; relax them to warnings.
- If you build OrderEvents in a custom fill/brokerage model, always copy LimitPrice from the originating order.
When it happens
Trigger: An OrderEvent arrives whose order is a LimitOrder or StopLimitOrder and order_event.limit_price == 0. Concretely: order_event.quantity is non-zero and matches order.quantity (the earlier checks passed), but the limit price was never copied from the order onto the event. This happens if the engine/serializer drops the LimitPrice, if a custom order type or fill model constructs the event without setting LimitPrice, or if the event was deserialized (e.g. via OrderEvent.FromSerialized) and the source lacked the limit price.
Common situations: Lean engine contributors run the OrderTicketDemo regression algorithm after changing order serialization, the fill model, or OrderEvent construction and the limit price stops being propagated. A user who copies this assertion pattern into their own algorithm hits it when their brokerage/custom fill model emits an event without setting LimitPrice. It can also surface after a Lean version upgrade if the OrderEvent contract for limit prices changed.
Related errors
- OrderEvent StopPrice is Not expected to be 0 for StopMarketO
- OrderEvent Ticket was not set
- OrderEvent.ORDER_ID and order_event.ticket.order_id do not m
- Order was not canceled
- There should be no open orders
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/5d118270adacc065.
Report an issue: GitHub.