Overall Statistics
Total Trades
4
Average Win
0.36%
Average Loss
0%
Compounding Annual Return
274.403%
Drawdown
0.200%
Expectancy
0
Net Profit
0.726%
Sharpe Ratio
17.932
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.66
Beta
-0.057
Annual Standard Deviation
0.034
Annual Variance
0.001
Information Ratio
-0.48
Tracking Error
0.615
Treynor Ratio
-10.721
Total Fees
$4.00
from datetime import timedelta

class BullCallSpreadAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 11, 7)
        self.SetEndDate(2019, 11, 10)
        self.SetCash(100000)
        #self.long= False
#stocks        
        equity = self.AddEquity("SHOP", Resolution.Minute)
        equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.SetBenchmark(equity.Symbol)
#options        
        option = self.AddOption("SHOP", Resolution.Minute)
        self.symbol = option.Symbol
        option.SetFilter(self.UniverseFunc)

# Start of day bar        
        self.Consolidate("SHOP", timedelta(minutes=3), self.OnDataConsolidated)
        self.openingBar = None    
        #self.Schedule.On(self.DateRules.EveryDay() , self.TimeRules.At(9, 37), Action(self.TradeOptions(chains)))
        # self.Schedule.On(self.DateRules.EveryDay("SHOP"), self.TimeRules.At(11, 00), self.ClosePositions)
        #self.Debug('end of initialization')    
    def UniverseFunc(self, universe):
        return universe.IncludeWeeklys().Expiration(TimeSpan.FromDays(0),
                                               TimeSpan.FromDays(6)).Strikes(0,0)        
    
    def OnData(self, slice):
        

        if self.openingBar is None: #wait for the first 3min candle 
            #self.Debug('Opening bar is none')
            return         
        
        for i in slice.OptionChains:
            chains = i.Value

#Entries
        if not self.Portfolio.Invested and self.long == False and self.short==False:
            # for i in slice.OptionChains:
            #     chains = i.Value
            
            if slice["SHOP"].Close > self.openingBar.Open:

                
                # self.entryprice= self.MarketOrder("SHOP", 100)
                self.avgfill = slice['SHOP'].Close
                self.long = True
                self.Debug(str(self.Time) + " Entry Long - Open was: " + str(self.openingBar.Open) + " SHOP is: " + str(self.avgfill))                
                self.TradeOptions(chains)

            elif slice["SHOP"].Close < self.openingBar.Open:

                self.avgfill = slice['SHOP'].Close
                # self.entryprice= self.MarketOrder("SHOP", -100)
                # self.avgfill = self.entryprice.AverageFillPrice
                self.short=True
                self.Debug(str(self.Time) + " Entry Short- Open was: " + str(self.openingBar.Open) + " SHOP is: " + str(self.avgfill))
                self.TradeOptions(chains)
                
#Exits Profit taking                  
        if self.Portfolio.Invested:
            
            if self.long== True and slice["SHOP"].Close > (self.openingBar.Open*1.035):

                self.Debug("Long Profit target hit, exit at " + str(slice["SHOP"].Close))
                self.Debug('Call tracking price' + 'Bid: ' + str(self.call.BidPrice )+ 'Ask: ' + str(self.call.AskPrice))
                self.Debug('Shop at: ' + str(self.call.UnderlyingLastPrice) + ' Stop Hit, expect Selling : At Bid ' + str(self.call.BidPrice) + ' and Ask is: ' + str(self.call.AskPrice))                

                self.Sell(self.call.Symbol,1)                
                self.long=False
                self.openingBar = None
                
            elif self.short== True and slice["SHOP"].Close < (self.openingBar.Open*0.965):
                self.Debug("Short Profit target hit, exit at " + str(slice["SHOP"].Close))                 
                self.Debug('Shop at: ' + str(self.put.UnderlyingLastPrice) + ' Stop Hit, expect Selling : At Bid ' + str(self.put.BidPrice) + ' and Ask is: ' + str(self.put.AskPrice))

                #self.ClosePositions
                self.short=False                
                self.Sell(self.put.Symbol,1)
                self.openingBar = None                
