{"record":{"id":"9c03b666d1b0eec4","repo":"QuantConnect/Lean","slug":"unexpected-cached-margin-interest-rate-for-intere","errorCode":null,"errorMessage":"Unexpected cached margin interest rate for {interestRate.Key}!","messagePattern":"Unexpected cached margin interest rate for (.+?)!","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs","lineNumber":81,"sourceCode":"            _interestPerSymbol[_btcUsd.Symbol] = 0;\n\n            // the amount of USDT we need to hold to trade 'BTCUSDT'\n            _btcUsdt.QuoteCurrency.SetAmount(200);\n            // the amount of BTC we need to hold to trade 'BTCUSD'\n            _btcUsd.BaseCurrency.SetAmount(0.005m);\n        }\n\n        public override void OnData(Slice slice)\n        {\n            var interestRates = slice.Get<MarginInterestRate>();\n            foreach (var interestRate in interestRates)\n            {\n                _interestPerSymbol[interestRate.Key]++;\n\n                var cachedInterestRate = Securities[interestRate.Key].Cache.GetData<MarginInterestRate>();\n                if (cachedInterestRate != interestRate.Value)\n                {\n                    throw new RegressionTestException($\"Unexpected cached margin interest rate for {interestRate.Key}!\");\n                }\n            }\n\n            if (!_slow.IsReady)\n            {\n                return;\n            }\n\n            if (_fast > _slow)\n            {\n                if (!Portfolio.Invested && Transactions.OrdersCount == 0)\n                {\n                    var ticket = Buy(_btcUsd.Symbol, 1000);\n                    if (ticket.Status != OrderStatus.Invalid)\n                    {\n                        throw new RegressionTestException($\"Unexpected valid order {ticket}, should fail due to margin not sufficient\");\n                    }\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/BybitCryptoFuturesRegressionAlgorithm.cs#L63-L99","documentation":"Thrown by a regression test in OnData to assert cache consistency: every MarginInterestRate object delivered in a Slice must be the same object cached on its Security. Lean pushes MarginInterestRate into both the time slice and Securities[symbol].Cache; if the two diverge, the data pipeline has a bug (cache not refreshed, or a stale/duplicate object). It is an internal integrity check, not a runtime contract a user code path normally hits.","triggerScenarios":"Calling slice.Get<MarginInterestRate>() and comparing each value to Securities[interestRate.Key].Cache.GetData<MarginInterestRate>(); the comparison fails when the cache holds a different/null MarginInterestRate than the slice. Happens with crypto-futures margin rate ingestion where the rate is produced by a broker/builder that bypasses the cache write.","commonSituations":"Changes to the MarginInterestRate builder/serializer, a new brokerage whose margin-rate data type is not registered in the cache, or an engine refactor that stopped updating Security.Cache before emitting the slice. Also seen after upgrading Lean versions that altered data-cache semantics.","solutions":["Ensure the same MarginInterestRate instance is written to the Security cache (Security.Cache.Store(data)) in the same step it is added to the slice.","If you added a custom data type or brokerage, register MarginInterestRate handling so Lean's SubscriptionDataReaderConsumer caches it like other BaseData.","Run the regression under a debugger and inspect whether cachedInterestRate is null (cache miss) or a distinct instance (duplicate allocation) to locate the divergence.","Confirm the data builder for BybitCryptoFutures produces one MarginInterestRate per symbol and forwards it through BaseData.Cache properly."],"exampleFix":"// before: slice value and cache hold different instances\nslice.Add(key, rate);\n// security.Cache never updated -> divergence\n\n// after: cache the exact instance emitted in the slice\nSecurity.Cache.Store(rate);\nslice.Add(rate.Symbol, rate);","handlingStrategy":"validation","validationCode":"// Before trusting the cached rate, verify cache/slice consistency defensively:\nvar sliceRates = slice.Get<MarginInterestRate>();\nforeach (var kv in sliceRates)\n{\n    var cached = Securities[kv.Key].Cache.GetData<MarginInterestRate>();\n    if (cached == null || !ReferenceEquals(cached, kv.Value))\n    {\n        // log and skip rather than throw in user code\n        Log($\"Cache/slice mismatch for {kv.Key}; skipping\");\n        continue;\n    }\n    // use the rate\n}","typeGuard":"bool IsCacheConsistent(Security security, MarginInterestRate sliceRate) =>\n    ReferenceEquals(security.Cache.GetData<MarginInterestRate>(), sliceRate);","tryCatchPattern":null,"preventionTips":["Do not write MarginInterestRate instances directly to the slice; route them through the security cache so the two stay identical.","When adding a brokerage/data type, register it in Lean's cache pipeline so Cache.GetData<T> resolves.","In regression tests, compare with ReferenceEquals to catch instance divergence early."],"tags":["regression-test","margin-interest-rate","data-cache","crypto-futures"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}