Universes

Future Options

Introduction

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.

var future = AddFuture(Futures.Metals.Gold);
future.SetFilter(0, 90);
AddFutureOption(future.Symbol);
future = self.AddFuture(Futures.Metals.Gold)
future.SetFilter(0, 90)
self.AddFutureOption(future.Symbol)

The following table describes the AddFutureOption method arguments:

ArgumentData TypeDescriptionDefault Value
symbolSymbolThe Future canonical symbol
optionFilterFunc<OptionFilterUniverse, OptionFilterUniverse>Callable[[OptionFilterUniverse], OptionFilterUniverse]A function that selects Future Option contractsnullNone

To set the price model of the Options, set their PriceModel property in a security initializer.

//In Initialize
SetSecurityInitializer(CustomSecurityInitializer);

private void CustomSecurityInitializer(Security security)
{
    if (security.Type == SecurityType.FutureOption)
    {
        security.PriceModel = OptionPriceModels.CrankNicolsonFD();
    }
}
#In Initialize
self.SetSecurityInitializer(self.CustomSecurityInitializer)

def CustomSecurityInitializer(self, security: Security) -> None:
    if security.Type == SecurityType.FutureOption:
        security.PriceModel = OptionPriceModels.CrankNicolsonFD()

Filter Contracts

By default, LEAN adds all of the available Future Option contracts to the Slice it passes to the OnData method. To narrow down the universe of contracts, pass a filter function to the AddFutureOption method.

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

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

MethodDescription
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
OnlyApplyFilterAtMarketOpen()Instructs the engine to only filter contracts on the first time step of each market day

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

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

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)

By default, LEAN adds contracts to the OptionChain that pass the filter criteria at every time step in your algorithm. LEAN removes contracts from the OptionChain that don't pass the filter criteria at different times, depending on the execution mode. In backtests, if a contract in the chain doesn't pass the filter criteria, LEAN removes it from the chain at the start of the next day. In live trading, LEAN removes these contracts from the chain every 15 minutes to avoid subscription restrictions from brokerages.

Navigate Option Chains

OptionChain objects represent and 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 chain = kvp.Value;
        // Example: Find an at-the-money (ATM) put contract with the farthest expiration
        var contract = optionChain
            .OrderByDescending(x => x.Expiry)
            .ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
            .ThenByDescending(x => x.Right)
            .FirstOrDefault();
    }
}

public void OnData(OptionChains optionChains)
{
    foreach (var kvp in optionChains)
    {
        var chain = kvp.Value;
    }
}
def OnData(self, slice: Slice) -> None:
    for _, chain in slice.OptionChains.items():
        # Example: Find an at-the-money (ATM) put contract with the farthest expiration
        contract = sorted(sorted(sorted(chain, \
            key = lambda x: abs(chain.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True), \
            key = lambda x: x.Right, reverse=True)[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 = Symbol.CreateCanonicalOption(futuresContract.Symbol);
        if (slice.OptionChains.TryGetValue(canonicalFOPSymbol, out var optionChain))
        {
            foreach (var optionContract in optionChain)
            {
                // 
            }
        }
    }
}
public void OnData(FuturesChains futuresChains)
{
    foreach (var kvp in futuresChains)
    {
        var continuousContractSymbol = kvp.Key;
        var futuresChain = kvp.Value;
    }
}
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)
        option_chain = slice.OptionChains.get(canonical_fop_symbol)
        if option_chain:
            for contract in option_chain:
                pass

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: