Requesting Data

Universes

Introduction

The AddFutureOptionadd_future_option method enables you to select a basket of Option contracts for an underlying Future. To form your universe of contracts, you can filter them down by their strike price and expiry or you can choose a subset of the contracts that form popular Option strategies. If you want to subscribe to individual contracts one-by-one instead of a set of contracts, see Individual Contracts.

Create Universes

To add a universe of Future Option contracts, in the Initializeinitialize method, call the AddFutureOptionadd_future_option method. Pass the optionFilteroption_filter argument to filter the set of tradable contract down to just the contracts you want.

public class BasicFutureOptionAlgorithm : QCAlgorithm
{
    private Future _future;
    public override void Initialize()
    {
        _future = AddFuture(Futures.Indices.SP500EMini,
            extendedMarketHours: true,
            dataMappingMode: DataMappingMode.OpenInterest,
            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
            contractDepthOffset: 0);
        _future.SetFilter(0, 182);

        AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-1, 1));
    }

    public override void OnData(Slice data)
    {
        // Iterate all Option chains to find the desired future and future options contracts 
        foreach (var (canonicalSymbol, chain) in data.OptionChains)
        {
            var futureContract = canonicalSymbol.Underlying;
            foreach (var (symbol, contract) in chain.Contracts)
            {
                var strike = contract.Strike;
            }
        }

        // Get the Option chain for the mapped contract 
        if (data.OptionChains.TryGetValue(QuantConnect.Symbol.CreateCanonicalOption(_future.Mapped), out var mappedChain))
        {
            foreach (var (symbol, contract) in mappedChain.Contracts)
            {
                var strike = contract.Strike;
            }
        }
    }
}
class BasicFutureOptionAlgorithm(QCAlgorithm):
    def initialize(self):
        self._future = self.add_future(Futures.Indices.SP_500_E_MINI,
            extended_market_hours=True,
            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
            contract_depth_offset=0)
        self._future.set_filter(0, 182)

        self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-1, 1))
    
    def on_data(self, data):
        # Iterate all Option chains to find the desired future and future options contracts 
        for canonical_symbol, chain in data.option_chains.items():
            future_contract = canonical_symbol.underlying
            for symbol, contract in chain.contracts.items():
                strike = contract.strike

        # Get the Option chain for the mapped contract 
        mapped_chain = data.option_chains.get(Symbol.create_canonical_option(self._future.mapped))
        if mapped_chain:
            for symbol, contract in mapped_chain.contracts.items():
            strike = contract.strike

For more information about the AddFutureOptionadd_future_option method, see Create Universes.

Filter by Investment Strategy

Options trading strategies consist of simultaneously buying or selling one or more Option contracts of the same underlying Future with different features. The following table describes the filter methods of the OptionFilterUniverse class that select contract for Option strategies.

The following table describes the filter methods of the OptionFilterUniverse class that select contracts for Option strategies:

NakedCall(int minDaysTillExpiry, decimal strikeFromAtm)naked_call(min_days_till_expiry: int, strike_from_atm: float)

Selects a call contract to form Naked Call, Covered Call, or Protective Call Option strategies.

NakedPut(int minDaysTillExpiry, decimal strikeFromAtm)naked_put(min_days_till_expiry: int, strike_from_atm: float)

Selects a put contract to form Naked Put, Covered Put, or Protective Put Option strategies.

CallSpread(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal lowerStrikeFromAtm)call_spread(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)

Selects two call contracts to form Bull Call Spread or Bear Call Spread Option strategies.

PutSpread(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal lowerStrikeFromAtm)put_spread(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)

Selects two put contracts to form Bull Put Spread or Bear Put Spread Option strategies.

CallCalendarSpread(decimal strikeFromAtm, int minNearDaysTillExpiry, int minFarDaysTillExpiry)call_calendar_spread(strike_from_atm: int, min_near_days_till_expiry: int, min_far_days_till_expiry: int)

Selects two call contracts to form Long Call Calendar Spread or Short Call Calendar Spread Option strategies.

