QuantConnect/Lean · error · RegressionTestException

Contract was not delisted

Error message

Contract was not delisted

What it means

OnEndOfAlgorithm asserts the traded contract was actually delisted (_delisted == true). _delisted is only set when slice.Delistings for _contractToTrade reports DelistingType.Delisted (line 102-104). If it never fired, the contract did not expire in-window, so the delisting/liquidation test path was never exercised.

Source

Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:170

            foreach (var addedSecurity in changes.AddedSecurities)
            {
                if (addedSecurity.Symbol.SecurityType == SecurityType.Future && addedSecurity.Symbol.IsCanonical())
                {
                    _mappedSymbol = _continuousContract.Mapped;
                }
            }
        }

        public override void OnEndOfAlgorithm()
        {
            if (_mappingsCount == 0)
            {
                throw new RegressionTestException($"Unexpected number of symbol changed events (mappings): {_mappingsCount}. Expected 1.");
            }

            if (!_delisted)
            {
                throw new RegressionTestException("Contract was not delisted");
            }

            // Make sure we traded and that the position was liquidated on delisting
            if (_boughtQuantity <= 0 || _liquidatedQuantity >= 0)
            {
                throw new RegressionTestException($"Unexpected sold quantity: {_boughtQuantity} and liquidated quantity: {_liquidatedQuantity}");
            }
        }

        /// <summary>
        /// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
        /// </summary>
        public bool CanRunLocally { get; } = true;

        /// <summary>
        /// This is used by the regression test system to indicate which languages this algorithm is written in.
        /// </summary>
        public List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm _contractToTrade was set (a mapping occurred) and that contract's expiry falls within the end date.
  2. Verify the contract's delisting data (warning + delisted events) is present.
  3. Extend SetEndDate past the held contract's expiration if the window was shortened.
  4. Ensure the held contract is the sooner-expiring previous-mapped one (line 90), not the new mapped one.
Defensive patterns

Strategy: validation

Validate before calling

public override void OnEndOfAlgorithm()
{
    if (!_delisted)
    {
        Log("Contract was not delisted in-window; verify _contractToTrade expiry vs EndDate.");
    }
}

Prevention

When it happens

Trigger: OnEndOfAlgorithm runs with _delisted == false — no DelistingType.Delisted event arrived for _contractToTrade during the backtest. The chosen contract (the previously-mapped, sooner-expiring one) did not reach its delisting date within the window.

Common situations: Date window ended before the held contract's expiry; the delisting data event is missing; _contractToTrade was never assigned because no mapping occurred; the wrong (later-expiring) contract was held.

Related errors


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