Universes
Futures
Introduction
A Futures universe lets you select a basket of contracts for a single Future. LEAN models Future subscriptions as a universe of Future contracts. A Future universe is similar to an Option universe, except Future contracts don't have a strike price, so the universe filter primarily focuses on the contract expiration date.
Create Universes
To add a universe of Future contracts, in the Initialize
method, call the AddFuture
method. This method returns an Future
object, which contains the continuous contract Symbol
. The continuous contract Symbol
is the key to access the contracts in the FutureChain that LEAN passes to the OnData
method. When you create the Future subscription, save a reference to the continuous contract Symbol
so you can use it later in your algorithm.
_future = AddFuture(Futures.Currencies.BTC); _symbol = _future.Symbol;
self.future = self.AddFuture(Futures.Currencies.BTC) self.symbol = self.future.Symbol
The following table describes the AddFuture
method arguments:
Argument: |
Argument: |
Argument: |
Argument: |
Argument: |
Argument: |
Argument: |
Argument: |
Argument: |
Continous Contracts
By default, LEAN only subscribes to the continuous Future contract. A continuous Future contract represents a series of separate contracts stitched together to form a continuous price. If you need a lot of historical data to warm up an indicator, apply the indicator to the continuous contract price series. The Future
object has a Symbol
property and a Mapped
property. The price of the Symbol
property is the adjusted price of the continuous contract. The price of the Mapped
property is the raw price of the currently selected contract in the continuous contract series.
// Get the adjusted price of the continuous contract var adjustedPrice = Securities[_future.Symbol].Price; // Get the raw price of the currently selected contract in the continuous contract series var rawPrice = Securities[_future.Mapped].Price;
# Get the adjusted price of the continuous contract adjusted_price = self.Securities[self.future.Symbol].Price # Get the raw price of the currently selected contract in the continuous contract series raw_price = self.Securities[self.future.Mapped].Price
To configure how LEAN identifies the current Future contract in the continuous series and how it forms the adjusted price between each contract, provide dataMappingMode
, dataNormalizationMode
, and contractDepthOffset
arguments to the AddFuture
method. The Future
object that the AddFuture
method returns contains a Mapped
property that references the current contract in the continuous contract series. As the contracts roll over, the Mapped
property references the next contract in the series and you receive a SymbolChangedEvent
object in the OnData
method. The SymbolChangedEvent
references the old contract Symbol
and the new contract Symbol
.
public override void OnData(Slice slice) { foreach (var changedEvent in slice.SymbolChangedEvents.Values) { Log($"Symbol changed: {changedEvent.OldSymbol} -> {changedEvent.NewSymbol}"); } }
def OnData(self, slice: Slice) -> None: for changed_event in slice.SymbolChangedEvents.Values: self.Log(f"Contract rollover from {changed_event.OldSymbol} to {changed_event.NewSymbol}")
Data Normalization Modes
The dataNormalizationMode
argument defines how the price series of two contracts are stitched together when the contract rollovers occur. The following DataNormalizatoinMode
enumeration members are available for continuous contracts:
We use the entire Futures history to adjust historical prices. This process ensures you get the same adjusted prices, regardless of the backtest end date.
Data Mapping Modes
The dataMappingMode
argument defines when contract rollovers occur. The DataMappingMode
enumeration has the following members:
Contract Depth Offsets
The contractDepthOffset
argument defines which contract to use. 0 is the front month contract, 1 is the following back month contract, and 3 is the second back month contract.
Filter Contracts
By default, LEAN doesn't add any contracts to the FuturesChain it passes to the OnData
method. To add a universe of Future contracts, in the Initialize
method, call the SetFilter
method of the Future
object. The following table describes the available filter techniques:
Method | Description |
---|---|
SetFilter(int minExpiryDays, int maxExpiryDays) SetFilter(minExpiryDays: int, maxExpiryDays: int) | Selects the contracts that expire within the range you set. |
SetFilter(Func<FutureFilterUniverse, FutureFilterUniverse> universeFunc) SetFilter(universeFunc: Callable[[FutureFilterUniverse], FutureFilterUniverse]) | Selects the contracts that a function selects. |
# Select the contracts which expire within 182 days self.future.SetFilter(0, 182) # Select the front month contract self.future.SetFilter(lambda future_filter_universe: future_filter_universe.FrontMonth())
// Select the contracts which expire within 182 days _future.SetFilter(0, 182); // Select the front month contract _future.SetFilter(futureFilterUniverse => futureFilterUniverse.FrontMonth());
The following table describes the filter methods of the FutureFilterUniverse
class:
Method | Description |
---|---|
StandardsOnly() | Selects standard contracts |
IncludeWeeklys() | Selects non-standard weekly contracts |
WeeklysOnly() | Selects weekly contracts |
FrontMonth() | Selects the front month contract |
BackMonths() | Selects the non-front month contracts |
BackMonth() | Selects the back month contracts |
Expiration(TimeSpan minExpiry, TimeSpan maxExpiry) Expiration(minExpiry: timedelta, maxExpiry: timedelta) | Selects contracts that expire within a range of dates relative to the current day |
Expiration(int minExpiryDays, int maxExpiryDays) Expiration(minExpiryDays: int, maxExpiryDays: 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(contractSelector: Callable[[List[Symbol]], List[Symbol]]) | Selects contracts that a selector function selects |
OnlyApplyFilterAtMarketOpen() | Instructs the engine to only filter contracts on the first time step of each market day |
The preceding methods return an FutureFilterUniverse
, so you can chain the methods together.
// Select the front month standard contracts _future.SetFilter(futureFilterUniverse => futureFilterUniverse.StandardsOnly().FrontMonth());
# Select the front month standard contracts self.future.SetFilter(lambda future_filter_universe: future_filter_universe.StandardsOnly().FrontMonth())
You can also define an isolated filter method.
// In Initialize _future.SetFilter(Selector); private FutureFilterUniverse Selector(FutureFilterUniverse futureFilterUniverse) { return futureFilterUniverse.StandardsOnly().FrontMonth(); }
# In Initialize self.future.SetFilter(self.contract_selector) def contract_selector(self, future_filter_universe: Callable[[FutureFilterUniverse], FutureFilterUniverse]) -> FutureFilterUniverse: return future_filter_universe.StandardsOnly().FrontMonth()
Some of the preceding filter methods only set an internal enumeration in the FutureFilterUniverse
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 FutureFilterUniverse
.
By default, LEAN adds contracts to the FutureChain
that pass the filter criteria at every time step in your algorithm. If a contract has been in the universe for a duration that matches the MinimumTimeInUniverse
setting and it no longer passes the filter criteria, LEAN removes it from the chain
Navigate Futures Chains
FuturesChain
objects represent an entire chain of contracts for a single underlying Future. They have the following properties:
To get the FuturesChain
, index the FuturesChains
property of the Slice
with the continuous contract Symbol
.
public override void OnData(Slice slice) { if (slice.FuturesChains.TryGetValue(_symbol, out var chain)) { // Example: Select the contract with the greatest open interest var contract = chain.OrderBy(x => x.OpenInterest).Last(); } }
def OnData(self, slice: Slice) -> None: chain = slice.FuturesChains.get(self.symbol) if chain: # Example: Select the contract with the greatest open interest contract = sorted(chain, key=lambda contract: contract.OpenInterest, reverse=True)[0]
You can also loop through the FuturesChains
property to get each FuturesChain
.
public override void OnData(Slice slice) { foreach (var kvp in slice.FuturesChains) { var continuousContractSymbol = kvp.Key; var chain = kvp.Value; } } public void OnData(FuturesChains futuresChains) { foreach (var kvp in futuresChains) { var continuousContractSymbol = kvp.Key; var chain = kvp.Value; } }
def OnData(self, slice: Slice) -> None: for continuous_contract_symbol, chain in slice.FuturesChains.items(): pass