Overall Statistics
Total Trades
13
Average Win
0.73%
Average Loss
0%
Compounding Annual Return
123.911%
Drawdown
2.400%
Expectancy
0
Net Profit
2.233%
Sharpe Ratio
5.218
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.41
Beta
0.981
Annual Standard Deviation
0.108
Annual Variance
0.012
Information Ratio
4.135
Tracking Error
0.099
Treynor Ratio
0.573
Total Fees
$7.00
from universe import getUniverse
import pandas as pd

class OptionsTrading(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 1, 4)  #Set Start Date
        self.SetEndDate(2017, 1, 15)  #Set End Date
        self.SetCash(50000)  #Set Strategy Cash
        self.happened  = False 
        self.boundUp   = 0.05
        self.boundDown = 0.03
        tickerList = getUniverse()
        

        
        for ticker in tickerList:
            self.AddEquity( ticker, Resolution.Minute )
            option = self.AddOption( ticker, Resolution.Minute) # Add the option corresponding to underlying stock
            option.SetFilter(lambda universe: universe.IncludeWeeklys().Strikes(0, 10).Expiration(timedelta(0), timedelta(30)))
            
    
    def onceADay( self, startHour = 10, resetHour = 15 ):
        if self.Time.hour >= resetHour:
            self.happened = False
            return False
        elif self.Time.hour >= startHour and self.happened == False :
            self.happened = True
            return True
        return False
        
    def isInvested( self, ticker ):
        for inst in self.Portfolio:
            if ticker == inst.Value.Symbol.Underlying:
                self.Debug('%s != %s' % ( ticker, inst.Value.Symbol.Underlying ))
                return True
        return False
        
    def getOption( self, ticker, chain, right, distance = 0.05 ):
        bound = chain.Underlying.Price * ( 1 + distance )
        if right == OptionRight.Put:
            optionList = [i for i in chain if i.Right == 1 ]
            option = max( optionList, key = lambda x : abs( x.Strike - bound ))
        elif right == OptionRight.Call:
            optionList = [i for i in chain if i.Right == 0 ]
            option = min( optionList, key = lambda x : abs( x.Strike - bound ))
        return option
        
    def OnAssignmentOrderEvent(self, assignmentEvent):
        self.Log(str(assignmentEvent))

    def OnData(self, slice):
        self.Debug(f"Time:  {self.Time}")
        if self.onceADay():
            self.Log(str(self.Time))
            for chain in slice.OptionChains.Values:
                if not self.isInvested( chain.Underlying ):
                    optionCall = self.getOption( chain.Underlying.Symbol, chain, right = OptionRight.Call, distance = 0.1 )
                    optionPut  = self.getOption( chain.Underlying.Symbol, chain, right = OptionRight.Put, distance = 0.1 )
                    if optionCall.BidPrice > 0.05 and optionPut.BidPrice > 0.05 :
                        self.Log('Selling in %s' % chain.Underlying.Symbol )
                        self.Sell( optionCall.Symbol, 1 )
                        self.Sell( optionPut.Symbol, 1 )

                    #self.Sell( highCall.Symbol, 1 )
                    # For validation we get the strikes of the selected contracts
                    #strikes = [x.Strike for x in contracts if x.Strike > lowerBound and x.Strike < upperBound]
                    #self.Log(f"stock: {chain.Underlying.Symbol}\nLower strike: {lowPut.Strike} \n Upper strike: {highCall.Strike} \n price: {chain.Underlying.Price}")
def getUniverse():
    #return ['aapl','intc','goog']
    return ['aapl', 'goog', 'amzn']