Overall Statistics
Total Orders
18
Average Win
1.47%
Average Loss
-0.64%
Compounding Annual Return
8.274%
Drawdown
1.400%
Expectancy
1.993
Start Equity
100000
End Equity
104081
Net Profit
4.081%
Sharpe Ratio
0.068
Sortino Ratio
0.091
Probabilistic Sharpe Ratio
74.745%
Loss Rate
9%
Win Rate
91%
Profit-Loss Ratio
2.29
Alpha
-0.071
Beta
0.315
Annual Standard Deviation
0.031
Annual Variance
0.001
Information Ratio
-3.532
Tracking Error
0.065
Treynor Ratio
0.007
Total Fees
$12.00
Estimated Strategy Capacity
$270000.00
Lowest Capacity Asset
SPY YHRN4T1I63QE|SPY R735QTJ8XC9X
Portfolio Turnover
2.54%
# region imports
from AlgorithmImports import *
# endregion

class OptionIndicatorAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2023, 11, 5)
        self.option = self.add_option("SPY").symbol

    def on_securities_changed(self, changes):
        for security in [x for x in changes.added_securities if x.type == SecurityType.OPTION]:
            if security.cache.properties.contains_key('iv'):
                continue
            symbol = security.symbol
            right = OptionRight.CALL if symbol.id.option_right == OptionRight.PUT else OptionRight.PUT
            mirror_symbol = Symbol.create_option(symbol.id.underlying.symbol, symbol.id.market, symbol.id.option_style, right, symbol.id.strike_price, symbol.id.date)
            security.iv = self.iv(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            security.d = self.d(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            security.g = self.g(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            security.v = self.v(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            security.r = self.r(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            security.t = self.t(symbol, mirror_symbol, resolution=Resolution.MINUTE)
            
    def on_data(self, slice: Slice):
        if self.portfolio.invested:
            if self.portfolio[self.option.underlying].invested:
                self.liquidate()
            return
        chain = slice.option_chains.get(self.option)
        if chain:
            # select the contract with the hightest implied volatility
            contract = sorted([x for x in chain],
                key=lambda x: self.securities[x.symbol].iv.current.value, reverse=True)[0]
            option = self.securities[contract.symbol]
            iv = option.iv.current.value
            delta = option.d.current.value
            gamma = option.g.current.value
            vega = option.v.current.value
            rho = option.r.current.value
            theta = option.t.current.value
            self.market_order(contract.symbol, 1, tag=f"IV = {iv:.2f}, Delta = {delta:.2f}, Gamma = {gamma:.2f}, Vega = {vega:.2f}, Rho = {rho:.2f}, Theta = {theta:.2f}")