Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index Options Universe Delta Filter Not Working #8511

Closed
vijaykyr opened this issue Jan 8, 2025 · 2 comments
Closed

Index Options Universe Delta Filter Not Working #8511

vijaykyr opened this issue Jan 8, 2025 · 2 comments

Comments

@vijaykyr
Copy link

vijaykyr commented Jan 8, 2025

Expected Behavior

Given a filter such as:

index = self.add_index('SPX')
index_option = self.add_index_option(index.symbol, 'SPXW',)
index_option.set_filter(lambda u: u.include_weeklys().delta(0.025, 0.035))

Only contracts with deltas between the filtered values should be made available to on_data()

Actual Behavior

Contracts with deltas both above and below the range are returned.

Potential Solution

Not a solution, but current work around is to remove the universe delta filter and post filter data slices in on_data{}. This is less efficient but filters by delta directly.

Reproducing the Problem

# region imports
from AlgorithmImports import *
# endregion

class SPX3delta(QCAlgorithm):

    def initialize(self):
        self.SetStartDate(2024, 10, 8)
        self.SetEndDate(2024, 10, 8)
        self.SetCash(800000)
        index = self.add_index('SPX')
        index_option = self.add_index_option(index.symbol, 'SPXW',)
        index_option.set_filter(lambda u: u.include_weeklys().expiration(0, 0).delta(0.025, 0.035))
        self._symbol = index_option.symbol

    def on_data(self, data: Slice):
        if self.portfolio.invested:
            return
        
        self.log(f"DATA TIME: {data.time}")

        chain = data.option_chains.get(self._symbol)
        if not chain:
            self.log("NO CONTRACTS FOUND")
            return

        contracts = [x for x in chain]
        self.log(f"CONTRACTS: {len(contracts)}")
        for idx, contract in enumerate(contracts):
            self.log(f"IDX: {idx}")
            self.log(f"SYMBOL: {contract.symbol}")
            self.log(f"STRIKE: {contract.strike}")
            self.log(f"EXPIRY: {contract.expiry}")
            self.log(f"DELTA: {contract.greeks.delta}")
            
        self.market_order(contracts[0].symbol, -1)

Run the backtest code above and then observe the logged deltas are out of range

System Information

Running locally on MacOS

@jhonabreul
Copy link
Collaborator

jhonabreul commented Jan 8, 2025

This is expected because the options are filtered using our pre-calculated daily greeks but the ones in the contracts in Slice.OptionChains are modeled and calculated every time using QuantLib. Our pre-calculated greeks are calculated using our indicators (e.g. https://github.com/QuantConnect/Lean/blob/master/Indicators/Delta.cs). We plan on implementing intraday pre-calculated greeks in the future #8440

Note that even after intraday precalculated greeks are implemented there might still be slight differences since prices (and time till expiry) will change after midnight and so intraday greeks could still have values outside the filter range.

@vijaykyr
Copy link
Author

vijaykyr commented Jan 9, 2025

Makes sense, thank you for the explanation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants