From 89860afd68c7f87eae96298c01c869d3693afa81 Mon Sep 17 00:00:00 2001 From: baobach <95854748+baobach@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:58:53 +0700 Subject: [PATCH 1/4] Fixing arrow symbols --- .../01 Universes/12 Examples.php | 73 ++++++++++++++++++- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php index a336876679..6fb9496b30 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php @@ -1,9 +1,74 @@ +

The following examples demonstrate some common practices for requesting Index Options universe data.

+

Example 1: Selecting for 0DTE Contracts

-

0DTE Options are Option contracts that expire on the same day you trade them. To create a universe with 0DTE Options, call the SetFilterset_filter method with the following argument:

+

0DTE Options are option contracts that expire on the same day they are traded. To create a universe with 0DTE options, call the SetFilter or set_filter method. In this example, we will select 0DTE contracts within 1 strike price level and a Delta between 0.25 and 0.75. Then, we will go long on the highest strike price call contract of the SPX index and hold until expiry.

-
option.SetFilter(u => u.IncludeWeeklys().Expiration(0, 0).Strikes(minStrike, maxStrike));
-
option.set_filter(lambda u: u.include_weeklys().expiration(0, 0).strikes(min_strike, max_strike))
-
+
private Option _option;
+
+public override void Initialize()
+{
+    SetStartDate(2023, 1, 1);
+    SetEndDate(2024, 1, 1);
+    SetCash(100000);
+
+    // Subscribe to the option chain.
+    _option = AddIndexOption("SPX", Resolution.Daily);
+
+    // Filter the option universe to only select 0DTE options.
+    _option.SetFilter(u => u.IncludeWeeklys().Expiration(0, 0).Strikes(-1, 1));
+
+    // Filter the option universe by Delta.
+    _option.SetFilter(optionFilterUniverse => optionFilterUniverse.Delta(0.25m, 0.75m));
+}
+
+public override void OnData(Slice slice)
+{
+    if (Portfolio.Invested)
+    {
+        return;
+    }
+
+    // Get the option chain data.
+    if (!slice.OptionChains.TryGetValue(_option.Symbol, out var chain))
+    {
+        return;
+    }
+
+    // Select the call Option contract.
+    var calls = chain.Where(contract => contract.Right == OptionRight.Call).ToList();
+    if (calls.Count < 1) return;
+
+    // Sorted the contracts according to their strike prices.
+    calls = calls.OrderBy(x => x.Strike).ToList();
+
+    // Buy 1 0DTE call option contract for the SPX index.
+    Buy(calls[0].Symbol, 1);
+}
+
def initialize(self) -> None:
+    self.set_start_date(2023,1,1)
+    self.set_end_date(2024,1,1)
+    self.set_cash(100_000)
+    # Subscribe to the option chain.
+    self._option = self.add_index_option("SPX", Resolution.DAILY)
+    # Filter the option universe to only select 0DTE options.
+    self._option.set_filter(lambda u: u.include_weeklys().expiration(0, 0).strikes(-1, 1))
+    # Filter the option universe by Delta.
+    self._option.set_filter(lambda option_filter_universe: option_filter_universe.delta(0.25, 0.75))
+
+def on_data(self, slice: Slice) -> None:
+    if self.portfolio.invested:
+        return
+    # Get the option chain data.
+    chain = slice.option_chains.get(self._option.symbol)
+    if not chain:
+        return
+    # Select the call Option contract.
+    calls = [contract for contract in chain if contract.right == OptionRight.CALL]
+    if len(calls) < 1: return
+    # Sorted the contracts according to their strike prices.
+    calls = sorted(calls, key=lambda x: x.Strike)
+    # Buy 1 0DTE call option contract for the SPX index.
+    self.Buy(calls[0].Symbol, 1)
From 6b409c8ac8d8757d16a6c9483b05a5294a06775a Mon Sep 17 00:00:00 2001 From: baobach <95854748+baobach@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:00:24 +0700 Subject: [PATCH 2/4] Fixing arrow symbols --- .../01 Requesting Data/01 Universes/12 Examples.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php index 6fb9496b30..5b650723b2 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php @@ -57,7 +57,7 @@ # Filter the option universe by Delta. self._option.set_filter(lambda option_filter_universe: option_filter_universe.delta(0.25, 0.75)) -def on_data(self, slice: Slice) -> None: +def on_data(self, slice: Slice) -> None: if self.portfolio.invested: return # Get the option chain data. From 49af3e4203d665637fd965be661c49b78e2dfdb4 Mon Sep 17 00:00:00 2001 From: baobach <95854748+baobach@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:00:35 +0700 Subject: [PATCH 3/4] Fix arrow symbol --- .../01 Requesting Data/01 Universes/12 Examples.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php index 5b650723b2..6fb9496b30 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php @@ -57,7 +57,7 @@ # Filter the option universe by Delta. self._option.set_filter(lambda option_filter_universe: option_filter_universe.delta(0.25, 0.75)) -def on_data(self, slice: Slice) -> None: +def on_data(self, slice: Slice) -> None: if self.portfolio.invested: return # Get the option chain data. From 02ffe2a251421db1775f48dad858cfec3c107b62 Mon Sep 17 00:00:00 2001 From: baobach <95854748+baobach@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:57:58 +0700 Subject: [PATCH 4/4] Update Example 2 --- .../01 Universes/12 Examples.php | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php index 6fb9496b30..7feffe4f60 100644 --- a/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php +++ b/03 Writing Algorithms/03 Securities/99 Asset Classes/09 Index Options/01 Requesting Data/01 Universes/12 Examples.php @@ -72,3 +72,67 @@ # Buy 1 0DTE call option contract for the SPX index. self.Buy(calls[0].Symbol, 1) + +

