Overall Statistics
Total Trades
435
Average Win
25.17%
Average Loss
-0.57%
Compounding Annual Return
19.134%
Drawdown
86.700%
Expectancy
1.555
Net Profit
1185.231%
Sharpe Ratio
0.441
Probabilistic Sharpe Ratio
0.000%
Loss Rate
94%
Win Rate
6%
Profit-Loss Ratio
44.36
Alpha
0.59
Beta
0.527
Annual Standard Deviation
1.487
Annual Variance
2.211
Information Ratio
0.357
Tracking Error
1.486
Treynor Ratio
1.246
Total Fees
$16838.79
Estimated Strategy Capacity
$21000000.00
Lowest Capacity Asset
SPY 31Q9LB7UFPYX2|SPY R735QTJ8XC9X
class UncoupledTransdimensionalPrism(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2007, 1, 1)  # Set Start Date
        #self.SetEndDate(2020, 4, 1)
        self.SetCash(100000)  # Set Strategy Cash
        spy = self.AddEquity("SPY", Resolution.Minute)
        spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.SetSecurityInitializer(lambda security: security.SetMarketPrice(self.GetLastKnownPrice(security)))
        self.spy = spy.Symbol
        self.contract = None
        self.secondcontract = None
        self.thirdcontract = None
        self.fourthcontract = None
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
            self.TimeRules.AfterMarketOpen("SPY", 5), self.TailRiskExit)
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
            self.TimeRules.AfterMarketOpen("SPY", 10), self.Roll)
        self.Schedule.On(self.DateRules.EveryDay("SPY"), 
            self.TimeRules.AfterMarketOpen("SPY", 15), self.OptionsSetup)
        self.expiry1 = 60
        self.expiry2 = 150
        self.buycontract = True
        self.buysecondcontract = True
        self.buythirdcontract = True
        self.buyfourthcontract = True
        
    def TailRiskExit(self): 
        
        if self.contract != None:
            if self.Securities[self.spy].Price < self.contract.ID.StrikePrice *1.175 :
                self.Liquidate(self.contract)
                self.RemoveSecurity(self.contract)
                self.contract = None

        if self.secondcontract != None:
            if self.Securities[self.spy].Price < self.secondcontract.ID.StrikePrice *1.175 :
                self.Liquidate(self.secondcontract)
                self.RemoveSecurity(self.secondcontract)
                self.secondcontract = None
                
        if self.thirdcontract != None:
            if self.Securities[self.spy].Price < self.thirdcontract.ID.StrikePrice *1.175 :
                self.Liquidate(self.thirdcontract)
                self.RemoveSecurity(self.thirdcontract)
                self.thirdcontract = None

        if self.fourthcontract != None:
            if self.Securities[self.spy].Price < self.fourthcontract.ID.StrikePrice *1.175 :
                self.Liquidate(self.fourthcontract)
                self.RemoveSecurity(self.fourthcontract)
                self.fourthcontract = None
                
    def Roll(self):
        
        if self.contract != None:
            if (self.contract.ID.Date - self.Time).days <=  20:
                self.Liquidate(self.contract)
                self.RemoveSecurity(self.contract)
                self.contract = None
                self.buycontract=True
        
        if self.secondcontract != None:    
            if (self.secondcontract.ID.Date - self.Time).days <=  25:
                self.Liquidate(self.secondcontract)
                self.RemoveSecurity(self.secondcontract)
                self.secondcontract = None
                self.buysecondcontract=True
                
        if self.thirdcontract != None:
            if (self.thirdcontract.ID.Date - self.Time).days <=  30:
                self.Liquidate(self.thirdcontract)
                self.RemoveSecurity(self.thirdcontract)
                self.thirdcontract = None
                self.buythirdcontract=True
        
        if self.fourthcontract != None:    
            if (self.fourthcontract.ID.Date - self.Time).days <=  35:
                self.Liquidate(self.fourthcontract)
                self.RemoveSecurity(self.fourthcontract)
                self.fourthcontract = None
                self.buyfourthcontract=True
            
    def OptionsSetup(self):
        
        if self.contract is None:
            self.contract = self.GetContract(self.expiry1,self.expiry2,strike=0)
            
        if self.secondcontract is None:
            self.secondcontract = self.GetContract(self.expiry1,self.expiry2,strike=1)
 
        if self.thirdcontract is None:
            self.thirdcontract = self.GetContract(self.expiry1,self.expiry2,strike=2)
            
        if self.fourthcontract is None:
            self.fourthcontract = self.GetContract(self.expiry1,self.expiry2,strike=3)           


        if self.buycontract and self.contract != None:
            self.SetHoldings(self.contract, 0.0025)
            self.buycontract=False
                
        if self.buysecondcontract and self.secondcontract != None:
            self.SetHoldings(self.secondcontract, 0.0025)
            self.buysecondcontract = False
            
        if self.buythirdcontract and self.thirdcontract != None:
            self.SetHoldings(self.thirdcontract, 0.0025)
            self.buythirdcontract=False
                
        if self.buyfourthcontract and self.fourthcontract != None:
            self.SetHoldings(self.fourthcontract, 0.0025)
            self.buyfourthcontract = False
        if self.Portfolio.Cash > (self.Portfolio.TotalPortfolioValue* 0.05):
            self.SetHoldings(self.spy, 0.99)
    
    def GetContract(self,firstexpiry,secondexpiry,strike):
        targetStrike = (self.Securities[self.spy].Price * 0.6) - (self.Securities[self.spy].Price * 0.6)%5
        contracts = self.OptionChainProvider.GetOptionContractList(self.spy, self.Time)
        puts = [x for x in contracts if x.ID.OptionRight == OptionRight.Put]
        puts = sorted( sorted(puts, key = lambda x: x.ID.Date, reverse = False),
                       key = lambda x: x.ID.StrikePrice)
        puts = [x for x in puts if targetStrike* 0.975 < x.ID.StrikePrice < targetStrike* 1.025]
        puts = [x for x in puts if firstexpiry < (x.ID.Date - self.Time).days <= secondexpiry]
        

        
        if len(puts) == 0:
            return None
        else:
        
            closestdate = puts[0].ID.Date
            puts=[x for x in puts if x.ID.Date == closestdate]
            if len(puts) >= strike+1:
                self.AddOptionContract(puts[strike], Resolution.Minute)
                return puts[strike]
            else:
                return None