Overall Statistics
Total Orders
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Start Equity
100000
End Equity
100000
Net Profit
0%
Sharpe Ratio
0
Sortino Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
Portfolio Turnover
0%
Drawdown Recovery
0
from AlgorithmImports import *
from datetime import timedelta, date

class QQQOptionUniverseDiagnostic(QCAlgorithm):

    def Initialize(self):
        # Setting backtest dates to the specific problematic day in May 2026
        self.SetStartDate(2026, 5, 11)
        self.SetEndDate(2026, 5, 11)
        self.SetCash(100000)

        self.qqq = self.AddEquity("QQQ", Resolution.Minute).Symbol
        self.Securities[self.qqq].SetDataNormalizationMode(DataNormalizationMode.Raw)

        option = self.AddOption("QQQ", Resolution.Minute)
        self.option_symbol = option.Symbol

        # Broad filter to ensure we capture all nearby available strikes
        option.SetFilter(
            lambda u: u.IncludeWeeklys()
                       .Strikes(-100, +100)
                       .Expiration(timedelta(0), timedelta(2))
        )

        self.done = False

    def OnData(self, data: Slice):
        # Run only once, shortly after market open at 09:35 AM NY time
        if self.done:
            return

        if self.Time.hour != 9 or self.Time.minute < 35:
            return

        self.done = True

        underlying_price = self.Securities[self.qqq].Price
        self.Log(f"=== QQQ OPTIONS DIAGNOSTIC {self.Time} ===")
        self.Log(f"QQQ price = {underlying_price}")

        target_expiries = [
            date(2026, 5, 12),
            date(2026, 5, 13)
        ]

        # 1) Contracts that QuantConnect claims to exist via the historical provider list
        provider_symbols = self.OptionChainProvider.GetOptionContractList(self.qqq, self.Time)

        self.Log(f"OptionChainProvider total contracts = {len(provider_symbols)}")

        for expiry in target_expiries:
            provider_puts = [
                s for s in provider_symbols
                if s.ID.OptionRight == OptionRight.Put
                and s.ID.Date.date() == expiry
            ]

            provider_strikes = sorted(set(float(s.ID.StrikePrice) for s in provider_puts))
            near_provider = [x for x in provider_strikes if 660 <= x <= 735]

            self.Log(f"--- PROVIDER expiry={expiry} puts strikes 660-735 ---")
            self.Log(",".join([str(int(x)) for x in near_provider]))
            self.Log(f"provider count near = {len(near_provider)}")

        # 2) Contracts that actually arrive inside the Slice.OptionChains data stream
        chain = data.OptionChains.get(self.option_symbol)

        if chain is None:
            self.Log("NO OptionChain found in Slice for self.option_symbol")
            return

        contracts = list(chain)
        self.Log(f"Slice OptionChain contracts = {len(contracts)}")

        for expiry in target_expiries:
            slice_puts = [
                c for c in contracts
                if c.Right == OptionRight.Put
                and c.Expiry.date() == expiry
            ]

            slice_strikes = sorted(set(float(c.Strike) for c in slice_puts))
            near_slice = [x for x in slice_strikes if 660 <= x <= 735]

            self.Log(f"--- SLICE expiry={expiry} puts strikes 660-735 ---")
            self.Log(",".join([str(int(x)) for x in near_slice]))
            self.Log(f"slice count near = {len(near_slice)}")

            self.Log(f"--- SLICE detail expiry={expiry} ---")
            for c in sorted(slice_puts, key=lambda x: x.Strike):
                if 660 <= float(c.Strike) <= 735:
                    delta = None
                    try:
                        delta = c.Greeks.Delta
                    except:
                        pass

                    self.Log(
                        f"{c.Symbol.Value} | "
                        f"DTE={(c.Expiry.date() - self.Time.date()).days} | "
                        f"strike={c.Strike} | "
                        f"delta={delta} | "
                        f"bid={c.BidPrice} | ask={c.AskPrice}"
                    )

        # 3) Direct comparison: strikes listed by provider but missing from Slice
        for expiry in target_expiries:
            provider_set = set(
                float(s.ID.StrikePrice) for s in provider_symbols
                if s.ID.OptionRight == OptionRight.Put
                and s.ID.Date.date() == expiry
                and 660 <= float(s.ID.StrikePrice) <= 735
            )

            slice_set = set(
                float(c.Strike) for c in contracts
                if c.Right == OptionRight.Put
                and c.Expiry.date() == expiry
                and 660 <= float(c.Strike) <= 735
            )

            missing_in_slice = sorted(provider_set - slice_set)
            extra_in_slice = sorted(slice_set - provider_set)

            self.Log(f"=== COMPARISON expiry={expiry} ===")
            self.Log(f"In Provider but MISSING from Slice: {','.join(str(int(x)) for x in missing_in_slice)}")
            self.Log(f"In Slice but MISSING from Provider: {','.join(str(int(x)) for x in extra_in_slice)}")