QuantConnect/Lean · error · RegressionTestException

Fee rate should be 0.0507, but was {rebateRate}

Error message

Fee rate should be 0.0507, but was {rebateRate}

What it means

Asserts RebateRate returns exactly 0.0507m (note: the message text mislabels it 'Fee rate' but the variable is rebateRate). CustomSPYShortableProvider.RebateRate is constant 0.0507m; any other value means the custom provider is not installed at query time.

Source

Thrown at Algorithm.CSharp/CustomShortableProviderRegressionAlgorithm.cs:73

            var transactions = Transactions.OrdersCount;
            if (transactions != 1)
            {
                throw new RegressionTestException($"Algorithm should have just 1 order, but was {transactions}");
            }
            var orderQuantity = Transactions.GetOrderById(_orderId).Quantity;
            if (orderQuantity != -1001)
            {
                throw new RegressionTestException($"Quantity of order {_orderId} should be -1001, but was {orderQuantity}");
            }
            var feeRate = _spy.ShortableProvider.FeeRate(_spy.Symbol, Time);
            if (feeRate != 0.0025m)
            {
                throw new RegressionTestException($"Fee rate should be 0.0025, but was {feeRate}");
            }
            var rebateRate = _spy.ShortableProvider.RebateRate(_spy.Symbol, Time);
            if (rebateRate != 0.0507m)
            {
                throw new RegressionTestException($"Fee rate should be 0.0507, but was {rebateRate}");
            }
        }

        private class CustomSPYShortableProvider : IShortableProvider
        {
            public decimal FeeRate(Symbol symbol, DateTime localTime) => 0.0025m;

            public decimal RebateRate(Symbol symbol, DateTime localTime) => 0.0507m;

            public long? ShortableQuantity(Symbol symbol, DateTime localTime)
            {
                if (localTime < new DateTime(2013, 10, 4, 16, 0, 0))
                {
                    return 10;
                }
                else
                {
                    return 1001;

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Apply SetShortableProvider after SetBrokerageModel on the stored _spy Security.
  2. Confirm CustomSPYShortableProvider implements RebateRate returning 0.0507m.
  3. Detect provider swaps by asserting `_spy.ShortableProvider is CustomSPYShortableProvider` before reading rates.
  4. Keep one place that assigns the provider to avoid double-assignment races.

Example fix

// before: provider overwritten, rebate reads default
_spy.SetShortableProvider(new CustomSPYShortableProvider());
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);

// after: custom provider wins
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
_spy.SetShortableProvider(new CustomSPYShortableProvider());
Defensive patterns

Strategy: validation

Validate before calling

if (!(_spy.ShortableProvider is CustomSPYShortableProvider))
    throw new InvalidOperationException("Custom shortable provider not installed");
var rebate = _spy.ShortableProvider.RebateRate(_spy.Symbol, Time);

Type guard

bool HasCustomShortableProvider(Security s) => s.ShortableProvider is CustomSPYShortableProvider;

Prevention

When it happens

Trigger: Reading _spy.ShortableProvider.RebateRate at OnEndOfAlgorithm and getting the default provider's value (e.g., 0 or a different constant) because SetShortableProvider did not stick.

Common situations: Same as FeeRate: brokerage model reset the provider, or provider set on the wrong reference. Distinct from error 55 only in which property is queried.

Related errors


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