QuantConnect/Lean · error · RegressionTestException

{Time} - Unexpected symbol changed event old symbol: {change

Error message

{Time} - Unexpected symbol changed event old symbol: {changedEvent}

What it means

This EUREX futures regression algorithm tracks continuous-contract rollover. When Lean remaps a continuous future, it emits a SymbolChangedEvent whose OldSymbol should equal the contract that was mapped BEFORE the roll. The assertion compares changedEvent.OldSymbol against _mappedSymbol.ID.ToString() (the contract captured at last mapping/subscription start). A mismatch means Lean rolled away from a different contract than the algorithm believed was active, indicating the mapping chain diverged from expectations.

Source

Thrown at Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs:80

            var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
            SetSecurityInitializer(security => seeder.SeedSecurity(security));
        }

        public override void OnData(Slice slice)
        {
            foreach (var changedEvent in slice.SymbolChangedEvents.Values)
            {
                if (++_mappingsCount > 1)
                {
                    throw new RegressionTestException($"{Time} - Unexpected number of symbol changed events (mappings): {_mappingsCount}. " +
                        $"Expected only 1.");
                }

                Debug($"{Time} - SymbolChanged event: {changedEvent}");

                if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())
                {
                    throw new RegressionTestException($"{Time} - Unexpected symbol changed event old symbol: {changedEvent}");
                }

                if (changedEvent.NewSymbol != _continuousContract.Mapped.ID.ToString())
                {
                    throw new RegressionTestException($"{Time} - Unexpected symbol changed event new symbol: {changedEvent}");
                }

                // Let's trade the previous mapped contract, so we can hold it until expiration for testing
                // (will be sooner than the new mapped contract)
                _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);
            }

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm Initialize() continuous contract settings (dataMappingMode: FirstDayMonth, contractDepthOffset: 0, dataNormalizationMode: BackwardsRatio) match the data set the regression expects.
  2. Verify the EuroStoxx50 contract chain for the 2024-05-30..2024-06-23 window to see which contract should be the rollover source.
  3. Ensure the EUREX futures data is present locally (CanRunLocally / required data points); missing contracts corrupt the mapping.
  4. If adapting the pattern, capture _mappedSymbol fresh from _continuousContract.Mapped on each OnSecuritiesChanged canonical add rather than assuming a fixed symbol.
Defensive patterns

Strategy: validation

Validate before calling

// Before processing the change event, confirm old symbol matches expectation
foreach (var changedEvent in slice.SymbolChangedEvents.Values)
{
    if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())
    {
        Log($"{Time} - Mapping source mismatch: event={changedEvent.OldSymbol} expected={_mappedSymbol.ID}");
        continue; // or handle gracefully
    }
}

Try / catch

try
{
    if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())
        throw new RegressionTestException($"{Time} - Unexpected old symbol: {changedEvent}");
}
catch (RegressionTestException ex)
{
    Log(ex.Message); // in non-regression use, log and re-map _mappedSymbol
}

Prevention

When it happens

Trigger: A SymbolChangedEvent fires during the backtest window (2024-05-30 to 2024-06-23 EuroStoxx50) and changedEvent.OldSymbol != _mappedSymbol.ID.ToString(). Occurs when the continuous contract's previously mapped symbol and the event's reported old symbol disagree — e.g. mapping mode/contractDepthOffset/data changes shifted which contract is the rollover source.

Common situations: Lean engine version upgrade changes default continuous-contract mapping rules; EUREX EuroStoxx50 dataset updated so a different contract becomes front-month; DataMappingMode.FirstDayMonth or contractDepthOffset: 0 altered in Initialize; incomplete local futures data alters the mapping chain.

Related errors


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