QuantConnect/Lean · error · RegressionTestException

{Time} - Unexpected sell order event status: {orderEvent.Sta

Error message

{Time} - Unexpected sell order event status: {orderEvent.Status}

What it means

The sell-leg invariant: a sell fill is only valid when a prior buy exists (_boughtQuantity > 0) and no sell has been recorded yet (_liquidatedQuantity == 0). If _boughtQuantity <= 0 and _liquidatedQuantity != 0, a sell fill arrived without a preceding buy or after liquidation already happened — an out-of-sequence or duplicate sell fill.

Source

Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:138

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

        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            foreach (var addedSecurity in changes.AddedSecurities)
            {
                if (addedSecurity.Symbol.SecurityType == SecurityType.Future && addedSecurity.Symbol.IsCanonical())
                {
                    _mappedSymbol = _continuousContract.Mapped;

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Verify the buy fill was recorded (_boughtQuantity > 0) before any sell is expected — check event ordering.
  2. Accumulate sell fills instead of treating each as the sole liquidation.
  3. Confirm delisting liquidation fires only once (no duplicate sell events).
  4. If using OnOrderEvent for a sell that can legitimately precede state, restructure the state machine to allow it.

Example fix

// before
if (_boughtQuantity <= 0 && _liquidatedQuantity != 0) { throw ...; }

// after: tolerate liquidation that arrives without a recorded buy (e.g. engine-forced)
_liquidatedQuantity += orderEvent.Quantity;
Defensive patterns

Strategy: validation

Validate before calling

if (orderEvent.Direction == OrderDirection.Sell && orderEvent.Status == OrderStatus.Filled)
{
    _liquidatedQuantity += orderEvent.Quantity;
}

Prevention

When it happens

Trigger: An OrderDirection.Sell with OrderStatus.Filled arrives while _boughtQuantity <= 0 and _liquidatedQuantity != 0 — e.g. a delisting liquidation sell when the buy was never recorded, or a second sell fill after liquidation.

Common situations: The buy fill event was missed/not recorded so _boughtQuantity stays 0 when the liquidation sell fires; delisting auto-liquidation emits a sell before the buy event was processed; a duplicate liquidation sell after the position is already closed.

Related errors


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