Future Options


A Future Option universe lets you select a basket of Option contracts on the contracts in a Futures universe.

Create Universes

To add a universe of Future Option contracts, in the Initialize method, define a Future universe and then pass the canonical Symbol to the AddFutureOption method.

UniverseSettings.Asynchronous = true;
var future = AddFuture(Futures.Metals.Gold);
future.SetFilter(0, 90);
self.universe_settings.asynchronous = True
future = self.add_future(Futures.Metals.GOLD)
future.set_filter(0, 90)

The following table describes the AddFutureOption method arguments:

ArgumentData TypeDescriptionDefault Value
symbolSymbolThe continuous Future contract Symbol. To view the supported assets in the US Future Options dataset, see Supported Assets.
optionFilterFunc<OptionFilterUniverse, OptionFilterUniverse>Callable[[OptionFilterUniverse], OptionFilterUniverse]A function that selects Future Option contractsnullNone

To override the default pricing model of the Option, set a pricing model in a security initializer.

// In Initialize
var seeder = SecuritySeeder.Null;
SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, seeder, this));

// Outside of the algorithm class
class MySecurityInitializer : BrokerageModelSecurityInitializer
    private QCAlgorithm _algorithm;

    public MySecurityInitializer(IBrokerageModel brokerageModel, ISecuritySeeder securitySeeder, QCAlgorithm algorithm)
        : base(brokerageModel, securitySeeder) 
        _algorithm = algorithm;
    public override void Initialize(Security security)
        // First, call the superclass definition
        // This method sets the reality models of each security using the default reality models of the brokerage model

        // Next, set the price model
        if (security.Type == SecurityType.FutureOption) // Option type
            security.PriceModel = OptionPriceModels.CrankNicolsonFD();
# In Initialize
seeder = SecuritySeeder.NULL
self.set_security_initializer(MySecurityInitializer(self.brokerage_model, seeder, self))

# Outside of the algorithm class
class MySecurityInitializer(BrokerageModelSecurityInitializer):

    def __init__(self, brokerage_model: IBrokerageModel, security_seeder: ISecuritySeeder, algorithm: QCAlgorithm) -> None:
        super().__init__(brokerage_model, security_seeder)
        self.algorithm = algorithm

    def initialize(self, security: Security) -> None:
        # First, call the superclass definition
        # This method sets the reality models of each security using the default reality models of the brokerage model

        # Next, set the price model
        if security.type == SecurityType.FUTURE_OPTION: # Option type
            security.price_model = OptionPriceModels.crank_nicolson_fd()

To override the initial guess of implied volatility, set and warm up the underlying volatility model.

Filter Contracts

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

  • Standard type (weeklies and non-standard contracts are not available)
  • 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 every time step in your algorithm. 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 OnData method.

To set a contract filter, in the Initialize method, pass a filter function to the AddFutureOption method. The following table describes the available filter techniques:

AddFutureOption(future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-1, 1));
self.add_future_option(future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-1, 1))

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

Strikes(int minStrike, int maxStrike)Strikes(minStrike: int, maxStrike: int)Selects contracts that are within minStrike strikes below the underlying price and maxStrike strikes above the underlying price
CallsOnly()Selects call contracts
PutsOnly()Selects put contracts
StandardsOnly()Selects standard contracts
IncludeWeeklys()Selects non-standard weeklys contracts
WeeklysOnly()Selects weekly contracts
FrontMonth()Selects the front month contract
BackMonths()Selects the non-front month contracts
BackMonth()Selects the back month contracts
Expiration(TimeSpan minExpiry, TimeSpan maxExpiry)Expiration(minExpiry: timedelta, maxExpiry: timedelta)Selects contracts that expire within a range of dates relative to the current day
Expiration(int minExpiryDays, int maxExpiryDays)Expiration(minExpiryDays: int, maxExpiryDays: 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(contractSelector: 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.

AddFutureOption(future.Symbol, optionFilterUniverse => optionFilterUniverse.Strikes(-1, 1).CallsOnly());
self.add_future_option(future.symbol, lambda option_filter_universe: option_filter_universe.strikes(-1, 1).calls_only())

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

# In 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);
# In Initialize
self.AddFutureOption(future.Symbol, self.contract_selector)

def contract_selector(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
    symbols = option_filter_universe.PutsOnly()
    strike = min([symbol.ID.StrikePrice for symbol in symbols])
    symbols = [symbol for symbol in symbols if symbol.ID.StrikePrice == 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.

Navigate Option Chains

OptionChain objects represent an entire chain of Option contracts for a single underlying security. They have the following properties:

To get the OptionChain, loop through the OptionChains property. After you get the OptionChain, you can sort and filter the Option contracts in the chain.

public override void OnData(Slice slice)
    foreach (var kvp in slice.OptionChains)
        var optionChain = kvp.Value;
        // Example: Find 5 put contracts that are closest to at-the-money (ATM) and have the farthest expiration
        var contracts = optionChain
            .Where(x => x.Right == OptionRight.Put)
            .OrderByDescending(x => x.Expiry)
            .ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))

        // Select the contract with the delta closest to -0.5
        var contract = contracts.OrderBy(x => Math.Abs(-0.5m - x.Greeks.Delta)).FirstOrDefault();
def OnData(self, slice: Slice) -> None:
    for _, option_chain in slice.OptionChains.items():
        # Example: Find 5 put contracts that are closest to at-the-money (ATM) and have the farthest expiration
        contracts = [x for x in option_chain if x.Right == OptionRight.Put]
        contracts = sorted(sorted(contracts, \
            key = lambda x: abs(option_chain.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True)[:5]

        # Select the contract with the delta closest to -0.5
        contract = sorted(contracts, key=lambda x: abs(-0.5 - x.Greeks.Delta))[0]

You can also iterate through the FuturesChains first.

public override void OnData(Slice slice)
    foreach (var kvp in slice.FuturesChains)
        var continuousContractSymbol = kvp.Key;
        var futuresChain = kvp.Value;
        // Select a Future Contract and create its canonical FOP Symbol
        var futuresContract = futuresChain.First();
        var canonicalFOPSymbol = QuantConnect.Symbol.CreateCanonicalOption(futuresContract.Symbol);
        if (slice.OptionChains.TryGetValue(canonicalFOPSymbol, out var fopChain))
            foreach (var contract in fopChain)
def OnData(self, slice: Slice) -> None:
    for continuous_future_symbol, futures_chain in slice.FuturesChains.items():
        # Select a Future Contract and create its canonical FOP Symbol
        futures_contract = [contract for contract in futures_chain][0]
        canonical_fop_symbol = Symbol.CreateCanonicalOption(futures_contract.Symbol)
        fop_chain = slice.OptionChains.get(canonical_fop_symbol)
        if fop_chain:
            for contract in fop_chain:

Selection Frequency

By default, Future Option universes run at the first time step of each day to select their contracts.

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: