Overall Statistics
Total Trades
2
Average Win
0%
Average Loss
0%
Compounding Annual Return
45.152%
Drawdown
40.000%
Expectancy
0
Net Profit
2.300%
Sharpe Ratio
2.201
Probabilistic Sharpe Ratio
50.307%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
4.215
Beta
4.002
Annual Standard Deviation
1.322
Annual Variance
1.747
Information Ratio
3.134
Tracking Error
1.032
Treynor Ratio
0.727
Total Fees
$10.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, 7, 1) # Set End Date
        
        
        self.equityVxx = self.AddEquity("VXX", Resolution.Minute)
        self.equitySpy = self.AddEquity("SPY", Resolution.Minute)
        
        self.symbols = []
        
        for ticker in ["VXX", "SPY"]:
            option = self.AddOption(ticker)
            self.symbols.append(option.Symbol)
            option.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
            option.PriceModel = OptionPriceModels.CrankNicolsonFD() 
        #vxxOptions = self.AddOption("VXX")
        #vxxOptions.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
        #vxxOptions.PriceModel = OptionPriceModels.CrankNicolsonFD() 
            
        #spyOptions = self.AddOption("SPY")
        #spyOptions.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
        #spyOptions.PriceModel = OptionPriceModels.CrankNicolsonFD() 
        #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):
                
            self.underlyingPriceVxx = self.Securities[self.equityVxx.Symbol].Price
            self.underlyingPriceSpy = self.Securities[self.equitySpy.Symbol].Price
            #self.Debug("Current " + str(self.Securities[self.equityVxx.Symbol]) + ", " + str(self.underlyingPriceVxx) + ", " + str(self.Securities[self.equitySpy.Symbol]) + ", " + str(self.underlyingPriceSpy) + ", at " + str(self.Time))
            for symbol in self.symbols:
                #checking to see if there is already an open position in the ticker
                invested = [option for option in option_invested if option.Underlying == symbol.Underlying]
                if len(invested) > 0: return
                for chain in slice.OptionChains:
                    if str(chain.Key) == "?VXX":
                            self.optionchain = [contract for contract in chain.Value if contract.Right is 0 and contract.Strike - self.underlyingPriceVxx > 1]
                            if len(self.optionchain) == 0:
                                self.Debug("no chain options")
                                continue
                            self.sortedVxx = sorted(self.optionchain, key=lambda k : k.Expiry, reverse=False)
                            self.greekVxx = [contract for contract in self.sortedVxx if contract.Greeks.Delta >= .25 and contract.Greeks.Delta <= .35 ]
                            self.popVxx = sorted(sorted(self.greekVxx, \
                                key=lambda k: k.Greeks.Delta, reverse=False),
                                key=lambda k: k.OpenInterest, reverse=True)
                            #for contract in self.popVxx:
                                #self.Debug(str(contract.Expiry) + ", " + str(contract.Strike) + ", " + str(contract.UnderlyingSymbol) + ", " + str(contract.Right) + ", " + str(contract.Greeks.Delta) + ", " + str(contract.OpenInterest))
                                    
                            #generally want to buy on a wednesday. 
                            self.liquidContract = self.popVxx[0]
                            #self.Debug("Selling this contract: ")
                            #self.Debug(str(self.liquidContract.Expiry) + ", " + str(self.liquidContract.Strike) + ", " + str(self.liquidContract.UnderlyingSymbol) + ", " + str(self.liquidContract.Right) + ", " + str(self.liquidContract.Greeks.Delta) + ", " + str(self.liquidContract.OpenInterest))
                                
                            #use criterion to choose how many options to sell
                            quantityVxx = self.CalculateOrderQuantity(self.liquidContract.Symbol, 0.05)
                            #self.Debug("quantity of VXX contracts to sell " + str(-1 * (quantityVxx)) + ", at limit " + str(self.liquidContract.AskPrice) )
                            newTicket = self.LimitOrder(self.liquidContract.Symbol, -1 * (quantityVxx), round(self.liquidContract.AskPrice, 2))
                            self.__openLimitOrders.append(newTicket)
                            
                            self.Debug("# limit orders " + str(len(self.__openLimitOrders)))
                                
                            if len(self.__openLimitOrders) == 1:
                                self.openOrders = self.__openLimitOrders
                                    
                                #vxxOrder = self.openOrders[0]
                                #orderId = vxxOrder.OrderId
                            #newTicketId = self.newTicket.OrderId
                                
                            #self.Debug("newTicket status " + str(self.newTicket.Status))
                            #self.Debug("order status " + str(OrderStatus.Filled))
                                #self.Debug("order id " + str(vxxOrder.OrderId))
                                #check if order got filled
                                #filled = self.OnOrderEvent(vxxOrder)
                                #self.Debug("filled : " + str(filled))
                                
                            #if self.newTicket.Status == OrderStatus.Filled:
                                #if filled == 0:
                                #self.Debug("Order Filled")
                                #self.__openLimitOrders = []
                                    
                                
                                    
                                #if it didn't get filled, do more reasonable limit
                                #elif vxxOrder.Status != OrderStatus.Filled:
                                #elif filled == 1:
                                    #self.newLimit = round(vxxOrder.Get(OrderField.LimitPrice) - 0.01, 2)
                                    #self.Debug("Updating limits - Price " + str(self.newLimit))
                                    #updateSettings = UpdateOrderFields()
                                    #updateSettings.LimitPrice = self.newLimit
                                    #vxxOrder.Update(updateSettings)
                                    
                                
                               
                            
                            
                        
                
    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))