Overall Statistics
# region imports
from AlgorithmImports import *
# endregion

class BasicOptionAlgorithm(QCAlgorithm):
    
    def initialize(self):
        self.set_start_date(2025,1,1)
        self.universe_settings.asynchronous = True
        option = self.add_option("SPY")
        option.set_filter(self._filter)
        self._symbol = option.symbol

    def _filter(self, universe):
        return universe.include_weeklys().expiration(0, 0).strikes(-1, 1)

    def on_data(self, data):
        chain = data.option_chains.get(self._symbol)
        if chain:
            for contract in chain:
                option = self.securities[contract.symbol]
                message = f'{contract.symbol.value} :: IV={option.iv.current.value}, Δ={option.d.current.value}, Γ={option.g.current.value}, ν={option.v.current.value}, Θ={option.t.current.value}, ρ={option.r.current.value}'
                #self.debug(message)
            
    def on_securities_changed(self, changes):
        for security in changes.added_securities:
            if security.type not in [SecurityType.OPTION, SecurityType.INDEX_OPTION]:
                continue
            self._add_greek_indicator(security)
        for security in changes.removed_securities:
            if security.type not in [SecurityType.OPTION, SecurityType.INDEX_OPTION]:
                continue
            self._remove_greek_indicator(security)
            
    def _add_greek_indicator(self, security):
        symbol = security.symbol
        mirror_option = Symbol.create_option(symbol.underlying, symbol.id.market, symbol.id.option_style,
            OptionRight.CALL if symbol.id.option_right == OptionRight.PUT else OptionRight.PUT,
            symbol.id.strike_price, symbol.id.date)
        if mirror_option not in self.securities:
            self.add_option_contract(mirror_option)
        security.iv = self.iv(symbol, mirror_option)
        security.d = self.d(symbol, mirror_option)
        security.g = self.g(symbol, mirror_option)
        security.v = self.v(symbol, mirror_option)
        security.t = self.v(symbol, mirror_option)
        security.r = self.v(symbol, mirror_option)

    def _remove_greek_indicator(self, security):
        self.deregister_indicator(security.iv)
        self.deregister_indicator(security.d)
        self.deregister_indicator(security.g)
        self.deregister_indicator(security.v)
        self.deregister_indicator(security.t)
        self.deregister_indicator(security.r)