From 2e1fbfcc07550dc79235aa7660f721b4808cb751 Mon Sep 17 00:00:00 2001 From: Alexandre Catarino Date: Fri, 8 Nov 2024 22:50:05 +0000 Subject: [PATCH] Improves Futures Examples --- .../01 Universes/99 Examples.html | 29 +++++----- .../02 Individual Contracts/99 Examples.html | 4 +- .../01 Universes/99 Examples.html | 56 +++++++++---------- .../12 Universes/06 Futures/99 Examples.html | 6 +- 4 files changed, 47 insertions(+), 48 deletions(-) diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/01 Universes/99 Examples.html b/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/01 Universes/99 Examples.html index 73342366b8..b7351ffc09 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/01 Universes/99 Examples.html +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/01 Universes/99 Examples.html @@ -12,7 +12,7 @@

Example 1: Rollover

var future = AddFuture(Futures.Indices.SP500EMini, extendedMarketHours: true); _future = future.Symbol; // We only want to hold position of the front month contract. - future.SetFilter((u) => u.OnlyApplyFilterAtMarketOpen().FrontMonth()); + future.SetFilter(u => u.FrontMonth()); } public override void OnSecuritiesChanged(SecurityChanges changes) @@ -40,7 +40,7 @@

Example 1: Rollover

future = self.add_future(Futures.Indices.SP_500_E_MINI, extended_market_hours=True) self._future = future.symbol # We only want to hold position of the front month contract. - future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month()) + future.set_filter(lambda u: u.front_month()) def on_securities_changed(self, changes: SecurityChanges) -> None: # Liquidate if expired (or not being the front month contract anymore) and exit universe. @@ -60,7 +60,7 @@

Example 2: Continuous Future Indicator

public class FutureExampleAlgorithm : QCAlgorithm
 {
-    private dynamic _future;
+    private Future _future;
 
     public override void Initialize()
     {
@@ -69,20 +69,20 @@ 

Example 2: Continuous Future Indicator

dataNormalizationMode: DataNormalizationMode.BackwardsRatio, extendedMarketHours: true); // We only want to hold position of the front month contract. - (_future as Future).SetFilter((u) => u.OnlyApplyFilterAtMarketOpen().FrontMonth()); + _future.SetFilter(u => u.FrontMonth()); // Create a 252-day EMA indicator as a trend estimator. - _future.ema = EMA(_future.Symbol, 252, Resolution.Daily); + ((dynamic)_future).ema = EMA(_future.Symbol, 252, Resolution.Daily); // Warm up the EMA indicator to make it readily available. - WarmUpIndicator((Symbol)_future.Symbol, (ExponentialMovingAverage)_future.ema); + WarmUpIndicator(_future.Symbol, _future.Get<ExponentialMovingAverage>("ema")); } public override void OnData(Slice slice) { // Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision. - if (slice.Bars.ContainsKey(_future.Symbol)) + if (slice.Bars.TryGetValue(_future.Symbol, out var bar)) { // Buy the mapped contract if the trend is estimated to go up (price above EMA). - if (_future.ema.Current.Value >= slice.Bars[_future.Symbol].Close) + if (_future.Get<ExponentialMovingAverage>("ema") >= bar.Close) { SetHoldings(_future.Mapped, 0.1m); } @@ -91,7 +91,7 @@

Example 2: Continuous Future Indicator

{ SetHoldings(_future.Mapped, -0.1m); } - } + } } public override void OnSecuritiesChanged(SecurityChanges changes) @@ -110,7 +110,7 @@

Example 2: Continuous Future Indicator

data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO, extended_market_hours=True) # We only want to hold position of the front month contract. - self._future.set_filter(lambda u: u.only_apply_filter_at_market_open().front_month()) + self._future.set_filter(lambda u: u.front_month()) # Create a 252-day EMA indicator as a trend estimator. self._future.ema = self.ema(self._future.symbol, 252, Resolution.DAILY) # Warm up the EMA indicator to make it readily available. @@ -118,9 +118,10 @@

Example 2: Continuous Future Indicator

def on_data(self, slice: Slice) -> None: # Ensure the TradeBar data is available for the Future. Only use updated price data to update the indicator and make trading decision. - if self._future.symbol in slice.bars: + bar = slice.bars.get(self._future.symbol) + if bar: # Buy the mapped contract if the trend is estimated to go up (price above EMA). - if self._future.ema.current.value >= slice.bars[self._future.symbol].close: + if self._future.ema.current.value >= bar.close: self.set_holdings(self._future.mapped, 0.1) # Short the mapped contract if the trend is estimated to go down (price below EMA). else: @@ -145,7 +146,7 @@

