book
Checkout our new book! Hands on AI Trading with Python, QuantConnect, and AWS Learn More arrow

Requesting Data

Individual Contracts

Introduction

The add_future_contract method enables you to add an individual Future contract to your algorithm. To check which contracts are currently available to add to your algorithm, call the futures_chain method. If you want to subscribe to a set of contracts instead of individual contracts one-by-one, see Universes.

Create Subscriptions

Before you can subscribe to a Future contract, you must have the underlying Future Symbol to get the contract Symbol.

Select Language:
class BasicFutureAlgorithm(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2020, 1, 1)
        self._continuous = self.add_future(Futures.Indices.SP_500_E_MINI).symbol
        self._contract_symbol = None
    
    def on_data(self, data):
        if not self._contract_symbol:
            self._contract_symbol = list(self.futures_chain(self._continuous))[0].symbol
            self.add_future_contract(self._contract_symbol)

Get Contract Symbols

To subscribe to a Future contract, you need the contract Symbol. The preferred method to getting Future contract Symbol objects is to use the futures_chain method. This method returns a FuturesChain object, which represent an entire chain of Option contracts for a single underlying security. You can even format the chain data into a DataFrame where each row in the DataFrame represents a single contract. With the chain, sort and filter the data to find the specific contract(s) you want to trade.

Select Language:
# Select the first contract in the chain, which is the front-month contract.
self._contract_symbol = list(self.futures_chain(self._continuous))[0].symbol

Subscribe to Contracts

To create an Future contract subscription, pass the contract Symbol to the add_future_contract method. Save a reference to the contract symbol so you can easily access the Future contract in the FutureChain that LEAN passes to the on_data method. This method returns an Future object.

Select Language:
self.add_future_contract(self._contract_symbol)

The add_future_contract method creates a subscription for a single Future contract and adds it to your user-defined universe. To create a dynamic universe of Futures contracts, add an Future universe or an Future Universe Selection model.

Warm Up Contract Prices

If you subscribe to an Future contract with add_future_contract, you'll need to wait until the next Slice to receive data and trade the contract. To trade the contract in the same time step you subscribe to the contract, set the current price of the contract in a security initializer.

Select Language:
seeder = FuncSecuritySeeder(self.get_last_known_prices)
self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, seeder))

Supported Assets

To view the supported assets in the Futures dataset, see the Supported Assets.

Resolutions

The following table shows the available resolutions and data formats for Futures subscriptions:

ResolutionTradeBarQuoteBarTrade TickQuote Tick
TICKgreen checkgreen check
SECONDgreen checkgreen check
MINUTEgreen checkgreen check
HOURgreen checkgreen check
DAILYgreen checkgreen check

The default resolution for Futures contract subscriptions is Resolution.MINUTE. To change the resolution, pass a resolution argument to the add_future_contract method.

Select Language:
self.add_future_contract(self._contract_symbol, Resolution.DAILY)

To create custom resolution periods, see Consolidating Data.

Supported Markets

The following Market enumeration members are available for Futures:

Historical data for backtesting is unavailable for ICE, INDIA, SGX and NYSELIFFE. In live trading, LEAN sources this data from your brokerage or a third-party data provider.

You don't need to pass a market argument to the add_future_contract method because the contract Symbol already contains the market.

Fill Forward

Fill forward means if there is no data point for the current slice, LEAN uses the previous data point. Fill forward is the default data setting. If you disable fill forward, you may get stale fills or you may see trade volume as zero.

To disable fill forward for a security, set the fill_forward argument to false when you create the security subscription.

Select Language:
self.add_future_contract(self._contract_symbol, fill_forward=False)

Margin and Leverage

LEAN models buying power and margin calls to ensure your algorithm stays within the margin requirements. Futures are already leveraged products, so you can't change their leverage with the default margin model.

Extended Market Hours

By default, your security subscriptions only cover regular trading hours. To subscribe to pre and post-market trading hours for a specific asset, enable the extended_market_hours argument when you create the security subscription.

Select Language:
self.add_future_contract(self._contract_symbol, extended_market_hours=True)

You only receive extended market hours data if you create the subscription with minute, second, or tick resolution. If you create the subscription with daily or hourly resolution, the bars only reflect the regular trading hours.

To view the schedule of regular and extended market hours, see Market Hours.

In general, we model most Futures market hours with the following segments:

Market SegmentTime
Pre-market00:00:00 to 09:30:00
Market09:30:00 to 17:00:00
Post-market18:00:00 to 00:00:00

We model it this way because some Futures, like VIX, have pre- and post-market hours, so we standardized it. With this segmentation, if you set a Scheduled Events for the market open, it's set for 9:30 AM instead of midnight.

Continuous Contracts

A continuous Futures contract represents a single contract that maps to other contracts over time as the rollover rules are met. For more information about continuous Futures contracts, see Continuous Contracts.

Data Normalization

The data normalization mode doesn't affect the data that LEAN passes to on_data or the data from history request for Futures contracts. If you change the data normalization mode, it won't change the outcome.

The following data normalization modes are available for continuous Futures contracts:

Properties

The add_future_contract method returns a Future object, which have the following properties:

Examples

The following examples demonstrate common practices for requesting individual Future contract data.

Example 1: Add the Front-Month Contract

The following algorithm adds the front-month contract, with a two-day buffer, for the E-Mini S&P 500 Future and plots the daily closing price of the contract three days before month end. Then, trade an EMA cross strategy.

Select Language:
class FutureExampleAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2022, 1, 1)
        self.set_end_date(2023, 1, 1)

        # Request the future underlying data for ATM strike selection.
        self._future = self.add_future(
            Futures.Indices.SP_500_E_MINI,
            extended_market_hours=True,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
        ).symbol

        # Create an EMA indicator for trade signal generation.
        self._ema = self.ema(self._future, 20, Resolution.DAILY)
        # Warm up the indicator for immediate readiness to trade with.
        self.warm_up_indicator(self._future, self._ema, Resolution.DAILY)

        # Set a scheduled event to select the option contract periodically.
        self.schedule.on(
            # 3 days offset to select in prior.
            self.date_rules.month_end(3),
            self.time_rules.at(0, 1),
            self.select_contract
        )
        self.select_contract()

    def select_contract(self) -> None:
        # Get all the contracts that are currently tradable.
        chain = self.futures_chain(self._future)
        # Select the front-month contract due to liquidity, with a 2-day buffer to avoid volatility.
        contracts = [c for c in chain if c.expiry >= self.time + timedelta(2)]
        if not contracts:
            return
        contract = contracts[0].symbol
        # Request the Futures contract for trading.
        self._contract_symbol = self.add_future_contract(contract).symbol

    def on_data(self, slice: Slice) -> None:
        # Trade based on updated data.
        bar = slice.bars.get(self._contract_symbol)
        if bar and self.is_market_open(self._contract_symbol):
            # Trade trend-following strategy with EMA cross.
            if bar.close > self._ema.current.value and not self.portfolio[self._future].is_long:
                self.set_holdings(self._contract_symbol, 0.5)
            elif bar.close < self._ema.current.value and not self.portfolio[self._future].is_short:
                self.set_holdings(self._contract_symbol, -0.5)

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: