QuantConnect/Lean · error · RegressionTestException
{Time} - Unexpected buy order event status: {orderEvent.Stat
Error message
{Time} - Unexpected buy order event status: {orderEvent.Status} What it means
The order-event handler is a small state machine: a buy fill is only valid as the FIRST fill (when neither a buy nor a sell has been recorded). If _boughtQuantity != 0 AND _liquidatedQuantity != 0, a second buy fill arrived after both legs completed — a duplicate or unexpected re-entry fill that violates the single-buy/single-sell lifecycle.
Source
Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:127
}
}
}
}
public override void OnOrderEvent(OrderEvent orderEvent)
{
if (orderEvent.Symbol != _contractToTrade)
{
throw new RegressionTestException($"{Time} - Unexpected order event symbol: {orderEvent.Symbol}. Expected {_contractToTrade}");
}
if (orderEvent.Direction == OrderDirection.Buy)
{
if (orderEvent.Status == OrderStatus.Filled)
{
if (_boughtQuantity != 0 && _liquidatedQuantity != 0)
{
throw new RegressionTestException($"{Time} - Unexpected buy order event status: {orderEvent.Status}");
}
_boughtQuantity = orderEvent.Quantity;
}
}
else if (orderEvent.Direction == OrderDirection.Sell)
{
if (orderEvent.Status == OrderStatus.Filled)
{
if (_boughtQuantity <= 0 && _liquidatedQuantity != 0)
{
throw new RegressionTestException($"{Time} - Unexpected sell order event status: {orderEvent.Status}");
}
_liquidatedQuantity = orderEvent.Quantity;
if (_liquidatedQuantity != -_boughtQuantity)
{
throw new RegressionTestException($"{Time} - Unexpected liquidated quantity: {_liquidatedQuantity}. Expected: {-_boughtQuantity}");
}View on GitHub (pinned to d2c3659f87)
Solutions
- Track fill accumulation (sum partial fills) instead of overwriting _boughtQuantity on every filled event.
- Guard against duplicate fills by checking orderEvent.OrderId or a processed-fill set.
- Confirm only one Buy(_contractToTrade, 1) call executes (the _boughtQuantity == 0 gate at line 95).
- If partial fills are expected, accumulate quantity until OrderStatus.Filled terminal and then record once.
Example fix
// before
if (_boughtQuantity != 0 && _liquidatedQuantity != 0) { throw ...; }
_boughtQuantity = orderEvent.Quantity;
// after: accumulate partial buys, record the buy total once
_boughtQuantity += orderEvent.Quantity; Defensive patterns
Strategy: validation
Validate before calling
// Accumulate fills instead of overwriting; detect the first buy only
if (orderEvent.Direction == OrderDirection.Buy && orderEvent.Status == OrderStatus.Filled)
{
_boughtQuantity += orderEvent.Quantity;
} Prevention
- Accumulate partial buy fills into a running total.
- Track processed OrderIds to ignore duplicate fills.
- Gate the single Buy() call on _boughtQuantity == 0.
When it happens
Trigger: An OrderDirection.Buy with OrderStatus.Filled arrives when _boughtQuantity is already non-zero and _liquidatedQuantity is already non-zero. Concretely, a duplicate buy fill after the position was already opened and closed.
Common situations: A partial fill followed by another fill that the state machine treats as a second full buy; a re-entry order the algorithm didn't intend; engine fill event duplication during delisting liquidation; order updates/cancels producing extra filled events.
Related errors
- {Time} - Unexpected sell order event status: {orderEvent.Sta
- {Time} - Unexpected order event symbol: {orderEvent.Symbol}.
- {Time} - Unexpected liquidated quantity: {_liquidatedQuantit
- Unexpected sold quantity: {_boughtQuantity} and liquidated q
- {Time} - Unexpected symbol changed event old symbol: {change
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/f0a1fa8ca8092ad1.
Report an issue: GitHub.