QuantConnect/Lean · error · RegressionTestException

{Time} - Portfolio should not be invested after the traded c

Error message

{Time} - Portfolio should not be invested after the traded contract is delisted.

What it means

When the traded EUREX contract reaches its DelistingType.Delisted event, Lean is expected to auto-liquidate any open position. This assertion verifies Portfolio.Invested is false at that moment — if the portfolio still holds the position, delisting liquidation did not occur as designed. It guards the core guarantee that expired/delisted futures positions are closed by the engine.

Source

Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:108

                _contractToTrade = _mappedSymbol;
                _mappedSymbol = _continuousContract.Mapped;
            }

            // Let's trade after the mapping is done
            if (_contractToTrade != null && _boughtQuantity == 0 && Securities[_contractToTrade].Exchange.ExchangeOpen)
            {
                Buy(_contractToTrade, 1);
            }

            if (_contractToTrade != null && slice.Delistings.TryGetValue(_contractToTrade, out var delisting))
            {
                if (delisting.Type == DelistingType.Delisted)
                {
                    _delisted = true;

                    if (Portfolio.Invested)
                    {
                        throw new RegressionTestException($"{Time} - Portfolio should not be invested after the traded contract is delisted.");
                    }
                }
            }
        }

        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)
                    {

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm the traded contract's delisting data is present (warning + delisted events).
  2. Verify the engine's delisting-time liquidation path is intact (no custom Holdings/settlement logic that prevents auto-close).
  3. If adapting, explicitly Liquidate() on DelistingType.WarningTarget to close before the forced delisted stage.
  4. Check that the buy fill (_boughtQuantity) was recorded so the position is in the expected invested state prior to delisting.

Example fix

// before: rely solely on engine auto-liquidation at delisted stage
// after: liquidate on the warning stage to avoid a stranded position
if (delisting.Type == DelistingType.WarningTarget && Portfolio.Invested)
{
    Liquidate();
}
Defensive patterns

Strategy: validation

Validate before calling

// Close the position at the warning stage, before forced delisting
if (_contractToTrade != null && slice.Delistings.TryGetValue(_contractToTrade, out var dl))
{
    if (dl.Type == DelistingType.WarningTarget && Portfolio.Invested)
    {
        Liquidate(_contractToTrade);
    }
}

Prevention

When it happens

Trigger: slice.Delistings for _contractToTrade reports DelistingType.Delisted while Portfolio.Invested is still true. The contract was bought (Buy(_contractToTrade, 1)) earlier and the position was never liquidated before/at delisting.

Common situations: Engine delisting/liquidation logic changed; a fill on the buy order never settled so the position is in an unexpected state; the delisting data for the contract is missing the price warning stage; algorithm logic interfered with auto-liquidation.

Related errors


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