QuantConnect/Lean · error · AssertionError

Expected 2 subscriptions, but found {len(subscriptions)}

Error message

Expected 2 subscriptions, but found {len(subscriptions)}

What it means

Regression assertion that adding equity SPY at Resolution.MINUTE produces exactly two internal subscriptions for that symbol — one for trade ticks and one for quote ticks, which together back the Tick history request. Lean's subscription manager creates separate SubscriptionDataConfig entries per tick type. The assertion fires when the count differs from the expected two.

Source

Thrown at Algorithm.Python/PandasDataFrameFromMultipleTickTypeTickHistoryRegressionAlgorithm.py:30

# limitations under the License.

from AlgorithmImports import *

### <summary>
### Regression algorithm for asserting that tick history that includes multiple tick types (trade, quote) is correctly converted to a pandas
### dataframe without raising exceptions. The main exception in this case was a "non-unique multi-index" error due to trades adn quote ticks with
### duplicated timestamps.
### </summary>
class PandasDataFrameFromMultipleTickTypeTickHistoryRegressionAlgorithm(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2013, 10, 8)
        self.set_end_date(2013, 10, 8)

        spy = self.add_equity("SPY", Resolution.MINUTE).symbol

        subscriptions = [x for x in self.subscription_manager.subscriptions if x.symbol == spy]
        if len(subscriptions) != 2:
            raise AssertionError(f"Expected 2 subscriptions, but found {len(subscriptions)}")

        history = pd.DataFrame()
        try:
            history = self.history(Tick, spy, timedelta(days=1), Resolution.TICK)
        except Exception as e:
            raise AssertionError(f"History call failed: {e}")

        if history.shape[0] == 0:
            raise AssertionError("SPY tick history is empty")

        if not np.array_equal(history.columns.to_numpy(), ['askprice', 'asksize', 'bidprice', 'bidsize', 'exchange', 'lastprice', 'quantity']):
            raise AssertionError("Unexpected columns in SPY tick history")

        self.quit()

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Inspect the actual subscriptions: log each config's tick_type and resolution to see which is missing.
  2. If quote/trade data is missing, ensure the data is requested — e.g. add_equity with the fill-forward/quote settings that produce both tick types, or check data.json/Lean defaults.
  3. As an engine regression: verify SubscriptionManager creates one config per supported tick type for the asset and that no dedup removed one.
  4. Confirm the symbol resolves to the expected market so the correct subscription set applies.

Example fix

# before
subscriptions = [x for x in self.subscription_manager.subscriptions if x.symbol == spy]
if len(subscriptions) != 2:
    raise AssertionError(f"Expected 2 subscriptions, but found {len(subscriptions)}")

# after (diagnostic: report which tick types exist)
subscriptions = [x for x in self.subscription_manager.subscriptions if x.symbol == spy]
types = sorted(str(x.tick_type) for x in subscriptions)
if len(subscriptions) != 2:
    raise AssertionError(
        f"Expected 2 subscriptions, but found {len(subscriptions)}: tick_types={types}")
Defensive patterns

Strategy: validation

Validate before calling

# Inspect actual subscription tick types before asserting the count
spy = self.add_equity('SPY', Resolution.MINUTE).symbol
subs = [x for x in self.subscription_manager.subscriptions if x.symbol == spy]
tick_types = sorted(str(x.tick_type) for x in subs)
self.log(f"SPY subscriptions: {len(subs)} tick_types={tick_types}")
assert len(subs) == 2, f"Expected 2, got {len(subs)}: {tick_types}"

Type guard

def has_tick_types(subscriptions, expected):
    """True when the subscriptions cover the expected set of tick types."""
    got = {str(x.tick_type) for x in subscriptions}
    return expected.issubset(got)

Prevention

When it happens

Trigger: After add_equity('SPY', Resolution.MINUTE), the filter [x for x in self.subscription_manager.subscriptions if x.symbol == spy] returns a count other than 2. This occurs if the default tick-type set for equities changed, if subscription config creation was deduplicated/merged, or if add_equity resolved the symbol differently (e.g. canonical or a different market).

Common situations: Lean contributors run the multiple-tick-type history regression after touching SubscriptionManager, SecurityManager, or the equity subscription configuration. Users hit it after upgrading Lean if the default subscription/tick configuration for equities changed (e.g. quote data no longer subscribed by default), or when they pass a different Resolution/data-normalization that yields fewer configs.

Related errors


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