Overall Statistics
Total Trades
17
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
0.127%
Drawdown
0.000%
Expectancy
1.162
Net Profit
0.006%
Sharpe Ratio
7.374
Probabilistic Sharpe Ratio
96.437%
Loss Rate
56%
Win Rate
44%
Profit-Loss Ratio
3.86
Alpha
0.001
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-0.579
Tracking Error
0.064
Treynor Ratio
9.233
Total Fees
$9.00
from datetime import timedelta

class BullCallSpreadAlgorithm(QCAlgorithm):
    FB = None
    SB = None
    TB = None
    LB = None

    def Initialize(self):
        self.SetStartDate(2018, 7,12)
        self.SetEndDate(2018, 7, 30)
        self.SetCash(600000)
        equity = self.AddEquity("SPY", Resolution.Minute)
        option = self.AddOption("SPY", Resolution.Minute)
        self.optionMultiplier = option.ContractMultiplier
        self.symbol = option.Symbol
        self.costs = {}
    
        # set our strike/expiry filter for this option chain
        option.SetFilter(self.UniverseFunc)
        self.Consolidate("SPY", timedelta(minutes=15), self.OnDataConsolidated)
        self.SetBenchmark(equity.Symbol)
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.At(15, 30), self.ClosePositions)
        
        
    def OnData(self,slice):
        if self.Portfolio["SPY"].Quantity != 0:
            self.Liquidate()
        
        optionchain = slice.OptionChains
        for i in slice.OptionChains:
            if i.Key != self.symbol: continue
            chains = i.Value
            contract_list = [x for x in chains]
       
        if (slice.OptionChains.Count == 0) or (len(contract_list) == 0): 
            return   

        if (not self.Portfolio.Invested) and (self.Time.hour==10) and (self.Time.minute==00):
           
            if (self.SB.Close > self.FB.High) and (self.FB.High > self.SB.Low > self.FB.Low):
                
                self.SELLPUT(optionchain)
        if (not self.Portfolio.Invested) and (self.Time.hour==10) and (self.Time.minute==00):
           
            if (self.SB.Close < self.FB.Low) and (self.FB.High > self.SB.High > self.FB.Low):
               
                self.SELLCALL(optionchain)

 
    def SELLPUT(self,optionchain):
        
       
        for i in optionchain:
            if i.Key != self.symbol: continue
            chain = i.Value
            expiry = sorted(chain,key = lambda x: x.Expiry,reverse=True)[-1].Expiry
            
            put = [i for i in chain if i.Expiry == expiry and i.Right == 1]
     
            hi=[]
            for i in put:
                
                if i.Strike<=self.FB.Low:
                    hi.append(i)
                    hi=sorted(hi,key = lambda x : x.Strike)

            put_contracts = sorted(hi,key = lambda x : abs(x.Strike -self.FB.Low))
            #self.Debug(str(self.Time) + ":" + "this is the current time")
            if len(put_contracts) == 0: continue
            if str(self.Time)[0:10]==str(put_contracts[0].Expiry)[0:10]:
                
                if len(put_contracts)>7:
                    self.put_low = put_contracts[0]
                    self.buy_put=put_contracts[6]
            
                    self.Sell(self.put_low.Symbol, 1)
                    self.Buy(self.buy_put.Symbol,1)
            
    def SELLCALL(self,optionchain):
 
        for i in optionchain:
            if i.Key != self.symbol: continue
            chain = i.Value
            expiry = sorted(chain,key = lambda x: x.Expiry,reverse=True)[-1].Expiry
            call = [i for i in chain if i.Expiry == expiry and i.Right == 0]
            hi=[]
            for i in call:
                
                if i.Strike>=self.FB.High:
                    hi.append(i)
                    hi=sorted(hi,key = lambda x : x.Strike)
            call_contracts = sorted(hi,key = lambda x : abs(x.Strike -self.FB.High))
 
            if len(call_contracts) == 0: continue
            if str(self.Time)[0:10]==str(call_contracts[0].Expiry)[0:10]:
                if len(call_contracts)>=7:
                    self.call_low = call_contracts[0]
                    self.buy_call=call_contracts[6]
                    self.Sell(self.call_low.Symbol, 1)
                    self.Buy(self.buy_call.Symbol,1)



    
    def OnDataConsolidated(self, bar):
        
        if bar.Time.hour == 9 and bar.Time.minute == 30:
            self.FB = bar
            #self.Debug("yes")
        if bar.Time.hour == 9 and bar.Time.minute ==45:
            self.SB = bar  
        
    
    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status == OrderStatus.Filled and orderEvent.Symbol.SecurityType == SecurityType.Option:
            q = orderEvent.FillQuantity
            p = orderEvent.FillPrice
            m = self.optionMultiplier
            cashflow = q * p * m
            if self.Portfolio[orderEvent.Symbol].Invested:
                self.costs[orderEvent.Symbol] = cashflow
            else:
                pnl = -(self.costs[orderEvent.Symbol] + cashflow)
        
    def ClosePositions(self):

        self.SB = None
        self.FB = None

    def UniverseFunc(self, universe):
         # include weekly contracts
        return universe.IncludeWeeklys().Expiration(TimeSpan.FromDays(0),TimeSpan.FromDays(3)).Strikes(-10,10)