#Exits Stop Loss
            elif self.long== True and slice["SHOP"].Close < (self.avgfill*0.985):
                self.Debug("Long stop loss, exit at " + str(slice["SHOP"].Close))
                self.Debug('Call tracking price' + str(self.call.BidPrice) + str(self.call.AskPrice))
                self.Debug('Shop at: ' + str(self.call.UnderlyingLastPrice) + ' Stop Hit, expect Selling : At Bid ' + str(self.call.BidPrice) + ' and Ask is: ' + str(self.call.AskPrice) )                
                #self.ClosePositions
                self.long=False
                self.Sell(self.call.Symbol,1)
                self.openingBar = None
                
            elif self.short== True and slice["SHOP"].Close > (self.avgfill*1.015):
                self.Debug("Short stop loss, exit at " + str(slice["SHOP"].Close))
                self.Debug('Shop at: ' + str(self.put.UnderlyingLastPrice) +' Stop Hit, expect Selling : At Bid ' + str(self.put.BidPrice) + ' and Ask is: ' + str(self.put.AskPrice))                
                #self.ClosePositions
                self.short=False
                self.Sell(self.put.Symbol,1)
                self.openingBar = None
             
            elif self.CloseTradeBar is True:
                self.Debug('CloseTradeBar :  time: ' + str(self.Time))
                self.Debug('Attempt to retreive latest options price : ')
                self.UpdateOptions(chains)

                if self.long==True:
                    self.Sell(self.call.Symbol,1)
                    self.Debug('Shop at: ' + str(self.call.UnderlyingLastPrice) + ' Stop Hit, expect Selling : At Bid ' + str(self.call.BidPrice) + ' and Ask is: ' + str(self.call.AskPrice) )  
                    #self.OptionChainProvider.GetOptionContractList(self.call,self.Time)                    
                    #self.long=False                    
                elif self.short==True:
                    self.Sell(self.put.Symbol,1)
                    #self.OptionChainProvider.GetOptionContractList(self.put,self.Time)
                    self.Debug('Shop at: ' + str(self.put.UnderlyingLastPrice) + ' Stop Hit, expect Selling : At Bid ' + str(self.put.BidPrice) + ' and Ask is: ' + str(self.put.AskPrice))  
                self.CloseTradeBar= False    
                    #self.short=False            
                # else:
                #     self.Debug('Something went wrong at 11am close position trigger' + str(self.Time))
                #     self.Debug(str(self.long) + str(self.short))
                # self.openingBar = None        
        
 #Options trade
    def TradeOptions(self,chains):

        # sorted the optionchain by expiration date and choose the furthest date
        expiry = sorted(chains,key = lambda x: x.Expiry, reverse=True)[0].Expiry
        # filter the call and put contract
        call = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Call]
        put = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Put]
        # sorted the contracts according to their strike prices 
        call_contracts = sorted(call,key = lambda x: x.Strike)    
        if len(call_contracts) == 0: return
        self.call = call_contracts[0]
        #self.Debug(str(self.call.Symbol))
        #self.Debug('ATM call is ' + str(self.call.Symbol.Value))
        for i in put:
            if i.Strike == self.call.Strike:
                self.put = i
                #self.Debug(str(self.Time) + ' ATM put is :' + str(self.put.Symbol) + ' and ' + 'ATM call is ' + str(self.call.Symbol)) #'SHOP Entry Price is: ' + str(slice['SHOP'].Close) +
                
        if self.long== True:
            #self.Buy(self.call.Symbol, 1)
            self.Buy(self.call.Symbol, 1)
            
            self.AddOptionContract(self.call.Symbol, Resolution.Minute)
            #self.Debug(str(self.entryTime))
            self.Debug('Shop at: ' + str(self.put.UnderlyingLastPrice) + ' Call Ask Price: ' + str(self.call.AskPrice))
        elif self.short==True:
            #self.Buy(self.put.Symbol, 1)
            self.Buy(self.put.Symbol, 1)
            self.AddOptionContract(self.put.Symbol, Resolution.Minute)            
            self.Debug('Shop at: ' + str(self.put.UnderlyingLastPrice) + ' Put Ask Price: ' + str(self.put.AskPrice))            


 #Update Options price
    def UpdateOptions(self,chains):

        # # sorted the optionchain by expiration date and choose the furthest date
        # expiry = sorted(chains,key = lambda x: x.Expiry, reverse=True)[0].Expiry
        # # filter the call and put contract
        # call = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Call]
        # put = [i for i in chains if i.Expiry == expiry and i.Right == OptionRight.Put]
        # # sorted the contracts according to their strike prices 
        # call_contracts = sorted(call,key = lambda x: x.Strike)    
            # if len(call_contracts) == 0: return
        if self.long==True: 
            self.Debug(str(self.call.Symbol) + str(self.call.BidPrice) + str(self.call.AskPrice) + str(self.call.UnderlyingLastPrice))
        if self.short==True:
            self.Debug('Contract: ' + str(self.put) + ' Bid: ' + str(self.put.BidPrice) + ' ASK: ' + str(self.put.AskPrice) + ' Underlying price: ' + str(self.put.UnderlyingLastPrice))   
       
        #self.Debug(str(self.call.Symbol))
        #self.Debug('ATM call is ' + str(self.call.Symbol.Value))


# create a 3min candle at open
    def OnDataConsolidated(self, bar):
        if bar.Time.hour == 9 and bar.Time.minute == 30:
            self.long= False
            self.short= False            
            self.openingBar = bar
            self.CloseTradeBar= False
            #self.Debug('doing the 3min bar thing')    
        if bar.Time.hour == 11 and bar.Time.minute == 00:
            self.CloseTradeBar = True
            #self.Debug('doing the 3min bar thing')             
    # def ClosePositions(self):
        
    #     if self.Portfolio.Invested:
            
    #         # if self.long==True:
    #         #     self.Sell(self.call.Symbol,1)
    #         #     self.openingBar = None
    #         #     self.long=False
    #         #     self.Debug('Selling :' + str(self.call.Symbol) + ' At Bid ' + str(self.call.BidPrice) + ' Ask is: '+ str(self.call.AskPrice) + 'Long is: ' + str(self.long))
                
    #         # elif self.short==True:
    #         #     self.Sell(self.put.Symbol,1)
    #         #     self.openingBar = None                
    #         #     self.short=False
    #         #     self.Debug('Selling :' + str(self.put.Symbol) + ' At Bid ' + str(self.put.BidPrice) + ' Ask is: ' + str(self.put.AskPrice) + 'Short is: ' + str(self.short))
    #     #else: return  
    #         self.Liquidate()
    #         self.Debug('11am Liquidate function called')
    #         self.openingBar = None            
        
    def OnOrderEvent(self, orderEvent):
        self.Log(str(orderEvent))