QuantConnect/Lean · error · RegressionTestException

CustomMarginInterestRateModel was not set

Error message

CustomMarginInterestRateModel was not set

What it means

Asserts that security.SetMarginInterestRateModel(...) persisted the model. OnEndOfAlgorithm casts Securities[_spy].MarginInterestRateModel to CustomMarginInterestRateModel; a null result means the property was never set or was overwritten by a default after Initialize.

Source

Thrown at Algorithm.CSharp/CustomMarginInterestRateModelAlgorithm.cs:70

            }
        }

        public override void OnOrderEvent(OrderEvent orderEvent)
        {
            if (orderEvent.Status == OrderStatus.Filled)
            {
                _cashAfterOrder = Portfolio.Cash;
            }
        }

        public override void OnEndOfAlgorithm()
        {
            var security = Securities[_spy];
            var marginInterestRateModel = security.MarginInterestRateModel as CustomMarginInterestRateModel;

            if (marginInterestRateModel == null)
            {
                throw new RegressionTestException("CustomMarginInterestRateModel was not set");
            }

            if (marginInterestRateModel.CallCount == 0)
            {
                throw new RegressionTestException("CustomMarginInterestRateModel was not called");
            }

            var expectedCash = _cashAfterOrder * (decimal)Math.Pow(1 + (double)marginInterestRateModel.InterestRate, marginInterestRateModel.CallCount);

            // add a tolerance since using Math.Pow(double, double) given the lack of a decimal overload
            if (Math.Abs(Portfolio.Cash - expectedCash) > 1e-10m)
            {
                throw new RegressionTestException($"Expected cash {expectedCash} but got {Portfolio.Cash}");
            }
        }

        public class CustomMarginInterestRateModel : IMarginInterestRateModel
        {

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Set the custom model AFTER SetBrokerageModel so the brokerage default does not overwrite it.
  2. Ensure you store the Security returned by AddEquity and call SetMarginInterestRateModel on that exact instance.
  3. Re-assert the model type in OnEndOfAlgorithm (as the test does) to catch silent overwrites early.
  4. Check whether the brokerage model's implementation reassigns MarginInterestRateModel and disable/override that path.

Example fix

// before: brokerage model applied last clobbers the custom model
security.SetMarginInterestRateModel(new CustomMarginInterestRateModel());
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);

// after: set custom model after brokerage defaults are applied
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
security.SetMarginInterestRateModel(new CustomMarginInterestRateModel());
Defensive patterns

Strategy: validation

Validate before calling

// Assert the model is set right after configuration
security.SetMarginInterestRateModel(new CustomMarginInterestRateModel());
if (!(security.MarginInterestRateModel is CustomMarginInterestRateModel))
    throw new InvalidOperationException("Custom margin interest rate model was overwritten");

Type guard

bool HasCustomModel(Security s) => s.MarginInterestRateModel is CustomMarginInterestRateModel;

Prevention

When it happens

Trigger: Calling security.SetMarginInterestRateModel(new CustomMarginInterestRateModel()) in Initialize, then later (or via a framework default) the MarginInterestRateModel is replaced by the brokerage default before OnEndOfAlgorithm.

Common situations: A Lean upgrade that resets MarginInterestRateModel when brokerage model is applied after Initialize, calling SetBrokerageModel after setting the custom model, or setting the model on the wrong security reference (e.g., a transient Security from AddEquity not stored).

Related errors


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