Example 2: Rolling expired index options

+ +

In this example, we will create a universe of option contracts for the SPX index that expire in 30 to 90 days. From this universe, we allocate 10% of our cash to buy an ATM Call option that expires in 90 days. We hold this until expiration and then roll over to the next 90-day ATM contract using the on security changed event handler. Since index options are European (they will not be exercised before expiration) and cash-settled (even if held until exercised, they only affect the cash book), this approach saves us the extra work of handling option exercise or assignment, as we would with equity options.

+ +
+
private Option _indexOption;
+
+public override void Initialize()
+{
+    // Subscribe to the index option and filter to get only the ones expiring in 30-90 days.
+    _indexOption = AddIndexOption("SPX", "SPXW");
+    _indexOption.SetFilter((u) => u.IncludeWeeklys().CallsOnly().Expiration(30, 90));
+}
+
+public override void OnData(Slice slice)
+{
+    // Get option chain data for the canonical symbol.
+    if (!Portfolio.Invested && 
+        slice.OptionChains.TryGetValue(_indexOption.Symbol, out var chain))
+    {
+        // Obtain the ATM call that expires furthest (90 days).
+        var expiry = chain.Max(x => x.Expiry);
+        var atmCall = chain.Where(x => x.Expiry == expiry)
+            .OrderBy(x => Math.Abs(x.Strike - x.UnderlyingLastPrice))
+            .First();
+        // Allocate 10% Capital.
+        SetHoldings(atmCall.Symbol, 0.1m);
+    }
+}
+
+public override void OnSecuritiesChanged(SecurityChanges changes)
+{
+    foreach (var removed in changes.RemovedSecurities)
+    {
+        // Liquidate the contracts that exit the universe (due to expiry).
+        if (Portfolio[removed.Symbol].Invested)
+        {
+            Liquidate(removed.Symbol);
+        }
+    }
+}
+
def initialize(self):
+    # Subscribe to the index option and filter to get only the ones expiring in 30-90 days.
+    self._index_option = self.add_index_option("SPX", "SPXW")
+    self._index_option.set_filter(lambda u: u.include_weeklys().calls_only().expiration(30, 90))
+
+def on_data(self, slice: Slice):
+    # Get option chain data for the canonical symbol.
+    if not self.portfolio.invested:
+        chain = slice.option_chains.get(self._index_option.symbol)
+        if chain:
+            # Obtain the ATM call that expires furthest (90 days).
+            expiry = max(x.expiry for x in chain)
+            atm_call = min(chain, key=lambda x: abs(x.strike - x.underlying_last_price))
+            # Allocate 10% Capital.
+            self.set_holdings(atm_call.symbol, 0.1)
+
+def on_securities_changed(self, changes: SecurityChanges):
+    for removed in changes.removed_securities:
+        if self.portfolio[removed.symbol].invested:
+            # Liquidate the contracts that exit the universe (due to expiry).
+            self.liquidate(removed.symbol)
+