Overall Statistics
Total Trades
3
Average Win
1.01%
Average Loss
0%
Compounding Annual Return
-27.872%
Drawdown
7.200%
Expectancy
0
Net Profit
-2.617%
Sharpe Ratio
-1.31
Probabilistic Sharpe Ratio
23.535%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
-0.1
Beta
0.237
Annual Standard Deviation
0.224
Annual Variance
0.05
Information Ratio
0.731
Tracking Error
0.715
Treynor Ratio
-1.238
Total Fees
$2.00
import pandas as pd
import datetime

class LtShortPuts(QCAlgorithm):
    
    def Initialize(self):
        
        self.SetStartDate(2020, 3, 2)  # Set Start Date
        self.SetEndDate(2020, 3 , 31)
        self.SetCash(100000)  # Set Strategy Cash
        
        self.last_slice = None
        self.strike = 0
        
        self.stock = "SPY"
        self.fillPrice = 0
        
        self.tradingAllowed = False
        self.tradingDay = False
        self.dt = None
        
        #self.optTrades =  pd.DataFrame(columns = ['type', 'symbol', 'price', 'qty', 'underPrice'])
        
        equity = self.AddEquity(self.stock, Resolution.Minute)
        equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        option = self.AddOption(self.stock, Resolution.Minute)
        self.symbol = option.Symbol
        option.SetFilter(lambda universe: universe.IncludeWeeklys().Strikes(-1, 1).Expiration(timedelta(27), timedelta(35)))
        
        # Init 
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(9, 30), Action(self.Init))
        
        # check SPY closing price
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 59), Action(self.CheckClose))
        
        
    def GetOptionContract(self, strike):
        # Returns call/put contracts and their details for the given strike
        
        for i in self.last_slice.OptionChains:
            if i.Key != self.symbol: continue
            optionchain = i.Value
        
        call = [x for x in optionchain if x.Right == 0]
        callContract = [x for x in call if x.Strike == strike][0]
        call_symbol = callContract.Symbol
        
        put = [x for x in optionchain if x.Right == 1]
        putContract = [x for x in put if x.Strike == strike][0]
        put_symbol = putContract.Symbol
        
        call_bid = callContract.BidPrice
        call_ask = callContract.AskPrice
        
        put_ask = putContract.AskPrice
        put_bid = putContract.BidPrice
        
        return(call_symbol, call_bid, call_ask, put_symbol, put_bid, put_ask)
        
        
    def Init(self):
        self.call_ready = False
        self.put_ready = False
        self.call_symb = None
        self.put_symb = None
        
        
    def CheckClose(self):
        stockPrice = self.Securities[self.stock].Close
        self.Log("Closing price: " + str(stockPrice))
        
        
    
    def CheckOptions(self):
        stockPrice = self.Securities[self.stock].Close
        self.strike = round(stockPrice)
        self.Log("Strike: " + str(self.strike))
        self.dt = self.Time.date()
        self.Log("Today: " + str(self.dt))
        
        
        
        call_symbol, call_bid, call_ask, put_symbol, put_bid, put_ask = self.GetOptionContract(self.strike)
        self.tradingDay = True
        self.Log("Trading day lah! Call_symbol: {0}, Put symbol: {1}".format(call_symbol, put_symbol))
        d = call_symbol.ID.Date
        self.dateOfSymbol = d.date()
        self.Log("Date of symbol: " + str(self.dateOfSymbol))
            
            # I encountered problem before with the same error, and found out that algorithm tried to call options with expired dates
            # so here I check whether the expiration date is ahead of the current date
        if self.dateOfSymbol < self.dt:
            self.Log("Problem!!!!!!! Today is: {0}, but option requested is: {1} ".format(str(self.Time.date(), call_symbol)) )
            self.tradingDay = False
                
        
       
            
        #self.Log("CheckOption tradingDay: " + str(self.tradingDay))
        
    
    def OnData(self, slice):
        
        if (self.Time.hour == 10 and self.Time.minute == 00):
            
            invested = [ x.Symbol.Value for x in self.Portfolio.Values if x.Invested ]
            self.Log("invested: " + str(invested))
            if len(invested) == 0:
                self.last_slice = slice
                self.CheckOptions()
            
                if self.tradingDay:
                    call_symbol, call_bid, call_ask, put_symbol, put_bid, put_ask = self.GetOptionContract(self.strike)
                    marketTicket = self.MarketOrder(put_symbol, -1)
                    #marketTicket = self.MarketOrder(call_symbol, -1)
                    #marketTicket = self.MarketOrder(self.stock, 100)
                    self.fillPrice = marketTicket.AverageFillPrice
                    self.Debug("Open position Fill Price: {0}".format(self.fillPrice))
                    
                    
                   
                
            elif len(invested)>2: # something went wrong
                self.Log("SOMETHING WENT WRONG. LIQUIDATING ALL POSITIONS!")
                self.Liquidate()
            
            else:
                for opt in invested:
                
                    if (opt == 'SPY' and len(invested) == 1):
                        price = self.Portfolio[self.stock].Price
                        self.Log("We have only SPY position priced at {0} and need to add CALL".format(price))
                        
                        self.last_slice = slice
                        self.CheckOptions()
                        
                        
                        if self.tradingDay:
                            
                            call_symbol, call_bid, call_ask, put_symbol, put_bid, put_ask = self.GetOptionContract(self.strike)
                            self.call_ready = True
                            self.call_symb = call_symbol
                            
                                
                            '''
                            try:
                                marketTicket = self.MarketOrder(call_symbol, -1)
                                self.fillPrice = marketTicket.AverageFillPrice
                                self.Debug("Opened short CALL for: {0}".format(self.fillPrice))
                            except:
                                pass
                            '''
        # !!!!!!!!!!!!!!!!!!
        # This is where it get error about wrong symbol
        # ---------------------------------------------
                            
        if (self.Time.hour == 10 and self.Time.minute == 10):
            if self.call_ready:
                marketTicket = self.MarketOrder(self.call_symb, -1)
                self.fillPrice = marketTicket.AverageFillPrice
                self.Debug("Opened short CALL for: {0}".format(self.fillPrice))