PutCalendarSpread(decimal strikeFromAtm, int minNearDaysTillExpiry, int minFarDaysTillExpiry)put_calendar_spread(strike_from_atm: int, min_near_days_till_expiry: int, min_far_days_till_expiry: int)

Selects two put contracts to form Long Put Calendar Spread or Short Put Calendar Spread Option strategies.

Strangle(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal lowerStrikeFromAtm)strangle(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)

Selects two contracts to form Long Strangle or Short Strangle Option strategies.

Straddle(int minDaysTillExpiry)straddle(min_days_till_expiry: int)

Selects two contracts to form Long Straddle or Short Straddle Option strategies.

ProtectiveCollar(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal lowerStrikeFromAtm)protective_collar(min_days_till_expiry: int, higher_strike_from_atm: float, lower_strike_from_atm: float)

Selects two contracts to form Protective Collar Option strategies.

Conversion(int minDaysTillExpiry, decimal strikeFromAtm)conversion(min_days_till_expiry: int, strike_from_atm: float)

Selects two contracts to form Conversion or Reverse Conversion Option strategies.

CallButterfly(int minDaysTillExpiry, decimal strikeSpread)call_butterfly(min_days_till_expiry: int, strike_spread: float)

Selects three contracts to form Long Call Butterfly or Short Call Butterfly Option strategies.

PutButterfly(int minDaysTillExpiry, decimal strikeSpread)put_butterfly(min_days_till_expiry: int, strike_spread: float)

Selects three contracts to form Long Put Butterfly or Short Put Butterfly Option strategies.

IronButterfly(int minDaysTillExpiry, decimal strikeSpread)iron_butterfly(min_days_till_expiry: int, strike_spread: float)

Selects four contracts to form Long Iron Butterfly or Short Iron Butterfly Option strategies.

IronCondor(int minDaysTillExpiry, decimal nearStrikeSpread, decimal farStrikeSpread)iron_condor(min_days_till_expiry: int, near_strike_spread: float, far_strike_spread: float)

Selects four contracts to form Long Iron Condor or Short Iron Condor Option strategies.

BoxSpread(int minDaysTillExpiry, decimal strikeSpread)box_spread(min_days_till_expiry: int, strike_spread: float)

Selects four contracts to form Box Spread or Short Box Spread Option strategies.

JellyRoll(decimal strikeFromAtm, int minNearDaysTillExpiry, int minFarDaysTillExpiry)jelly_roll(strike_from_atm: float, min_near_days_till_expiry: int, min_far_days_till_expiry: int)

Selects four contracts to form Jelly Roll or Short Jelly Roll Option strategies.

CallLadder(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal middleStrikeFromAtm, decimal lowerStrikeFromAtm)call_ladder(min_days_till_expiry: int, higher_strike_from_atm: float, middle_strike_from_atm: float, lower_strike_from_atm: float)

Selects four contracts to form Bear Call Ladder or Bull Call Ladder Option strategies.

PutLadder(int minDaysTillExpiry, decimal higherStrikeFromAtm, decimal middleStrikeFromAtm, decimal lowerStrikeFromAtm)put_ladder(min_days_till_expiry: int, higher_strike_from_atm: float, middle_strike_from_atm: float, lower_strike_from_atm: float)

Selects four contracts to form Bear Put Ladder or Bull Put Ladder Option strategies.

The preceding methods return an OptionFilterUniverse, so you can chain the methods together.

// Example 1: Select a Straddle
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Straddle(30, 5, 10));

// Example 2: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-20, 20).Expiration(0, 30).IronCondor(30, 5, 10));

// Example 3: Select the front month contracts that form an Strangle
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.FrontMonth().Strangle(30, 5, -10));
# Example 1: Select a Straddle
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.straddle(30, 5, 10))

# Example 2: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 30).iron_condor(30, 5, 10))

# Example 3: Select the front month contracts that form an Strangle
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.front_month().strangle(30, 5, -10))

Filter by Other Contract Properties

