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 Initializeinitialize method, define a Future universe and then pass the canonical Symbolsymbol to the AddFutureOptionadd_future_option method.
UniverseSettings.Asynchronous = true; var future = AddFuture(Futures.Metals.Gold); future.SetFilter(0, 90); AddFutureOption(future.Symbol);
self.universe_settings.asynchronous = True future = self.add_future(Futures.Metals.GOLD) future.set_filter(0, 90) self.add_future_option(future.symbol)
The following table describes the AddFutureOptionadd_future_option method arguments:
| Argument | Data Type | Description | Default Value |
|---|---|---|---|
symbol | Symbol | The continuous Future contract Symbol. To view the supported assets in the US Future Options dataset, see Supported Assets. | |
optionFilteroption_filter | Func<OptionFilterUniverse, OptionFilterUniverse>Callable[[OptionFilterUniverse], OptionFilterUniverse] | A function that selects Future Option contracts | nullNone |
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
base.Initialize(security);
// 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) -> None:
super().__init__(brokerage_model, security_seeder)
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
super().initialize(security)
# 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 OnDataon_data method.
To set a contract filter, in the Initializeinitialize method, pass a filter function to the AddFutureOptionadd_future_option 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(min_strike: int, max_strike: int) Selects contracts that are within |
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. This filter doesn't currently work. To add this functionality to our roadmap, react to this GitHub Issue with a thumbs up emoji. |
WeeklysOnly()weeklys_only() Selects weekly contracts. This filter doesn't currently work. To add this functionality to our roadmap, react to this GitHub Issue with a thumbs up emoji. |
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.
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.add_future_option(future.Symbol, self._contract_selector)
def _contract_selector(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
symbols = option_filter_universe.PutsOnly()
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.
Navigate Option Chains
OptionChain objects represent an entire chain of Option contracts for a single underlying security.
To get the OptionChain, loop through the OptionChainsoption_chains 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))
.Take(5);
// Select the contract with the delta closest to -0.5
var contract = contracts.OrderBy(x => Math.Abs(-0.5m - x.Greeks.Delta)).FirstOrDefault();
}
}
def on_data(self, slice: Slice) -> None:
for _, option_chain in slice.option_chains.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 FuturesChainsfutures_chains 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 on_data(self, slice: Slice) -> None:
for continuous_future_symbol, futures_chain in slice.futures_chains.items():
# Select a Future Contract and create its canonical FOP Symbol
futures_contract = [contract for contract in futures_chain][0]
canonical_fop_symbol = Symbol.create_canonical_option(futures_contract.symbol)
fop_chain = slice.option_chains.get(canonical_fop_symbol)
if fop_chain:
for contract in fop_chain:
pass
OptionChain objects have the following properties:
Historical Data
To get historical Future Option universe data, call the historyHistory<FutureUniverse> method with the canoncial Option Symbol.
This method returns the all the available contracts for each trading day, not the subset of contracts that pass your universe filter.
The return type depends on how you call the method.
public class FutureOptionHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
// Select a Futures contract.
var future = AddFuture(Futures.Indices.SP500EMini);
var futuresContract = FuturesChain(future.Symbol).First();
// Create the canoncial Option Symbol for this Futures contract.
var canonical = QuantConnect.Symbol.CreateCanonicalOption(futuresContract.Symbol);
// Get the historical Option universe data for this Futures contract.
var history = History<OptionUniverse>(canonical, 5);
foreach (var universe in history)
{
var endTime = universe.EndTime;
foreach (OptionUniverse contract in universe)
{
var symbol = contract.Symbol;
var expiry = contract.ID.Date;
var price = contract.Close;
}
}
}
} class FutureOptionsHistoryAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 19)
self.set_end_date(2024, 12, 31)
# Select a Futures contract.
future = self.add_future(Futures.Indices.SP_500_E_MINI)
futures_contract = list(self.futures_chain(future.symbol))[0]
# Create the canoncial Option Symbol for this Futures contract.
canonical = Symbol.create_canonical_option(futures_contract.symbol)
# Get the historical Option universe data for this Futures contract.
# DataFrame example:
history_df = self.history(OptionUniverse, canonical, 3, flatten=True)
# Series example:
history_series = self.history(OptionUniverse, canonical, 3, flatten=False)
# OptionUniverse example:
history = self.history[OptionUniverse](canonical, 3)
for universe in history:
end_time = universe.end_time
for contract in universe:
symbol = contract.symbol
expiry = contract.id.date
price = contract.close
The method represents each contract with a OptionUniverse object, which have the following properties:
Examples
The following examples demonstrate some common Future Option universes.
Example 1: 0DTE Contracts
0DTE Options are Option contracts that expire on the same day you trade them. The following algorithm selects 0DTE Future Option contracts for the E-mini S&P 500 that fall within 3 strikes of the underlying price.
public class ZeroDTEFutureOptionUniverseAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
var future = AddFuture(Futures.Indices.SP500EMini);
future.SetFilter(0, 90);
AddFutureOption(
future.Symbol,
u => u.IncludeWeeklys().Expiration(0, 0).Strikes(-3, 3)
);
}
} class ZeroDTEFutureOptionUniverseAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
future = self.add_future(Futures.Indices.SP_500_E_MINI)
future.set_filter(0, 90)
self.add_future_option(
future.symbol,
lambda u: u.include_weeklys().expiration(0, 0).strikes(-3, 3)
)
For full trading examples of Future Options, see Examples .