Universes
Equity Options
Create Universes
To add a universe of Equity Option contracts, in the Initializeinitialize method, call the AddOptionadd_option method.
This method returns an Option object, which contains the canonical Symbolsymbol.
You can't trade with the canonical Option Symbolsymbol, but save a reference to it so you can easily access the Option contracts in the OptionChain that LEAN passes to the OnDataon_data method.
public class BasicOptionAlgorithm : QCAlgorithm
{
private Symbol _symbol;
public override void Initialize()
{
UniverseSettings.Asynchronous = true;
var option = AddOption("SPY");
option.SetFilter(Filter);
_symbol = option.Symbol;
}
private OptionFilterUniverse Filter(OptionFilterUniverse universe)
{
return universe.Expiration(0, 7).Delta(0.35m, 0.75m);
}
public override void OnData(Slice data)
{
if (data.OptionChains.TryGetValue(_symbol, out var chain))
{
var contract = chain.OrderBy(x => x.Greeks.Delta).FirstOrDefault();
}
}
} class BasicOptionAlgorithm(QCAlgorithm):
def initialize(self):
self.universe_settings.asynchronous = True
option = self.add_option("SPY")
option.set_filter(self._filter)
self._symbol = option.symbol
def _filter(self, universe):
return universe.expiration(0, 7).delta(0.35, 0.75)
def on_data(self, data):
chain = data.option_chains.get(self._symbol)
if chain:
contract = sorted(chain, key=lambda x: (x.expiry, x.greeks.delta))[0]
The following table describes the AddOptionadd_option method arguments:
| Argument | Data Type | Description |
|---|---|---|
ticker | stringstr | The underlying Equity ticker. To view the supported underlying Equity tickers, see Supported Assets. |
resolution | Resolution?Resolution | The resolution of the market data. To view the supported resolutions, see Resolutions. The Equity resolution must be less than or equal to the Equity Option resolution. For example, if you set the Equity resolution to minute, then you must set the Equity Option resolution to minute, hour, or daily. |
market | stringstr | The underlying Equity market. |
fillForwardfill_forward | bool | If true, the current slice contains the last available data even if there is no data at the current time. |
leverage | decimalfloat | The leverage for this Equity. |
extendedMarketHoursextended_market_hours | bool | A flag that signals if LEAN should send data during pre- and post-market trading hours. |
If you don't set any of these parameters, LEAN uses the UniverseSettingsself.universe_settings values. See Set Universe Settings for more information.
If you add an Equity Option universe but don't have a subscription to the underlying Equity, LEAN automatically subscribes to the underlying Equity with the following settings:
| Setting | Value |
|---|---|
| Fill forward | Same as the Option universe |
| Leverage | 0 |
| Extended Market Hours | Same as the Option universe |
| Data Normalization | DataNormalizationMode.RawDataNormalizationMode.RAW |
If you already have a subscription to the underlying Equity but it's not RawRAW data normalization, LEAN automatically changes it to RawRAW.
Filter by Investment Strategy
Options trading strategies consist of simultaneously buying or selling one or more Option contracts of the same underlying Equity, but with different features.
// Example 1: Select a Straddle option.SetFilter(optionFilterUniverse => optionFilterUniverse.Straddle(30)); // Example 2: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor option.SetFilter(optionFilterUniverse => optionFilterUniverse.Strikes(-20, 20).Expiration(0, 30).IronCondor(30, 5, 10)); // Example 3: Select the 0DTE contracts that form an Strangle option.SetFilter(optionFilterUniverse => optionFilterUniverse.Expiration(0, 0).Strangle(30, 5, -10));
# Example 1: Select a Straddle option.set_filter(lambda option_filter_universe: option_filter_universe.straddle(30)) # Example 2: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor option.set_filter(lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 30).iron_condor(30, 5, 10)) # Example 3: Select the 0DTE contracts that form an Strangle option.set_filter(lambda option_filter_universe: option_filter_universe.expiration(0, 0).strangle(30, 5, -10))
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.
Filter by Implied Volatility and Greeks
Option price models compute the theoretical price of Option contracts, their implied volatility, and their Greek values. Theoretical prices can help you detect undervalued and overvalued contracts, implied volatility can provide you insight into the upcoming volatility of the underlying security, and Greek values can help you hedge your portfolio.
// Example 1: Select the contracts with delta between 0.25 and 0.75 option.SetFilter(optionFilterUniverse => optionFilterUniverse.Delta(0.25m, 0.75m)); // Example 2: Select the contracts (including weeklys) that expire in the next 90 days with implied volatility below 20% option.SetFilter(optionFilterUniverse => optionFilterUniverse.IV(0, 20).Expiration(0, 90)); // Example 3: Select the contracts (including weeklys) that expire in the next 30 days with implied volatility below 20% that forms an Iron Condor option.SetFilter(optionFilterUniverse => optionFilterUniverse.IV(0, 20).Expiration(0, 30).IronCondor(30, 5, 10));
# Example 1: Select the contracts with delta between 0.25 and 0.75 option.set_filter(lambda option_filter_universe: option_filter_universe.delta(0.25, 0.75)) # Example 2: Select the contracts (including weeklys) that expire in the next 90 days with implied volatility below 20% option.set_filter(lambda option_filter_universe: option_filter_universe.iv(0, 20).expiration(0, 90)) # Example 3: Select the contracts (including weeklys) that expire in the next 30 days with implied volatility below 20% that forms an Iron Condor option.set_filter(lambda option_filter_universe: option_filter_universe.iv(0, 20).expiration(0, 30).iron_condor(30, 5, 10))
The following table describes the filter methods of the OptionFilterUniverse class that select contract for a range of implied volatility, Greek values, and open interest:
IV(decimal min, decimal max)iv(min: float, max: float)ImpliedVolatility(decimal min, decimal max)implied_volatility(min: float, max: float) Selects a contract with implied volatility within the range you set. |
D(decimal min, decimal max)d(min: float, max: float)Delta(decimal min, decimal max)delta(min: float, max: float) Selects a contract with delta within the range you set. |
G(decimal min, decimal max)g(min: float, max: float)Gamma(decimal min, decimal max)gamma(min: float, max: float) Selects a contract with gamma within the range you set. |
R(decimal min, decimal max)r(min: float, max: float)Rho(decimal min, decimal max)rho(min: float, max: float) Selects a contract with rho within the range you set. |
V(decimal min, decimal max)v(min: float, max: float)Vega(decimal min, decimal max)vega(min: float, max: float) Selects a contract with vega within the range you set. |
T(decimal min, decimal max)t(min: float, max: float)Theta(decimal min, decimal max)theta(min: float, max: float) Selects a contract with theta within the range you set. |
OI(long min, long max)oi(min: int, max: int)OpenInterest(decimal min, decimal max)open_interest(min: float, max: float) Selects a contract with open interest within the range you set. |
The preceding methods return an OptionFilterUniverse, so you can chain the methods together.
To perform thorough filtering on the OptionFilterUniverse, define an isolated filter method.
// Select the put contracts with the lowest strike price.
option.SetFilter(Selector);
private OptionFilterUniverse Selector(OptionFilterUniverse optionFilterUniverse)
{
return universe
.Delta(0.5m, 1.5m)
.Gamma(0.0001m, 0.0006m)
.Vega(0.01m, 1.5m)
.Theta(-2.0m, -0.5m)
.Rho(0.5m, 3.0m)
.ImpliedVolatility(1.0m, 3.0m)
.OpenInterest(100, 500);
} # Select the put contracts with the lowest strike price.
option.set_filter(self._contract_selector)
def _contract_selector(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse:
return option_filter_universe \
.delta(0.5, 1.5) \
.gamma(0.0001, 0.0006) \
.vega(0.01, 1.5) \
.theta(-2.0, -0.5) \
.rho(0.5, 3.0) \
.implied_volatility(1, 3) \
.open_interest(100,500)
Filter by Other Contract Properties
To set a contract filter, in the Initializeinitialize method, call the SetFilterset_filter method of the Option object.
// Select contracts that have a strike price within 1 strike level above and below the underlying price option.SetFilter(minStrike: -1, maxStrike: 1); // Select contracts that expire within 30 days option.SetFilter(minExpiry: TimeSpan.FromDays(0), maxExpiry: TimeSpan.FromDays(30)); // Select contracts that have a strike price within 1 strike level and expire within 30 days option.SetFilter(minStrike: -1, maxStrike: 1, minExpiry: TimeSpan.FromDays(0), maxExpiry: TimeSpan.FromDays(30)); // Select call contracts option.SetFilter(optionFilterUniverse => optionFilterUniverse.CallsOnly());
# Select contracts that have a strike price within 1 strike level above and below the underlying price option.set_filter(min_strike=-1, max_strike=1) # Select contracts that expire within 30 days option.set_filter(min_expiry=timedelta(days=0), maxExpiry=timedelta(days=30)) # Select contracts that have a strike price within 1 strike level and expire within 30 days option.set_filter(min_strike=-1, max_strike=1, min_expiry=timedelta(days=0), maxExpiry=timedelta(days=30)) # Select call contracts option.set_filter(lambda option_filter_universe: option_filter_universe.calls_only())
The following table describes the available filter techniques:
SetFilter(int minStrike, int maxStrike)set_filter(minStrike: int, maxStrike: int) Selects the contracts that have a strike price within a minimum and maximum strike level relative to the underlying price. For example, say the underlying price is $302 and there are strikes at every $5. If you set |
SetFilter(TimeSpan minExpiry, TimeSpan maxExpiry)set_filter(minExpiry: timedelta, maxExpiry: timedelta) Selects the contracts that expire within the range you set. This filter runs asynchronously by default. |
SetFilter(int minStrike, int maxStrike, TimeSpan minExpiry, TimeSpan maxExpiry)set_filter(minStrike: int, maxStrike: int, minExpiry: timedelta, maxExpiry: timedelta) Selects the contracts that expire and have a strike within the range you set. This filter runs asynchronously by default. |
SetFilter(Func<OptionFilterUniverse, OptionFilterUniverse> universeFunc)set_filter(universeFunc: Callable[[OptionFilterUniverse], OptionFilterUniverse]) Selects the contracts that a function selects. |
The same filter methods are available on OptionChain objects, so you can reuse them to narrow down a chain you receive during the algorithm.
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. |
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.
// Example 1: Select the front month call contracts option.SetFilter(optionFilterUniverse => optionFilterUniverse.CallsOnly().FrontMonth()); // Example 2: Select the contracts (including weeklys) that expire in the next 90 days option.SetFilter(optionFilterUniverse => optionFilterUniverse.Strikes(-20, 20).Expiration(0, 90)); // Example 3: Select the contracts (including weeklys) that expire in the next 30 days that form an Iron Condor option.SetFilter(optionFilterUniverse => optionFilterUniverse.Strikes(-20, 20).Expiration(0, 30).IronCondor(30, 5, 10));
# Example 1: Select the front month call contracts option.set_filter(lambda option_filter_universe: option_filter_universe.calls_only().front_month()) # Example 2: Select the contracts (including weeklys) that expire in the next 90 days option.set_filter(lambda option_filter_universe: option_filter_universe.strikes(-20, 20).expiration(0, 90))
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 and 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.
Navigate Intraday Option Chains
OptionChain objects represent an entire chain of Option contracts for a single underlying security.
To get the OptionChain, index the OptionChainsoption_chains property of the Slice with the canonical Symbolsymbol. After you get the OptionChain, you can sort and filter the Option contracts in the chain.
public override void OnData(Slice slice)
{
// Try to get the OptionChain using the canonical symbol
if (slice.OptionChains.TryGetValue(_symbol, out var chain))
{
// Example: Find 5 put contracts that are closest to at-the-money (ATM) and have the farthest expiration
var contracts = chain
.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:
# Try to get the OptionChain using the canonical symbol
chain = slice.option_chains.get(self._symbol)
if chain:
# Example: Find 5 put contracts that are closest to at-the-money (ATM) and have the farthest expiration
contracts = [x for x in chain if x.right == OptionRight.PUT]
contracts = sorted(sorted(contracts, \
key = lambda x: abs(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 loop through the OptionChainsoption_chains property to get each OptionChain.
public override void OnData(Slice slice)
{
// Iterate all received Canonical Symbol-OptionChain key-value pairs
foreach (var kvp in slice.OptionChains)
{
var canoncialSymbol = kvp.Key;
var chain = kvp.Value;
var contracts = chain.Contracts;
}
} def on_data(self, slice: Slice) -> None:
# Iterate all received Canonical Symbol-OptionChain key-value pairs
for canonical_symbol, chain in slice.option_chains.items():
contracts = chain.contracts
Filter Chains
OptionChain objects provide the same filter methods as Option universe selection, with the same names and the same behavior.
Each method returns a new OptionChain and leaves the source chain unchanged, so you can chain the calls together.
// Select the call contracts that expire in 20-40 days and are within 3 strikes of the underlying price. var contracts = chain.CallsOnly().Expiration(20, 40).Strikes(-3, 3);
# Select the call contracts that expire in 20-40 days and are within 3 strikes of the underlying price. contracts = chain.calls_only().expiration(20, 40).strikes(-3, 3)
The contract property filters, the Greeks and implied volatility filters, and the Option strategy filters are all available. The strategy filters select the legs of the strategy, or return an empty chain when no set of contracts matches the criteria.
// Select the four legs of an Iron Condor that expires in at least 30 days. var legs = chain.IronCondor(30, 5, 10);
# Select the four legs of an Iron Condor that expires in at least 30 days. legs = chain.iron_condor(30, 5, 10)
To filter the chain with your own predicate, use LINQ's Where method.
To filter the chain with your own predicate, call the where method.
var liquidContracts = chain.Where(contract => contract.OpenInterest > 100);
liquid_contracts = chain.where(lambda contract: contract.open_interest > 100)
The StandardsOnlystandards_only and WeeklysOnlyweeklys_only methods of a chain apply to the contracts the chain already holds, so you can combine them with the expiration filters in any order.
In universe selection, these two filters always run last.
Select Contracts
To get a single contract from the chain, call the Selectselect method.
It returns the contract that best matches the criteria you provide, or nullNone when the chain holds no match.
// Get the put contract at 85% of the underlying price, from the expiration closest to 30 days out. var contract = chain.Select(OptionRight.Put, targetDte: 30, moneyness: -0.15m);
# Get the put contract at 85% of the underlying price, from the expiration closest to 30 days out. contract = chain.select(OptionRight.PUT, target_dte=30, moneyness=-0.15)
These methods take a target number of days to expiration and return the closest expiration within the optional minDtemin_dte and maxDtemax_dte window.
The Option strategy filters instead take a minimum number of days to expiration and return the first expiration at or after it.
The following table describes the contract selection methods of the OptionChain class:
Select(OptionRight? right, int? targetDte, int? minDte, int? maxDte, decimal moneyness)select(right: OptionRight = None, target_dte: int = None, min_dte: int = None, max_dte: int = None, moneyness: float = 0) Selects the contract with the strike closest to |
Pick(OptionRight? right, int? targetDte, int? minDte, int? maxDte, decimal moneyness)pick(right: OptionRight = None, target_dte: int = None, min_dte: int = None, max_dte: int = None, moneyness: float = 0) A synonym of the |
SelectByStrikeDistance(decimal strikeFromAtm, OptionRight? right, int? targetDte, int? minDte, int? maxDte)select_by_strike_distance(strike_from_atm: float, right: OptionRight = None, target_dte: int = None, min_dte: int = None, max_dte: int = None) Selects the contract with the strike closest to a signed distance from the underlying price, in price units. This is how the Option strategy filters express their strikes. |
SelectByDelta(decimal targetDelta, OptionRight? right, int? targetDte, int? minDte, int? maxDte)select_by_delta(target_delta: float, right: OptionRight = None, target_dte: int = None, min_dte: int = None, max_dte: int = None) Selects the contract with the absolute delta closest to the absolute target, so a 30 delta put is 0.3 or -0.3. Contracts without Greeks are ignored. |
AtTheMoney(OptionRight? right)at_the_money(right: OptionRight = None) Selects the contract with the strike closest to the underlying price. Ties go to the lower strike, then to the nearest expiration. |
ClosestExpiry(int? targetDte, int? minDte, int? maxDte)closest_expiry(target_dte: int = None, min_dte: int = None, max_dte: int = None) Returns the expiration date closest to the target number of days out, or |
At(DateTime expiry)at(expiry: datetime) Returns a new chain with the contracts of the given expiration date. The time of day is ignored. |
The expiration methods compose with the chain filters, so you can narrow a single expiration down further.
var expiry = chain.ClosestExpiry(targetDte: 45, minDte: 30, maxDte: 60); var contracts = chain.At(expiry.Value).PutsOnly().Strikes(-2, 0);
expiry = chain.closest_expiry(target_dte=45, min_dte=30, max_dte=60) contracts = chain.at(expiry).puts_only().strikes(-2, 0)
OptionChain objects also expose read-only views of their contracts: Callscalls and Putsputs, sorted by expiration and then strike; Expiriesexpiries, the distinct expiration dates in ascending order; and StrikePricesstrike_prices, the distinct strikes in ascending order.
StrikePricesstrike_prices is a StrikeList object, which adds the ClosestToclosest_to, FirstAbovefirst_above, and FirstBelowfirst_below methods.
Each one takes a reference price and returns nullNone when no strike matches.
var strike = chain.StrikePrices.FirstAbove(chain.Underlying.Price);
strike = chain.strike_prices.first_above(chain.underlying.price)
Properties
OptionChain objects have the following properties:
Navigate Daily Option Chains
To get the daily, pre-calculated Greeks and implied volaility of all the currently tradable contracts, call the OptionChainoption_chain method.
This method returns a collection of OptionUniverse objects, where each object represents a contract.
This method returns a DataHistory[OptionUniverse] object, which you can format into a DataFrame or iterate through.
Each row in the DataFrame and each OptionUniverse object represents a single contract.
The data this method returns contains information on all the currently tradable contracts, not just the contracts that pass your filter.
// In the initialize method, create a Scheduled Event to get the Option
// chain and rebalance the portfolio.
Schedule.On(DateRules.WeekStart(_symbol), TimeRules.AfterMarketOpen(_symbol, 1), Rebalance);
public void Rebalance()
{
foreach (var optionUniverse in OptionChain(_symbol))
{
var close = optionUniverse.Close;
var oi = optionUniverse.OpenInterest;
var delta = optionUniverse.Greeks.Delta;
}
}
# In the initialize method, create a Scheduled Event to get the Option
# chain and rebalance the portfolio.
self.schedule.on(
self.date_rules.week_start(self._symbol),
self.time_rules.after_market_open(self._symbol, 1),
self._rebalance
)
# Define the method.
def _rebalance(self):
daily_option_chain = self.option_chain(self._symbol, flatten=True)
# Get the DataFrame format.
df = daily_option_chain.data_frame
delta_by_symbol = df.delta
# Get the OptionUniverse objects format.
for option_universe in daily_option_chain:
close = option_universe.close
oi = option_universe.open_interest
delta = option_universe.greeks.delta
The OptionChainoption_chain method was previously known as the OptionChainProvider.GetOptionContractListoption_chain_provider.get_option_contract_list method.
OptionUniverse objects have the following properties:
Greeks and Implied Volatility
There are several ways to get the implied volatility and Greeks of contracts.
The Greeks and IV values in the filter function are the daily, pre-calculated values based on the end of the previous trading day.
public override void Initialize()
{
var option = AddOption("SPY");
option.SetFilter(universe => universe.Delta(0.3m, 0.7m).Expiration(0, 7));
} def initialize(self):
option = self.add_option("SPY")
option.set_filter(lambda universe: universe.delta(0.3, 0.7).expiration(0,7))
To calculate the values, we use our implementation of the forward tree pricing model, which accounts for the interest rate and dividend payments.
You can't customize the Greeks and IV values that the filter function receives. However, you can create indicators to customize how the Greeks and IV are calculated for the contracts already in your universe.
To override the default pricing model of the Option, set a pricing model. If you set a price model, it sets the price model of the individual contracts in the universe.
// Set PriceModel property to use the Binomial Cox-Ross-Rubinstein model to price the Options. option.PriceModel = OptionPriceModels.BinomialCoxRossRubinstein();
// Set price_model field to use the Binomial Cox-Ross-Rubinstein model to price the Options. option.price_model = OptionPriceModels.binomial_cox_ross_rubinstein()
To override the initial guess of implied volatility, set and warm up the underlying volatility model.
Historical Data
To get historical chains for an Equity Option, call the History<OptionUniverse>history[OptionUniverse] method with the canonical Option Symbol.
This method returns the entire Option chain for each trading day, not the subset of contracts that pass your universe filter.
public class OptionHistoryAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
var option = AddOption("SPY");
var history = History<OptionUniverse>(option.Symbol, 5);
foreach (var chain in history)
{
var endTime = chain.EndTime;
var filteredContracts = chain.Data
.Select(contract => contract as OptionUniverse)
.Where(contract => contract.Greeks.Delta > 0.3m);
foreach (var contract in filteredContracts)
{
var price = contract.Price;
var iv = contract.ImpliedVolatility;
}
}
}
} class OptionHistoryAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
option = self.add_option('SPY')
# DataFrame example:
history_df = self.history(option.symbol, 5, flatten=True)
# OptionUniverse objects example:
history = self.history[OptionUniverse](option.symbol, 5)
for chain in history:
end_time = chain.end_time
filtered_contracts = [c for c in chain if c.greeks.delta > 0.3]
for contract in filtered_contracts:
symbol = contract.symbol
expiry = contract.id.date
strike = contract.id.strike_price
price = contract.close
iv = contract.implied_volatility
The Greeks and IV values that you get from a history request of the Option universe are the daily, pre-calculated values based on the end of the previous trading day. To get the intraday values or to customize the Greeks and IV calculations, create some Option indicators.
The History<OptionUniverse> method represents each contract with an OptionUniverse object, which have the following properties:
Examples
The following examples demonstrate some common Equity 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 Option contracts for the SPY that fall within 3 strikes of the underlying price.
public class ZeroDTEOptionUniverseAlgorithm : QCAlgorithm
{
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 12, 31);
var option = AddOption("SPY");
option.SetFilter(u => u.Expiration(0, 0).Strikes(-3, 3));
}
} class ZeroDTEOptionUniverseAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
option = self.add_option('SPY')
option.set_filter(lambda u: u.expiration(0, 0).strikes(-3, 3))
For trading full examples of Equity Option Universe, please refer to the Securities > Equity Options > Requesting Data > Universes page.
Other Examples
For more examples, see the following algorithms: