{"record":{"id":"138176317c99aee0","repo":"QuantConnect/Lean","slug":"time-unexpected-symbol-changed-event-old-symbo","errorCode":null,"errorMessage":"{Time} - Unexpected symbol changed event old symbol: {changedEvent}","messagePattern":"(.+?) - Unexpected symbol changed event old symbol: (.+?)","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs","lineNumber":80,"sourceCode":"            var seeder = new FuncSecuritySeeder(GetLastKnownPrices);\n            SetSecurityInitializer(security => seeder.SeedSecurity(security));\n        }\n\n        public override void OnData(Slice slice)\n        {\n            foreach (var changedEvent in slice.SymbolChangedEvents.Values)\n            {\n                if (++_mappingsCount > 1)\n                {\n                    throw new RegressionTestException($\"{Time} - Unexpected number of symbol changed events (mappings): {_mappingsCount}. \" +\n                        $\"Expected only 1.\");\n                }\n\n                Debug($\"{Time} - SymbolChanged event: {changedEvent}\");\n\n                if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())\n                {\n                    throw new RegressionTestException($\"{Time} - Unexpected symbol changed event old symbol: {changedEvent}\");\n                }\n\n                if (changedEvent.NewSymbol != _continuousContract.Mapped.ID.ToString())\n                {\n                    throw new RegressionTestException($\"{Time} - Unexpected symbol changed event new symbol: {changedEvent}\");\n                }\n\n                // Let's trade the previous mapped contract, so we can hold it until expiration for testing\n                // (will be sooner than the new mapped contract)\n                _contractToTrade = _mappedSymbol;\n                _mappedSymbol = _continuousContract.Mapped;\n            }\n\n            // Let's trade after the mapping is done\n            if (_contractToTrade != null && _boughtQuantity == 0 && Securities[_contractToTrade].Exchange.ExchangeOpen)\n            {\n                Buy(_contractToTrade, 1);\n            }","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/BasicTemplateEurexFuturesAlgorithm.cs#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm Initialize() continuous contract settings (dataMappingMode: FirstDayMonth, contractDepthOffset: 0, dataNormalizationMode: BackwardsRatio) match the data set the regression expects.","Verify the EuroStoxx50 contract chain for the 2024-05-30..2024-06-23 window to see which contract should be the rollover source.","Ensure the EUREX futures data is present locally (CanRunLocally / required data points); missing contracts corrupt the mapping.","If adapting the pattern, capture _mappedSymbol fresh from _continuousContract.Mapped on each OnSecuritiesChanged canonical add rather than assuming a fixed symbol."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before processing the change event, confirm old symbol matches expectation\nforeach (var changedEvent in slice.SymbolChangedEvents.Values)\n{\n    if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())\n    {\n        Log($\"{Time} - Mapping source mismatch: event={changedEvent.OldSymbol} expected={_mappedSymbol.ID}\");\n        continue; // or handle gracefully\n    }\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    if (changedEvent.OldSymbol != _mappedSymbol.ID.ToString())\n        throw new RegressionTestException($\"{Time} - Unexpected old symbol: {changedEvent}\");\n}\ncatch (RegressionTestException ex)\n{\n    Log(ex.Message); // in non-regression use, log and re-map _mappedSymbol\n}","preventionTips":["Keep _mappedSymbol in sync with _continuousContract.Mapped on each OnSecuritiesChanged canonical add.","Pin the Lean version and EUREX dataset so the mapping chain is deterministic.","Log every SymbolChangedEvent to audit the rollover source."],"tags":["futures","continuous-contract","symbol-mapping","regression-test","eurex","rollover"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}