To set a contract filter, in the Initializeinitialize method, call the AddFutureOptionadd_future_option method and pass the optionFilteroption_filter argument.

// Select contracts that have a strike price within 1 strike level above and below the underlying price
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-1,1));

// Select contracts that expire within 30 days
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Expiration(0, 30));

// Select contracts that have a strike price within 1 strike level and expire within 30 days
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-1,1).Expiration(0, 30));

// Select call contracts
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.CallsOnly());
# Select contracts that have a strike price within 1 strike level above and below the underlying price
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-1,1))

# Select contracts that expire within 30 days
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.expiration(0,30))

# Select contracts that have a strike price within 1 strike level and expire within 30 days
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-1,1).expiration(0,30))

# Select call contracts
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.calls_only())

The following table describes the filter methods of the OptionFilterUniverse class:

Strikes(int minStrike, int maxStrike)strikes(min_strike: int, max_strike: int)

Selects contracts that are within minStrikem_strike strikes below the underlying price and maxStrikemax_strike strikes above the underlying price.

CallsOnly()calls_only()

Selects call contracts.

PutsOnly()puts_only()

Selects put contracts.

StandardsOnly()standards_only()

Selects standard contracts.

IncludeWeeklys()include_weeklys()

Selects non-standard weeklys contracts.

WeeklysOnly()weeklys_only()

Selects weekly contracts.

FrontMonth()front_month()

Selects the front month contract.

BackMonths()back_months()

Selects the non-front month contracts.

BackMonth()back_month()

Selects the back month contracts.

Expiration(int minExpiryDays, int maxExpiryDays)expiration(min_expiryDays: int, max_expiryDays: int)

Selects contracts that expire within a range of dates relative to the current day.

Contracts(IEnumerable<Symbol> contracts)contracts(contracts: List[Symbol])

Selects a list of contracts.

Contracts(Func<IEnumerable<Symbol>, IEnumerable< Symbol>> contractSelector)contracts(contract_selector: Callable[[List[Symbol]], List[Symbol]])

Selects contracts that a selector function selects.

The preceding methods return an OptionFilterUniverse, so you can chain the methods together.

The preceding methods return an OptionFilterUniverse, so you can chain the methods together.

// Example 1: Select the front month call contracts
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.CallsOnly().FrontMonth());

// Example 2: Select the contracts that expire in the next 90 days
AddFutureOption(_future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-20, 20).Expiration(0, 90));
# Example 1: Select the front month call contracts
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.calls_only().front_month())

# Example 2: Select the contracts that expire in the next 90 days
self.add_future_option(self._future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 90))

To perform thorough filtering on the OptionFilterUniverse, define an isolated filter method.

public class BasicFutureOptionAlgorithm : QCAlgorithm
{
    private Future _future;
    public override void Initialize()
    {
        AddFutureOption(_future.Symbol, Selector);
    }

