Overall Statistics
Total Trades
2
Average Win
0%
Average Loss
0%
Compounding Annual Return
-7.473%
Drawdown
17.200%
Expectancy
0
Net Profit
-0.282%
Sharpe Ratio
0.702
Probabilistic Sharpe Ratio
47.144%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
1.287
Beta
1.62
Annual Standard Deviation
0.648
Annual Variance
0.42
Information Ratio
2.6
Tracking Error
0.373
Treynor Ratio
0.281
Total Fees
$8.50
from QuantConnect.Securities.Option import OptionPriceModels

class TransdimensionalResistanceReplicator(QCAlgorithm):
    #sell calls
    
    def Initialize(self):
        self.SetStartDate(2020, 6, 9)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        self.SetEndDate(2020, 6, 22) # Set End Date
        
        self.equity_symbols_by_option_symbols = {}
        
        for ticker in ["VXX", "SPY"]:
            option = self.AddOption(ticker)
            option.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
            option.PriceModel = OptionPriceModels.CrankNicolsonFD() 
            
            equity_symbol = self.AddEquity(ticker, Resolution.Minute).Symbol
            
            self.equity_symbols_by_option_symbols[option.Symbol] = equity_symbol
            

        #cash buffer
        self.Settings.FreePortfolioValuePercentage = 0.02
        #dict of limit orders open
        self.__openLimitOrders = []
        
        self.SetWarmUp(30, Resolution.Daily) 

    def OnData(self, slice):
        if self.IsWarmingUp: return
    
        option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
        if self.HourMinuteIs(10, 00):

            for option_symbol, equity_symbol in self.equity_symbols_by_option_symbols.items():
                underlying_price = self.Securities[equity_symbol].Price
                
                #checking to see if there is already an open position in the ticker
                invested = [option for option in option_invested if option.Underlying == equity_symbol]
                if invested: 
                    continue
            
                for chain in slice.OptionChains:
                    if chain.Key != option_symbol:
                        continue
                        
                    option_chain = [contract for contract in chain.Value if contract.Right is 0 and contract.Strike - underlying_price > 1]
                    if len(option_chain) == 0:
                        continue
                    
                    delta_filter = [contract for contract in option_chain if contract.Greeks.Delta >= .25 and contract.Greeks.Delta <= .35 ]
                    sorted_contracts = sorted(sorted(delta_filter, \
                        key=lambda k: k.Greeks.Delta, reverse=False),
                        key=lambda k: k.OpenInterest, reverse=True)

                    #generally want to buy on a wednesday. 
                    liquidContract = sorted_contracts[0]

                    #use criterion to choose how many options to sell
                    quantity = self.CalculateOrderQuantity(liquidContract.Symbol, 0.05)
                    newTicket = self.LimitOrder(liquidContract.Symbol, -1 * (quantity), round(liquidContract.AskPrice, 2))
                    self.__openLimitOrders.append(newTicket)
                    
                    self.Debug("# limit orders " + str(len(self.__openLimitOrders)))

                        
                
    def HourMinuteIs(self, hour, minute):
        return self.Time.hour == hour and self.Time.minute == minute
        
    def OnOrderEvent(self, orderEvent):
        order = self.Transactions.GetOrderById(orderEvent.OrderId)
        if orderEvent.Status == OrderStatus.Filled: 
            self.Debug("{0}: {1}: {2}".format(self.Time, order.Type, orderEvent))