Requesting Data
Universes
Introduction
The AddFutureOption
add_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 Initialize
initialize
method, call the AddFutureOption
add_future_option
method. Pass the optionFilter
option_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 AddFutureOption
add_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 Initialize
initialize
method, call the AddFutureOption
add_future_option
method and pass the optionFilter
option_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 |
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 OnData
on_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 AddFutureOption
self.add_future_option
with the underlying Symbol
and the filtering function. We use CallSpread
call_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.