    private OptionFilterUniverse Selector(OptionFilterUniverse optionFilterUniverse)
    {
        var symbols = optionFilterUniverse.PutsOnly();
        var strike = symbols.Select(symbol => symbol.ID.StrikePrice).Min();
        symbols = symbols.Where(symbol => symbol.ID.StrikePrice == strike);
        return optionFilterUniverse.Contracts(symbols);
    }
}
class BasicFutureOptionAlgorithm(QCAlgorithm):
    def initialize(self):
        self.add_future_option(self._future.symbol, self._selector)

    def _selector(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
        symbols = option_filter_universe.puts_only()
        strike = min([symbol.id.strike_price for symbol in symbols])
        symbols = [symbol for symbol in symbols if symbol.id.strike_price == strike]
        return option_filter_universe.contracts(symbols)

Some of the preceding filter methods only set an internal enumeration in the OptionFilterUniverse that it uses later on in the filter process. This subset of filter methods don't immediately reduce the number of contract Symbol objects in the OptionFilterUniverse.

Default Filter

By default, LEAN subscribes to the Option contracts that have the following characteristics:

  • Standard type (exclude weeklys)
  • Within 1 strike price of the underlying asset price
  • Expire within 35 days

To adjust the universe of contracts, set a filter. The filter usually runs at the first bar of every day. When the filter selects a contract that isn't currently in your universe, LEAN adds the new contract data to the next Slice that it passes to the OnDataon_data method.

Examples

The following examples demonstrate some common practices for requesting Future Option data through universe filtering.

Example 1: Call Spread

The following example demonstrates how to implement a bull call spread option strategy using universe filtering. We have to first subscribe to the underlying Future (with filtering), then call AddFutureOptionself.add_future_option with the underlying Symbol and the filtering function. We use CallSpreadcall_spread method in the OptionFilterUniverse object to return only the 2 best match call contracts that forms a bull call spread.

public class FutureOptionAlgorithm : QCAlgorithm
{
    private Future _underlying;

    public override void Initialize()
    {
        // Filter the underlying continuous Futures to narrow the FOP spectrum.
        _underlying = AddFuture(Futures.Indices.SP500EMini,
            extendedMarketHours: true,
            dataMappingMode: DataMappingMode.OpenInterest,
            dataNormalizationMode: DataNormalizationMode.BackwardsRatio,
            contractDepthOffset: 0);
        _underlying.SetFilter(0, 182);
        // Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
        // It simplifies from further filtering and reduce computation on redundant subscription.
        AddFutureOption(_underlying.Symbol, (u) => u.CallSpread(5, 5, -5));
    }
    
    public override void OnData(Slice slice)
    {
        if (Portfolio.Invested)
            return;

        // Create canonical symbol for the mapped future contract, since we need that to access the option chain.
        var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped);
    
        // Get option chain data for the mapped future only.
        // It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
        if (!slice.OptionChains.TryGetValue(symbol, out var chain) || chain.Count() < 2)
            return;
    
        // Separate the contracts by strike, as we need to access their strike.
        var expiry = chain.Min(x => x.Expiry);
        var itmStrike = chain.Min(x => x.Strike);
        var otmStrike = chain.Max(x => x.Strike);
    
        // Use abstraction method to order a bull call spread to avoid manual error.
        var optionStrategy = OptionStrategies.BullCallSpread(symbol, itmStrike, otmStrike, expiry);
        Buy(optionStrategy, 1);
    }
}
class FutureOptionAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        # Filter the underlying continuous Futures to narrow the FOP spectrum.
        self.underlying = self.add_future(Futures.Indices.SP_500_E_MINI,
            extended_market_hours=True,
            data_mapping_mode=DataMappingMode.OPEN_INTEREST,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
            contract_depth_offset=0)
        self.underlying.set_filter(0, 182)
        # Use CallSpread filter to obtain the 2 best-matched contracts that forms a call spread.
        # It simplifies from further filtering and reduce computation on redundant subscription.
        self.add_future_option(self.underlying.symbol, lambda u: u.call_spread(5, 5, -5))
        
    def on_data(self, slice: Slice) -> None:
        if self.portfolio.invested:
            return
        # Create canonical symbol for the mapped future contract, since we need that to access the option chain.
        symbol = Symbol.create_canonical_option(self.underlying.mapped)
    
        # Get option chain data for the mapped future only.
        # It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present.
        chain = slice.option_chains.get(symbol)
        if not chain or len(list(chain)) < 2:
            return
            
        # Separate the contracts by strike, as we need to access their strike.
        expiry = min([x.expiry for x in chain])
        sorted_by_strike = sorted([x.strike for x in chain])
        itm_strike = sorted_by_strike[0]
        otm_strike = sorted_by_strike[-1]
        
        # Use abstraction method to order a bull call spread to avoid manual error.
        option_strategy = OptionStrategies.bull_call_spread(symbol, itm_strike, otm_strike, expiry)
        self.buy(option_strategy, 1)

Note that since both the underlying Future and the Future Option are expiring on the same day and are cash-settling in most cases, Lean can exercise the Future Option into account cash automatically at expiry and we do not need to handle the option exercise/assignment event.

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: