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))