Equity Options

Requesting Data

Introduction

Request Equity Options data in your algorithm to receive a feed of contract prices in the OnData method. For more information about the specific dataset we use for backtests, see the US Equity Options dataset listing. To trade Equity Options live, you can use the data feed from Interactive Brokers or Tradier. We currently only support American-style Options for US Equity Options.

Create Subscriptions

Before you can subscribe to an Option contract, you must configure the underlying Equity and get the contract Symbol.

Configure the Underlying Equity

If you want to subscribe to the underlying Equity in the Initialize method, follow these steps to configure the asset:

  1. Set the Equity data normalization to DataNormalizationMode.Raw.
  2. Set the underlying volatility model.
  3. Warm up the volatility model.
var equity = AddEquity("SPY", dataNormalizationMode: DataNormalizationMode.Raw);
_symbol = equity.Symbol;
equity.VolatilityModel = new StandardDeviationOfReturnsVolatilityModel(30);
SetWarmup(30, Resolution.Daily);
equity = self.AddEquity("SPY", dataNormalizationMode=DataNormalizationMode.Raw)
self.symbol = equity.Symbol
equity.VolatilityModel = StandardDeviationOfReturnsVolatilityModel(30)
self.SetWarmup(30, Resolution.Daily)

If your algorithm has a dynamic universe of Equities, follow these steps to configure the underlying asset:

  1. In the Initialize method, set the universe data normalization mode to DataNormalizationMode.Raw.
  2. Before you add the Option contract subscription, set the underlying volatility model.
  3. If you trade Options for every Equity in the universe, add this logic to a security initializer.

  4. Warm up the volatility model
// In Initialize
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
var seeder = SecuritySeeder.Null;
SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, seeder, this));


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 and warm up the volatility model
        if (security.Type == SecurityType.Equity)
        {
            security.VolatilityModel = new StandardDeviationOfReturnsVolatilityModel(30);
            foreach (var tradeBar in _algorithm.History(security.Symbol, 30, Resolution.Daily))
            {
                security.VolatilityModel.Update(security, tradeBar);
            }
        }
    }
}
# In Initialize
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
seeder = SecuritySeeder.Null
self.SetSecurityInitializer(MySecurityInitializer(self.BrokerageModel, seeder, self))


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
        super().Initialize(security)

        # Next, set and warm up the volatility model
        if security.Type == SecurityType.Equity:
            security.VolatilityModel = StandardDeviationOfReturnsVolatilityModel(30)
            trade_bars = self.algorithm.History[TradeBar](security.Symbol, 30, Resolution.Daily)
            for trade_bar in trade_bars:
                security.VolatilityModel.Update(security, trade_bar)

Get Contract Symbols

To subscribe to an Option contract, you need the contract Symbol. You can get the contract Symbol from the CreateOption method or from the OptionChainProvider. If you use the CreateOption method, you need to provide the details of an existing contract.

_contractSymbol = QuantConnect.Symbol.CreateOption(_symbol, Market.USA,
    OptionStyle.American, OptionRight.Call, 365, new DateTime(2022, 6, 17));
self.contract_symbol = Symbol.CreateOption(self.symbol, Market.USA,
    OptionStyle.American, OptionRight.Call, 365, datetime(2022, 6, 17))

Another way to get an Option contract Symbol is to use the OptionChainProvider. The GetOptionContractList method of OptionChainProvider returns a list of Symbol objects that reference the available Option contracts for a given underlying Equity on a given date. To filter and select contracts, you can use the following properties of each Symbol object:

PropertyDescription
ID.DateThe expiration date of the contract.
ID.StrikePriceThe strike price of the contract.
ID.OptionRight The contract type. The OptionRight enumeration has the following members:
ID.OptionStyle The contract style. The OptionStyle enumeration has the following members:
var contractSymbols = OptionChainProvider.GetOptionContractList(_symbol, Time);
var expiry = contractSymbols.Select(symbol => symbol.ID.Date).Min();
var filteredSymbols = contractSymbols.Where(symbol => symbol.ID.Date == expiry && symbol.ID.OptionRight == OptionRight.Call);
_contractSymbol = filteredSymbols.OrderByDescending(symbol => symbol.ID.StrikePrice).Last();
contract_symbols = self.OptionChainProvider.GetOptionContractList(self.symbol, self.Time)
expiry = min([symbol.ID.Date for symbol in contract_symbols])
filtered_symbols = [symbol for symbol in contract_symbols if symbol.ID.Date == expiry and symbol.ID.OptionRight == OptionRight.Call]
self.contract_symbol = sorted(filtered_symbols, key=lambda symbol: symbol.ID.StrikePrice)[0]

