Overall Statistics |
Total Trades 5 Average Win 4.88% Average Loss 0% Compounding Annual Return 42.818% Drawdown 13.600% Expectancy 0 Net Profit 6.120% Sharpe Ratio 1.245 Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 3.419 Beta -183.185 Annual Standard Deviation 0.269 Annual Variance 0.073 Information Ratio 1.181 Tracking Error 0.27 Treynor Ratio -0.002 Total Fees $5.00 |
import numpy as np from datetime import timedelta import pandas as pd ### <summary> ### Basic template algorithm simply initializes the date range and cash. This is a skeleton ### framework you can use for designing an algorithm. ### </summary> class CustomSlippageModel: def GetSlippageApproximation(self, asset, order): return np.float( asset.Price ) * 0.002 class BasicTemplateAlgorithm(QCAlgorithm): '''Basic template algorithm simply initializes the date range and cash''' def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' self.SetStartDate(2016,1,1) #Set Start Date self.SetEndDate(2016,3,1) #Set End Date self.SetCash(100000) #Set Strategy Cash self.stocks = ["DUST","NUGT"] self.should_trade = False self.order_tickets = {} self.open_trades = {} self.nearest_option = 27 self.sell_with_days_left = 5 self.short_call = True for stock in self.stocks: self.AddEquity(stock, Resolution.Minute) # self.Securities[stock].SetDataNormalizationMode(DataNormalizationMode.Raw) self.Securities[stock].SetSlippageModel(CustomSlippageModel()) self.order_tickets[ stock ] = [] option = self.AddOption( stock, Resolution.Minute) option.SetFilter(lambda u: u.IncludeWeeklys().Strikes(-1, +1).Expiration(timedelta(self.nearest_option), timedelta(45))) self.lev = 1.0 self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(self.stocks[0], 10), Action(self.activate)) self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(self.stocks[0], 6), Action(self.deactivate)) def activate(self): self.should_trade = True def deactivate(self): self.should_trade = False def OnData(self, data): ''' ''' if self.should_trade: nav = np.float(self.Portfolio.TotalPortfolioValue) '''check current option holdings, do not hold options to expiration''' option_holding_underlyings = [] for sym in self.Portfolio.Keys: holding = self.Portfolio[sym] if holding.HoldStock and holding.Symbol.SecurityType == SecurityType.Option: info = self.open_trades[ holding.Symbol ] if int( ( info['expiry'] - data.Time ).days ) <= self.sell_with_days_left: self.SetHoldings(sym, 0) else: if holding.Quantity > 0: dir = "long" else: dir = "short" if info['type'] == 1: option_holding_underlyings.append( [str(holding.Symbol.Underlying), "put", dir] ) else: option_holding_underlyings.append( [str(holding.Symbol.Underlying), "call", dir] ) self.Log( str( holding.Symbol ) ) options = {} for stock in self.stocks: options[stock] = { 'put': None, 'call': None, 'qnty': None } for i in data.OptionChains: optionchain = list( i.Value ) if len(optionchain) == 0: continue try: usym = str( optionchain[0].UnderlyingSymbol ) upric = float( optionchain[0].UnderlyingLastPrice ) except: return # create a data frame to show the filtered contracts # type(call 0, put 1) df = pd.DataFrame([[ x.Right, np.float(x.Strike), x.Expiry, np.float(x.BidPrice), np.float(x.AskPrice), x.Symbol] for x in optionchain ], index=[ x.Symbol.Value for x in optionchain ], columns=[ 'type', 'strike', 'expiry', 'ask', 'bid', 'Symbol' ]) df = df.loc[ ( df['expiry'] > data.Time + timedelta(days=self.nearest_option) ) ] self.Log(usym+" "+str(upric)) puts = df.loc[ df['type'] == 1 ] calls = df.loc[ df['type'] == 0 ] if len( calls.index ) < 1 or len( puts.index ) < 1: continue options[ usym ]['call'] = calls.sort_values(['expiry','strike'], ascending=[True, False]).iloc[0] options[ usym ]['put'] = puts.sort_values(['expiry','strike'], ascending=[False, True]).iloc[0] options[ usym ]['qnty'] = np.round( self.lev * nav * 0.5 / np.float( np.mean([options[ usym ]['call'].strike, options[ usym ]['put'].strike]) ) / 100 ) for stock in self.stocks: if [stock,'call','short'] not in option_holding_underlyings and self.short_call == True: c = options[ stock ]['call'] self.Log( "trying to sell %s call contracts" % options[ stock ]['qnty'] ) self.Log( "at strike price %s" % c['strike'] ) self.MarketOrder( c['Symbol'] , -options[ stock ]['qnty'] ) self.open_trades[ c['Symbol'] ] = c self.should_trade = False