QuantConnect/Lean · error · AssertionError

FuturesChain() returned contract with no data.

Error message

FuturesChain() returned contract with no data.

What it means

Data-quality assertion in a FuturesChain regression: for every row in the futures_chain(future, flatten=True).data_frame, if bidprice, askprice AND volume are all 0 the test aborts, proving every returned contract has at least some market data.

Source

Thrown at Algorithm.Python/FuturesChainFullDataRegressionAlgorithm.py:35

### Regression algorithm illustrating the usage of the <see cref="QCAlgorithm.FuturesChain(Symbol, bool)"/>
### method to get a future chain.
### </summary>
class FuturesChainFullDataRegressionAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2013, 10, 7)
        self.set_end_date(2013, 10, 7)

        future = self.add_future(Futures.Indices.SP_500_E_MINI, Resolution.MINUTE).symbol

        chain = self.futures_chain(future, flatten=True)

        # Demonstration using data frame:
        df = chain.data_frame

        for index, row in df.iterrows():
            if row['bidprice'] == 0 and row['askprice'] == 0 and row['volume'] == 0:
                raise AssertionError("FuturesChain() returned contract with no data.");

        # Get contracts expiring within 6 months, with the latest expiration date, and lowest price
        contracts = df.loc[(df.expiry <= self.time + timedelta(days=180))]
        contracts = contracts.sort_values(['expiry', 'lastprice'], ascending=[False, True])
        self._future_contract = contracts.index[0]

        self.add_future_contract(self._future_contract)

    def on_data(self, data):
        # Do some trading with the selected contract for sample purposes
        if not self.portfolio.invested:
            self.set_holdings(self._future_contract, 0.5)
        else:
            self.liquidate()

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Identify which contract (index) has all-zero bid/ask/volume and inspect its data file.
  2. Filter the chain to contracts that actually have data before trading.
  3. Confirm the resolution requested matches the data granularity available.
  4. Re-run the data generator / re-download the affected contract.

Example fix

// before
for index, row in df.iterrows():
    if row['bidprice'] == 0 and row['askprice'] == 0 and row['volume'] == 0:
        raise AssertionError("FuturesChain() returned contract with no data.")
// after - filter out empty contracts instead of failing
df = df[~((df['bidprice'] == 0) & (df['askprice'] == 0) & (df['volume'] == 0))]
Defensive patterns

Strategy: validation

Validate before calling

# Filter empty-data contracts before trading
mask = ~((df['bidprice'] == 0) & (df['askprice'] == 0) & (df['volume'] == 0))
empty = df[~mask]
if not empty.empty:
    self.debug(f"Contracts with no data: {list(empty.index)}")
df = df[mask]

Type guard

def contract_has_data(row) -> bool:
    return not (row['bidprice'] == 0 and row['askprice'] == 0 and row['volume'] == 0)

Prevention

When it happens

Trigger: The chain returning a contract whose data file has no quotes and no trades for the requested bar; a stale or placeholder contract entry with zero data; flatten=True surfacing contracts that have no row-level data.

Common situations: Data drop missing quote/trade files for one contract; chain provider returning expired/illiquid contracts with no activity; resolution mismatch so no bar aggregates; data refresh inserting empty rows.

Related errors


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