Subscribe to Contracts

To create an Equity Option contract subscription, pass the contract Symbol to the AddOptionContract method. Save a reference to the contract Symbol so you can easily access the Option contract in the OptionChain that LEAN passes to the OnData method. This method returns an Option object. To set the price model of the Option, set its PriceModel property.

var option = AddOptionContract(_contractSymbol);
option.PriceModel = OptionPriceModels.BjerksundStensland();
option = self.AddOptionContract(self.contract_symbol)
option.PriceModel = OptionPriceModels.BjerksundStensland()

The AddOptionContract method creates a subscription for a single Option contract and adds it to your user-defined universe. To create a dynamic universe of Option contracts, add an Equity Options universe or an Options Universe Selection model.

Warm Up Contract Prices

If you subscribe to an Option contract with AddOptionContract, you'll need to wait until the next Slice to receive data and trade the contract. To trade the contract in the same time step you subscribe to the contract, set the current price of the contract in a security initializer.

var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
SetSecurityInitializer(new MySecurityInitializer(BrokerageModel, seeder, this));
seeder = FuncSecuritySeeder(self.GetLastKnownPrices)
self.SetSecurityInitializer(MySecurityInitializer(self.BrokerageModel, seeder, self))

Supported Assets

To view the supported assets in the US Equities dataset, see the Data Explorer.

Resolutions

The following table shows the available resolutions and data formats for Equity Option contract subscriptions:

ResolutionTradeBarQuoteBarTrade TickQuote Tick
Tick

Second

Minutegreen checkgreen check
Hourgreen checkgreen check
Dailygreen checkgreen check

The default resolution for Option contract subscriptions is Resolution.Minute. To change the resolution, pass a resolution argument to the AddOptionContract method.

AddOptionContract(_contractSymbol, Resolution.Minute);
self.AddOptionContract(self.contract_symbol, Resolution.Minute)

To create custom resolution periods, see Consolidating Data.

Supported Markets

LEAN groups all of the US Equity exchanges under Market.USA. You don't need to pass a Market argument to the AddOptionContract method because the contract Symbol already contains the market.

Fill Forward

Fill forward means if there is no data point for the current slice, LEAN uses the previous data point. Fill forward is the default data setting. If you disable fill forward, you may get stale fills or you may see trade volume as zero.

To disable fill forward for a security, set the fillDataForward argument to false when you create the security subscription.

AddOptionContract(_contractSymbol, fillDataForward: false);
self.AddOptionContract(self.contract_symbol, fillDataForward=False)

Margin and Leverage

LEAN models buying power and margin calls to ensure your algorithm stays within the margin requirements. Options are already leveraged products, so you can't change their leverage.

Extended Market Hours

By default, your security subscriptions only cover regular trading hours. To subscribe to pre- and post-market trading hours for a specific asset, enable the extendedMarketHours argument when you create the security subscription.

AddOptionContract(_contractSymbol, extendedMarketHours: true);
self.AddOptionContract(self.contract_symbol, extendedMarketHours=True)

You only receive extended market hours data if you create the subscription with an intraday resolution. If you create the subscription with daily resolution, the daily bars only reflect the regular trading hours.

To view the schedule of regular and extended market hours, see Market Hours.

Remove Subscriptions

To remove a contract subscription that you created with AddOptionContract, call the RemoveOptionContract method. This method is an alias for RemoveSecurity.

RemoveOptionContract(_contractSymbol);
self.RemoveOptionContract(self.contract_symbol)

The RemoveOptionContract method cancels your open orders for the contract and liquidates your holdings.

Properties

The AddOptionContract method returns an Option object, which have the following properties:

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: