QuantConnect/Lean · error · RegressionTestException

{Time} - Unexpected liquidated quantity: {_liquidatedQuantit

Error message

{Time} - Unexpected liquidated quantity: {_liquidatedQuantity}. Expected: {-_boughtQuantity}

What it means

After liquidation, the absolute sell quantity must equal the buy quantity (_liquidatedQuantity == -_boughtQuantity). A mismatch means the position was not fully closed in one opposing fill — a partial liquidation, a quantity scaling error, or the engine liquidating a different size than was bought.

Source

Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:144

                    {
                        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;
                }
            }
        }

        public override void OnEndOfAlgorithm()
        {

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Accumulate both buy and sell fill quantities so the comparison reflects total filled, not a single event's quantity.
  2. Confirm the delisting liquidation sells the entire holdings quantity (Portfolio[_contractToTrade].Holdings.Quantity).
  3. If partial liquidation is expected, compare running totals rather than per-event equality.
  4. Log orderEvent.Quantity and Holdings at fill time to trace the divergence.

Example fix

// before
if (_liquidatedQuantity != -_boughtQuantity) { throw ...; }

// after: compare accumulated totals after all fills settle
if (_liquidatedRunningTotal != -_boughtRunningTotal) { throw ...; }
Defensive patterns

Strategy: validation

Validate before calling

// Compare accumulated totals after all fills, not per-event
if (orderEvent.Status == OrderStatus.Filled && _boughtRunningTotal + _liquidatedRunningTotal != 0)
{
    Log($"{Time} - Net position nonzero: bought={_boughtRunningTotal} sold={_liquidatedRunningTotal}");
}

Prevention

When it happens

Trigger: OrderDirection.Sell filled where _liquidatedQuantity != -_boughtQuantity — e.g. buy filled 1 but sell filled 0 (partial), or sell filled a different magnitude than the held position.

Common situations: Partial fills make the recorded sell not the full inverse of the buy; delisting liquidation rounds/limits quantity; commission or split adjustments alter quantity; the buy recorded gross quantity while sell netted differently.

Related errors


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