Example 3: Contango

var future = AddFuture(Futures.Metals.MicroGold, extendedMarketHours: true); _future = future.Symbol; // Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty. - future.SetFilter((u) => u.OnlyApplyFilterAtMarketOpen().Expiration(0, 183)); + future.SetFilter((u) => u.Expiration(0, 183)); } public override void OnData(Slice slice) @@ -183,7 +184,7 @@

Example 3: Contango

future = self.add_future(Futures.Metals.MICRO_GOLD, extended_market_hours=True) self._future = future.symbol # Limit the expiration to within 6 months, as the longer the expiration, the higher the price uncertainty. - future.set_filter(lambda u: u.only_apply_filter_at_market_open().expiration(0, 183)) + future.set_filter(lambda u: u.expiration(0, 183)) def on_data(self, slice: Slice) -> None: # Get Future chain only for the selected Future contract. diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/02 Individual Contracts/99 Examples.html b/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/02 Individual Contracts/99 Examples.html index eac2dc0bb1..52531359d7 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/02 Individual Contracts/99 Examples.html +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/06 Futures/01 Requesting Data/02 Individual Contracts/99 Examples.html @@ -33,10 +33,10 @@

Example 1: Add the Front-Month Contract

# Get all the contracts that are currently tradable. contract_symbols = self.future_chain_provider.get_future_contract_list(self._future.symbol, self.time) # Get the contract with the closest expiry. - self._contract_symbol = sorted(contract_symbols, key=lambda x: x.id.date)[0] + self._contract_symbol = min(contract_symbols, key=lambda x: x.id.date) # Add the Futures contract. self.add_future_contract(self._contract_symbol) # Plot the contract price. self.plot_indicator("Price", self.identity(self._contract_symbol, Resolution.DAILY)) self.set_end_date(self._contract_symbol.id.date)
-
+ \ No newline at end of file diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/07 Future Options/01 Requesting Data/01 Universes/99 Examples.html b/03 Writing Algorithms/03 Securities/99 Asset Classes/07 Future Options/01 Requesting Data/01 Universes/99 Examples.html index a86995c48d..8bea07d221 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/07 Future Options/01 Requesting Data/01 Universes/99 Examples.html +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/07 Future Options/01 Requesting Data/01 Universes/99 Examples.html @@ -18,32 +18,30 @@

Example 1: Call Spread

_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.IncludeWeeklys().CallSpread(5, 5, -5)); + 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. - if (!Portfolio.Invested && - slice.OptionChains.TryGetValue(symbol, out var chain)) - { - // It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present. - if (chain.Count() < 2) - { - return; - } + // 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 itmStrike = chain.Min(x => x.Strike); - var otmStrike = chain.Max(x => x.Strike); + // 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, chain.First().Expiry); - Buy(optionStrategy, 1); - } + // 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):
@@ -57,27 +55,29 @@ 

Example 1: Call Spread

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.include_weeklys().call_spread(5, 5, -5)) + 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 self.portfolio.invested and chain: - # It requires 2 contracts with different strikes to form a call spread, so we make sure at least 2 contracts are present. - if len(list(chain)) < 2: - return + if not chain or len(list(chain)) < 2: + return - # Separate the contracts by strike, as we need to access their strike. - sorted_by_strike = sorted([x.strike for x in chain]) - itm_strike = sorted_by_strike[0] - otm_strike = sorted_by_strike[-1] + # 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, otm_call.expiry) - self.buy(option_strategy, 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.

diff --git a/03 Writing Algorithms/12 Universes/06 Futures/99 Examples.html b/03 Writing Algorithms/12 Universes/06 Futures/99 Examples.html index da15af0077..bb3f306328 100644 --- a/03 Writing Algorithms/12 Universes/06 Futures/99 Examples.html +++ b/03 Writing Algorithms/12 Universes/06 Futures/99 Examples.html @@ -29,16 +29,14 @@

Example 2: Contracts Expiring Within One Week

public override void Initialize() { var future = AddFuture("ES"); - future.SetFilter(futureFilterUniverse => futureFilterUniverse.Expiration(0, 7).OnlyApplyFilterAtMarketOpen()); + future.SetFilter(futureFilterUniverse => futureFilterUniverse.Expiration(0, 7)); } }
class WeeklyFuturesAlgorithm(QCAlgorithm):
 
     def initialize(self):
         future = self.add_future("ES")
-        future.set_filter(
-            lambda future_filter_universe: future_filter_universe.expiration(0, 7).only_apply_filter_at_market_open()
-        )
+ future.set_filter(lambda future_filter_universe: future_filter_universe.expiration(0, 7))

Other Examples