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