Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-3.832
Tracking Error
0.088
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
#region imports
from AlgorithmImports import *
#endregion
from QuantConnect import *
from QuantConnect.Algorithm import *
from datetime import timedelta
from QuantConnect.Securities.Option import OptionPriceModels


class BasicTemplateOptionsAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 1, 1)
        self.SetEndDate(2020, 1, 8)
        self.SetCash(10000)

        option = self.AddOption("SPY", Resolution.Minute)
        self.spy = self.AddEquity("SPY", Resolution.Minute)
        self.option_symbol = option.Symbol
        self.spy_symbol = self.spy.Symbol
        self.callcontract = None
        self.putcontract = None
        self.uNos = {'calls' : {self.spy_symbol : self.callcontract},
                    'puts' : {self.spy_symbol : self.putcontract}
        }
        self.data = None
        

        option.PriceModel = OptionPriceModels.CrankNicolsonFD()  # both European & American, automatically

        # set our strike/expiry filter for this option chain
        self.SetWarmUp(7)
    
    
        #Scheduled Events
        self.oldDelta = 0
        self.newDeltas = 0
        self.callexpiry = 0
        self.putexpiry = 0 
        self.Schedule.On(self.DateRules.WeekStart("SPY"), 
                        self.TimeRules.AfterMarketOpen(self.spy.Symbol, 10),         
                        Action(self.getGreeks))


    def OnData(self, slice):
        
        self.data = slice
        
        self.getContracts()
        
        self.timeDecayCheck()

        self.setContracts()
        
        #self.profitTake()



    def getContracts(self):
        
        if self.IsWarmingUp:
            return
        for right,_ in self.uNos.items():
            if right == 'calls':
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        # ATM call option 
                        targetStrike = (self.Securities[underlying].Price *1) - (self.Securities[underlying].Price * 1)%5
                        xcontracts = self.OptionChainProvider.GetOptionContractList("SPY", self.Time)
                        '''
                        ERROR:
                            When I am debugging this algorithm, on line 69, xcontracts is a list of option contracts, but when I reach line 74, the xcontracts variable 
                            becomes and error and watch window says NameError ("name 'xcontracts' is not defined")
                        '''
                        if self.CurrentSlice.Bars.ContainsKey(underlying):
                            calls = [x for x in xcontracts if x.ID.OptionRight == OptionRight.Call]
                            calls = sorted( sorted(calls, key = lambda x: x.ID.Date, reverse = True),
                            key = lambda x: x.ID.StrikePrice)
                            calls = [x for x in calls if x.ID.StrikePrice == targetStrike]
                            calls = [x for x in calls if 50 < (x.ID.Date - self.Time).days <= 60]
                            if len(calls) == 0:
                                calls = sorted(calls, key = lambda x: x.ID.Date, reverse=True)
                            if len(calls) == 0:    
                                return None
                            self.AddOptionContract(calls[0], Resolution.Minute)
                            self.uNos[right][underlying] = calls[0]
                        
                        
            if right == 'puts':
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        #40% OTM call option 
                        targetStrike = (self.Securities[underlying].Price *1) - (self.Securities[underlying].Price *1)%5
                        xcontracts = self.OptionChainProvider.GetOptionContractList("SPY", self.Time)
                        if self.CurrentSlice.Bars.ContainsKey(underlying):
                            puts = [x for x in xcontracts if x.ID.OptionRight == OptionRight.Put]
                            puts = sorted( sorted(puts, key = lambda x: x.ID.Date, reverse = True),
                            key = lambda x: x.ID.StrikePrice)
                            puts = [x for x in puts if x.ID.StrikePrice == targetStrike]
                            puts = [x for x in puts if 50 < (x.ID.Date - self.Time).days <= 60]
                            if len(puts) == 0:
                                return None
                            self.AddOptionContract(puts[0], Resolution.Minute)
                            self.uNos[right][underlying] = puts[0]
                            self.Log("Delta: " + str(puts[0].Greeks.Delta))
        

    def getGreeks(self):
        if self.IsWarmingUp:
            return
        #if  self.callcontract or self.putcontract is None: return
        
        #Get invested Option Values
        for symbol, chain in self.data.OptionChains.items():
            for contract in chain:
                if self.Portfolio[contract.Symbol].Invested:
                    #self.MarketOrder("SPY", int((contract.Greeks.Delta)*100))
                    #Get Latest Delta
                    x = int((contract.Greeks.Delta)*100)
                    #self.Log(int((contract.Greeks.Delta)*100))
                    self.newDeltas += x
                    #self.newDeltas = int((contract.Greeks.Delta) * 100)
                    #See quantity of hedging

        #self.newDeltas = sum(self.newDeltas)
        adjDelta = int(self.oldDelta) - int(self.newDeltas)    
        #Perform Hedges
        self.MarketOrder("SPY", adjDelta)
        #Make Store delta value for next hedge
        self.oldDelta = self.newDeltas


    def timeDecayCheck(self):
        #Need to fix my time decay check method
        
        if self.IsWarmingUp:
            return
        #Liquidating on Expiration
        for right,cluster in self.uNos.items():
            if right == 'calls':
                #continue
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        continue
                    if (contract.ID.Date - self.Time).days < 1:
                        self.Liquidate(contract)
                        self.callcontract = None
            if right == 'puts':
                #continue
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        continue
                    if (contract.ID.Date - self.Time).days < 1:
                        self.Liquidate(contract)
                        self.putcontract = None
    
    def profitTake(self):
        return 
    
        if self.IsWarmingUp:
            return
        
        for right,cluster in self.uNos.items():
            if right == 'puts':
                for underlying,contract in self.uNos[right].items():
                    if self.Portfolio[contract].UnrealizedProfitPercent > 1:
                        self.Liquidate(contract)
                        self.uNos[right][underlying] = None


    def setContracts(self):
        for right, cluster in self.uNos.items():
            if right == 'calls':
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        continue
                    if not self.Portfolio[contract].Invested:
                        if self.CurrentSlice.Bars.ContainsKey(underlying):
                            if self.Securities[contract].Price != 0:
                                self.MarketOrder(contract, 1)
                            
            if right == 'puts':
                for underlying, contract in self.uNos[right].items():
                    if contract is None:
                        continue
                    if (self.purchasedTRH == True):
                        continue
                    if not self.Portfolio[contract].Invested:
                        if self.CurrentSlice.Bars.ContainsKey(underlying):
                        #self.SetHoldings(contract, 0.03)
                            if self.Securities[contract].Price != 0:
                            # SHILE: PUT ADDITIONAL CHECKS HERE
                                self.MarketOrder(contract, 1)