AlgoSeek
US Future Options
Introduction
The US Future Options dataset by AlgoSeek provides Option data on US Future contracts, including prices, strikes, and expires. The data covers 16 Monthly Future contracts, starts in January 2012, and is delivered on a minute frequency. This dataset is created by monitoring the trading activity on the CME, CBOT, NYMEX, and COMEX markets.
This dataset depends on the following datasets:
- US Future Option Universe - data on the available US Future Options contracts and their current Open Interest.
- US Futures Security Master - data to construct continuous Futures.
- US Future Universe - data on the available US Future contracts, their daily trading volume, and Open Interest.
- US Futures - data on the underlying Futures contracts, including price, volume, Open Interest, and expiry.
For more information about the US Future Options dataset, including CLI commands and pricing, see the dataset listing.
About the Provider
AlgoSeek is a leading historical intraday US market data provider offering the most comprehensive and detailed market data and analytics products in the financial industry covering equities, futures, options, cash forex, and cryptocurrencies. AlgoSeek data is built for quantitative trading and machine learning. For more information about AlgoSeek, visit algoseek.com.
Getting Started
The following snippet demonstrates how to request data from the US Future Options dataset:
future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE) future.set_filter(0, 90) self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
var future = AddFuture(Futures.Metals.Gold, Resolution.Minute); future.SetFilter(0, 90); AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5));
Data Summary
The following table describes the dataset properties:
Property | Value |
---|---|
Start Date | January 2012 |
Asset Coverage | 16 Monthly Future Contracts. Standard expires only*. |
Data Density | Dense |
Resolution | Minute, Hourly, & Daily |
Timezone | New York |
Market Hours | Regular and Extended |
Requesting Data
To add US Future Options data to your algorithm, call the AddFutureOption
add_future_option
method.
class FutureOptionDataAlgorithm(QCAlgorithm): def initialize(self) -> None: self.set_start_date(2020, 1, 28) self.set_end_date(2020, 6, 1) self.set_cash(100000) self.universe_settings.asynchronous = True future = self.add_future(Futures.Metals.GOLD, Resolution.MINUTE) future.set_filter(0, 90) self.add_future_option(future.symbol, lambda universe: universe.strikes(-5, +5))
public class FutureOptionDataAlgorithm : QCAlgorithm { public override void Initialize() { SetStartDate(2020, 1, 28); SetEndDate(2020, 6, 1); SetCash(100000); UniverseSettings.Asynchronous = True; var future = AddFuture(Futures.Metals.Gold, Resolution.Minute); future.SetFilter(0, 90); AddFutureOption(future.Symbol, universe => universe.Strikes(-5, +5)); } }
The Future resolution must be less than or equal to the Future Option resolution. For example, if you set the Future resolution to minute, then the Future Option resolution must be minute, hour, or daily.
For more information about creating Future Options subscriptions, see Requesting Data or Future Options Universes.
Accessing Data
To get the current Future Options data, iterate through the OptionChains
option_chains
property of the current Slice
. Slice objects deliver unique events to your algorithm as they happen, but the Slice
may not contain data for your Future Options at every time step.
def on_data(self, slice: Slice) -> None: for canonical_fop_symbol, chain in slice.option_chains.items(): for contract in chain: self.log(f"{contract.symbol} price at {slice.time}: {contract.last_price}")
public override void OnData(Slice slice) { foreach (var kvp in slice.OptionChains) { var canonicalFOPSymbol = kvp.Key; var chain = kvp.Value; foreach (var contract in chain) { Log($"{contract.Symbol} price at {slice.Time}: {contract.LastPrice}"); } } }
You can also iterate through the FuturesChains
futures_chains
in the current Slice
first.
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) option_chain = slice.option_chains.get(canonical_fop_symbol) if option_chain: for fop_contract in option_chain: self.log(f"{fop_contract.symbol} price at {slice.time}: {fop_contract.last_price}")
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 optionChain)) { foreach (var fopContract in optionChain) { Log($"{fopContract.Symbol} price at {slice.Time}: {fopContract.LastPrice}"); } } } }
For more information about accessing Future Options data, see Handling Data.
Historical Data
You can get historical US Future Options data in an algorithm and the Research Environment.
Historical Data In Algorithms
To get historical US Future Options data in an algorithm, call the History
history
method with the Future Option contract Symbol
. If there is no data in the period you request, the history result is empty.
# DataFrame of trade and quote data history_df = self.history(contract.symbol, 100, Resolution.MINUTE) # DataFrame of open interest data history_oi_df = self.history(OpenInterest, contract.symbol, 100, Resolution.MINUTE) # TradeBar objects history_trade_bars = self.history[TradeBar](contract.symbol, 100, Resolution.MINUTE) # QuoteBar objects history_quote_bars = self.history[QuoteBar](contract.symbol, 100, Resolution.MINUTE) # OpenInterest objects history_oi = self.history[OpenInterest](contract.symbol, 100, Resolution.MINUTE)
// TradeBar objects var historyTradeBars = History(contract.Symbol, 100, Resolution.Minute); // QuoteBar objects var historyQuoteBars = History<QuoteBar>(contract.Symbol, 100, Resolution.Minute); // OpenInterest objects var historyOpenInterest = History<OpenInterest >(contract.Symbol, 100, Resolution.Minute);
For more information about historical data in algorithms, see History Requests.
Historical Data In Research
To get historical US Future Options data in the Research Environment, call the History
history
or OptionHistory
option_history
method. The History
history
method returns the price, volume, and open interest history for some given Future Option contract(s). The OptionHistory
option_history
method returns the price and volume history for the contracts that pass your daily universe filter.
qb = QuantBook() future = qb.add_future(Futures.Indices.SP_500_E_MINI) start_date = datetime(2024, 1, 2) future_contract_symbol = sorted( qb.future_chain_provider.get_future_contract_list(future.symbol, start_date), key=lambda s: s.id.date )[0] history = qb.option_history( future_contract_symbol, start_date, future_contract_symbol.id.date, Resolution.HOUR ) history_df = history.data_frame expiries = history.get_expiry_dates() strikes = history.get_strikes()
var qb = new QuantBook(); var future = qb.AddFuture(Futures.Indices.SP500EMini); var startDate = new DateTime(2024, 1, 2); var futureContractSymbol = qb.FutureChainProvider.GetFutureContractList(future.Symbol, startDate) .OrderBy(x => x.ID.Date) .First(); var history = qb.OptionHistory( futureContractSymbol, startDate, futureContractSymbol.ID.Date, Resolution.Hour ); var contracts = history .SelectMany(x => x.OptionChains.SelectMany(y => y.Value.Contracts.Keys)) .Distinct().ToList(); var expiries = contracts.Select(x => x.ID.Date).Distinct().ToList(); var strikes = contracts.Select(x => x.ID.StrikePrice).Distinct().ToList();
To get historical data for arbitrary US Equity Option contracts instead of just the that pass your universe filter, call the History
history
method like you would in an algorithm, but on the QuantBook
object. For more information about historical data in the Research Environment, see Key Concepts.
Supported Assets
The following list shows the available (16) Futures Options:
: Class III Milk Futures (CME: DC)Futures.Dairy.ClassIIIMilk
Futures.Dairy.CLASS_III_MILK
: Crude Oil WTI Futures (NYMEX: LO | Underlying: CL)Futures.Energy.CrudeOilWTI
Futures.Energy.CRUDE_OIL_WTI
: Gasoline RBOB Futures (NYMEX: OB | Underlying: RB)Futures.Energy.Gasoline
Futures.Energy.GASOLINE
: Heating Oil Futures (NYMEX: OH | Underlying: HO)Futures.Energy.HeatingOil
Futures.Energy.HEATING_OIL
: Natural Gas Futures (NYMEX: ON | Underlying: NG)Futures.Energy.NaturalGas
Futures.Energy.NATURAL_GAS
: 10Y U.S. Treasury Note Futures (CBOT: OZN | Underlying: ZN)Futures.Financials.Y10TreasuryNote
Futures.Financials.Y_10_TREASURY_NOTE
: 2Y U.S. Treasury Note Futures (CBOT: OZT | Underlying: ZT)Futures.Financials.Y2TreasuryNote
Futures.Financials.Y_2_TREASURY_NOTE
: 30Y U.S. Treasury Bond Futures (CBOT: OZB | Underlying: ZB)Futures.Financials.Y30TreasuryBond
Futures.Financials.Y_30_TREASURY_BOND
: Corn Futures (CBOT: OZC | Underlying: ZC)Futures.Grains.Corn
Futures.Grains.CORN
: Soybeans Futures (CBOT: OZS | Underlying: ZS)Futures.Grains.Soybeans
Futures.Grains.SOYBEANS
: Default wheat contract is SRWWheat (CBOT: OZW | Underlying: ZW)Futures.Grains.Wheat
Futures.Grains.WHEAT
: E-mini NASDAQ 100 Futures (CME: NQ)Futures.Indices.NASDAQ100EMini
Futures.Indices.NASDAQ_100_E_MINI
: E-mini S&P 500 Futures (CME: ES)Futures.Indices.SP500EMini
Futures.Indices.SP_500_E_MINI
: Copper Futures (COMEX: HXE | Underlying: HG)Futures.Metals.Copper
Futures.Metals.COPPER
: Gold Futures (COMEX: OG | Underlying: GC)Futures.Metals.Gold
Futures.Metals.GOLD
: Silver Futures (COMEX: SO | Underlying: SI)Futures.Metals.Silver
Futures.Metals.SILVER
Example Applications
The US Future Options dataset enables you to accurately design Future Option strategies. Examples include the following strategies:
- Selling out of the money Future Option contracts to collect the premium that the Option buyer pays
- Buying put Options to hedge against downward price movement in Future contracts you bought
- Exploiting arbitrage opportunities that arise when the price of Option contracts deviates from their theoretical value
Classic Algorithm Example
The following example demonstrates a weekly-renewing covered call strategy to collect credit of selling the option. It filters the ATM call contract that expires within the current week at week start using SetFilter
filtering function.
from AlgorithmImports import * class FutureOptionExampleAlgorithm(QCAlgorithm): def initialize(self) -> None: # Subscribe the underlying since the updated price is needed for filtering 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) # Filter the underlying continuous Futures to narrow the FOP spectrum self.underlying.set_filter(0, 182) # Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week self.add_future_option(self.underlying.symbol, lambda u: u.include_weeklys().calls_only().expiration(0, 5)) def on_data(self, slice: Slice) -> None: # Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol symbol = Symbol.create_canonical_option(self.underlying.mapped) # Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts chain = slice.option_chains.get(symbol) if not self.portfolio.invested and chain: # Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time expiry = max(x.expiry for x in chain) atm_call = sorted([x for x in chain if x.expiry == expiry], key=lambda x: abs(x.strike - x.underlying_last_price))[0] # Use abstraction method to order a covered call to avoid manual error option_strategy = OptionStrategies.covered_call(symbol, atm_call.strike,expiry) self.buy(option_strategy, 1) def on_securities_changed(self, changes: SecurityChanges) -> None: for security in changes.added_securities: if security.type == SecurityType.FUTURE_OPTION: # Historical data history = self.history(security.symbol, 10, Resolution.MINUTE) self.debug(f"We got {len(history)} from our history request for {security.symbol}")
public class FutureOptionExampleAlgorithm : QCAlgorithm { private Future _underlying; public override void Initialize() { // Subscribe the underlying since the updated price is needed for filtering _underlying = AddFuture(Futures.Indices.SP500EMini, extendedMarketHours: True, dataMappingMode: DataMappingMode.OpenInterest, dataNormalizationMode: DataNormalizationMode.BackwardsRatio, contractDepthOffset: 0); // Filter the underlying continuous Futures to narrow the FOP spectrum _underlying.SetFilter(0, 182); // Filter for the current-week-expiring calls to formulate a covered call that expires at the end of week AddFutureOption(_underlying.Symbol, (u) => u.IncludeWeeklys().CallsOnly().Expiration(0, 5)); } public override void OnData(Slice slice) { // Create canonical symbol for the mapped future contract, since option chains are mapped by canonical symbol var symbol = QuantConnect.Symbol.CreateCanonicalOption(_underlying.Mapped); // Get option chain data for the mapped future, as both the underlying and FOP have the highest liquidity among all other contracts if (!Portfolio.Invested && slice.OptionChains.TryGetValue(symbol, out var chain)) { // Obtain the ATM call that expires at the end of week, such that both underlying and the FOP expires the same time var expiry = chain.Max(x => x.Expiry); var atmCall = chain.Where(x => x.Expiry == expiry) .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice)) .First(); // Use abstraction method to order a covered call to avoid manual error var optionStrategy = OptionStrategies.CoveredCall(symbol, atmCall.Strike, expiry); Buy(optionStrategy, 1); } } public override void OnSecuritiesChanged(SecurityChanges changes) { foreach (var security in changes.AddedSecurities) { if (security.Type == SecurityType.FutureOption) { // Historical data var history = History(security.Symbol, 10, Resolution.Minute); Debug($"We got {history.Count()} from our history request for {security.Symbol}"); } } } }
Framework Algorithm Example
The following example demonstrates a daily renewing speculation trade on upward movement of Gold with FOP using algorithm framework. Using FOP, traders can achieve lower cost to get similar absolute profit, given the FOP is selected to be deep ITM with high Delta value.
from AlgorithmImports import * class USFuturesDataAlgorithm(QCAlgorithm): def initialize(self) -> None: self.set_start_date(2013, 12, 20) self.set_end_date(2014, 2, 20) self.set_cash(100000) # Asynchronous to save computation resources self.universe_settings.asynchronous = True # Override an option universe selection model to select the FOPs self.set_universe_selection(GoldFOPUniverseSelectionModel()) # Handle the FOP trading logic in an alpha model self.add_alpha(ConstantFutureOptionsAlphaModel()) # To order a single contract per insight, use a custom portfolio construction model self.set_portfolio_construction(SingleSharePortfolioConstructionModel()) class GoldFOPUniverseSelectionModel(OptionUniverseSelectionModel): # Daily renewed universe since option contract list is updated on a daily basis def __init__(self,) -> None: super().__init__(timedelta(1), self.select_fop_symbols) def select_fop_symbols(self, algorithm: QCAlgorithm, utcTime: datetime) -> List[Symbol]: # Create the underlying symbol to get the FOP contracts later future_symbol = Symbol.create(Futures.Metals.GOLD, SecurityType.FUTURE, Market.COMEX) # Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest future_contract_list = algorithm.future_chain_provider.get_future_contract_list(future_symbol, algorithm.time) return [Symbol.create_canonical_option(x) for x in future_contract_list if x.id.date <= algorithm.time + timedelta(90)] def filter(self, option_filter_universe: OptionFilterUniverse) -> OptionFilterUniverse: # Filter for the ATM calls that expires latest (same expiry as the underlying) # +/-5 strike range buffer for price movement return option_filter_universe.back_month().strikes(-5, +5).calls_only(); class ConstantFutureOptionsAlphaModel(AlphaModel): # A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested option_contract_by_future_underlying_contract = {} def update(self, algorithm: QCAlgorithm, slice: Slice) -> List[Insight]: insights = [] for kvp in slice.option_chains: # Liquidate underlying Future contract after Option assignment underlying_future_contract = kvp.key.underlying if algorithm.portfolio[underlying_future_contract].invested: algorithm.insights.cancel([underlying_future_contract]) del self.option_contract_by_future_underlying_contract[underlying_future_contract] # Do not repeatly invest in the same underlying's FOP chain = [contract for contract in kvp.Value if algorithm.securities[contract.symbol].is_tradable)] if not chain or underlying_future_contract in self.option_contract_by_future_underlying_contract: continue # Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta contract = sorted(chain, key=lambda x: x.strike)[0] insights.append(Insight.price(contract.symbol, contract.expiry + timedelta(1), InsightDirection.UP)) self.option_contract_by_future_underlying_contract[underlying_future_contract] = contract return insights class SingleSharePortfolioConstructionModel(PortfolioConstructionModel): def create_targets(self, algorithm: QCAlgorithm, insights: List[Insight]) -> List[PortfolioTarget]: targets = [] for insight in insights: if algorithm.securities[insight.symbol].is_tradable: # Use integer target to create a portfolio target to trade a single contract targets.append(PortfolioTarget(insight.symbol, insight.direction)) return targets
public class FutureOptionDataAlgorithm : QCAlgorithm { public override void Initialize() { SetStartDate(2020, 1, 28); SetEndDate(2020, 6, 1); SetCash(100000); // Asynchronous to save computation resources UniverseSettings.Asynchronous = True; // Override an option universe selection model to select the FOPs AddUniverseSelection(new GoldFOPUniverseSelectionModel(this)); // Handle the FOP trading logic in an alpha model SetAlpha(new ConstantFutureOptionsAlphaModel()); // To order a single contract per insight, use a custom portfolio construction model SetPortfolioConstruction(new SingleSharePortfolioConstructionModel()); } } public class GoldFOPUniverseSelectionModel : OptionUniverseSelectionModel { // Daily renewed universe since option contract list is updated on a daily basis public GoldFOPUniverseSelectionModel(QCAlgorithm algorithm) : base(TimeSpan.FromDays(1), _ => OptionChainSymbolSelector(algorithm, _)) { } private static IEnumerable<Symbol> OptionChainSymbolSelector(QCAlgorithm algorithm, DateTime utcTime) { // Create the underlying symbol to get the FOP contracts later var futureSymbol = QuantConnect.Symbol.Create(Futures.Metals.Gold, SecurityType.Future, Market.COMEX); // Get all gold FOP contracts of the front month gold contract expiring within 3 months, since their liquidity is the highest return algorithm.FutureChainProvider.GetFutureContractList(futureSymbol, algorithm.Time) .Where(futureContractSymbol => futureContractSymbol.ID.Date <= algorithm.Time + TimeSpan.FromDays(90)) .Select(futureContractSymbol => QuantConnect.Symbol.CreateCanonicalOption(futureContractSymbol)); } protected override OptionFilterUniverse Filter(OptionFilterUniverse optionFilterUniverse) { // Filter for the ATM calls that expires latest (same expiry as the underlying) // +/-5 strike range buffer for price movement return optionFilterUniverse.BackMonth().Strikes(-5, +5).CallsOnly(); } } class ConstantFutureOptionsAlphaModel : AlphaModel { // A dictionary to cache the mapped FOP of the underlying Future for filtering wanted option chain data and check if invested private Dictionary<Symbol, OptionContract> optionContractByUnderlyingFutureContract = new Dictionary<Symbol, OptionContract>(); public override IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice slice) { var insights = new List<Insight>(); foreach (var kvp in slice.OptionChains) { // Liquidate underlying Future contract after Option assignment var underlyingFutureContract = kvp.Key.Underlying; if (algorithm.Portfolio[underlyingFutureContract].Invested) { algorithm.Insights.Cancel(new[] { underlyingFutureContract }); optionContractByUnderlyingFutureContract.Remove(underlyingFutureContract); } // Do not repeatly invest in the same underlying's FOP var chain = kvp.Value.Where(contract => algorithm.Securities[contract.Symbol].IsTradable); if (chain.Count() == 0 || optionContractByUnderlyingFutureContract.ContainsKey(underlyingFutureContract)) { continue; } // Select the Option contract with the lowest strike price to speculate trade the underlying with lowest cost and highest delta var contract = chain.MinBy(contract => contract.Strike); insights.Add(Insight.Price(contract.Symbol, contract.Expiry.AddDays(1), InsightDirection.Up)); optionContractByUnderlyingFutureContract.Add(kvp.Key.Underlying, contract); } return insights; } } class SingleSharePortfolioConstructionModel : PortfolioConstructionModel { public override IEnumerable<PortfolioTarget> CreateTargets(QCAlgorithm algorithm, Insight[] insights) { var targets = new List<PortfolioTarget>(); foreach (var insight in insights) { if (algorithm.Securities[insight.Symbol].IsTradable) { // Use integer target to create a portfolio target to trade a single contract targets.Add(new PortfolioTarget(insight.Symbol, (int) insight.Direction)); } } return targets; } }
Data Point Attributes
The US Future Options dataset provides TradeBar
, QuoteBar
, and OpenInterest
objects.
TradeBar Attributes
TradeBar
objects have the following attributes:
QuoteBar Attributes
QuoteBar
objects have the following attributes:
OpenInterest Attributes
OpenInterest
objects have the following attributes: