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
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
#Need to change the liquidate to later in the day
#Same goes for when this is executed

from datetime import timedelta
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Securities.Option import OptionPriceModels
from QuantConnect.Data.UniverseSelection import *

class BasicTemplateOptionsAlgorithm(QCAlgorithm):

    contracts = 1
    shortDelta = .18
    longDelta = .15
    
    

    def Initialize(self):
        self.SetStartDate(2021, 1, 1)
        self.SetEndDate(2021, 2, 1)
        self.SetCash(100000)
        self.symbol = "TSLA"
        self.expiry = self.Time
       

        equity = self.AddEquity(self.symbol, Resolution.Minute)
        option = self.AddOption(self.symbol, Resolution.Minute)
        option.SetFilter(-20, 20, timedelta(30), timedelta(60))
        option.PriceModel = OptionPriceModels.CrankNicolsonFD()
        
        self.logs = 0
        
#       self.MaximumOrderValue = 20000

        # use the underlying equity as the benchmark
        self.SetBenchmark(equity.Symbol)
        self.SetWarmUp(35, Resolution.Daily) 

    def OnData(self, slice):
        if(self.IsWarmingUp):
            return
        
        # Run once per hour
        if slice.Time.minute != 0:
            return
        
        
        self.TradeOptions(slice)

    def TradeOptions(self, slice):
        days_to_expiry = (self.expiry-self.Time).days
        if self.Portfolio.Invested and days_to_expiry <=20:
                self.Liquidate()
                
        profit2 = sum([x.UnrealizedProfitPercent for x in self.Portfolio.Values if x.Type == SecurityType.Option])
        
        self.logs += 1
        self.Log(f"profit2 at {self.Time} {slice.Time}: {profit2}")
        if self.logs > 5:
            self.Quit()
            return
        
        if self.Portfolio.Invested and profit2 >= .5:
            self.Liquidate()
            
        if not self.Portfolio.Invested: 
        
            shortCall = None
            longCall = None
            shortPut = None
            longPut = None

            for i in slice.OptionChains:
                chain = [x for x in i.Value if x.ImpliedVolatility < 50]
                contract_list = [x for x in chain]
                
                # if there is no optionchain or no contracts in this optionchain, pass the instance
                if (slice.OptionChains.Count == 0) or (len(contract_list) == 0): 
                    return   
    
                # sorted optionchain by expiration date and choose the furthest date
                self.expiry = sorted(chain, key = lambda x: x.Expiry)[-1].Expiry
                
                
                # filter call and put options from the contracts
                call = [i for i in chain if i.Right == 0 and i.Expiry == self.expiry]
                put = [i for i in chain if i.Right == 1 and i.Expiry == self.expiry]
    
                # sort calls by strike prices in ascending order
                call_contracts = sorted(call, key = lambda x: x.Strike)    
                # sort puts by strike prices in descending order
                put_contracts = sorted(put, key = lambda x: x.Strike, reverse=True)    
                
                if len(call_contracts) == 0 or len(put_contracts) == 0 : 
                    continue
                
                for contract in call_contracts + put_contracts:
                    self.Log(f"IV at {self.Time} for {contract.Symbol}: {contract.ImpliedVolatility}")
                
                # loop from low strike to high
                for call in call_contracts:
                    #self.Log("call=" + str(call.Greeks.Delta))

                    if((shortCall is None) and (call.Greeks.Delta <= self.shortDelta)):
                        shortCall = call
                    elif((longCall is None) and (call.Greeks.Delta <= self.longDelta)):
                        longCall = call
                        break # stop for loop

                # loop from high strike to low
                for put in put_contracts:
                    #self.Log("put=" + str(put.Greeks.Delta))

                    if((shortPut is None) and (put.Greeks.Delta >= -self.shortDelta)):
                        shortPut = put
                    elif((longPut is None) and (put.Greeks.Delta >= -self.longDelta)):
                        longPut = put
                        break # stop for loop

                if((longCall is not None) and (shortCall is not None) and (longPut is not None) and (shortPut is not None)):
                    break

            if((longCall is None) or (shortCall is None) or (longPut is None) or (shortPut is None)):
                return
            

            #self.Log(str(longCall.Greeks.Delta))
            #self.Log(str(shortCall.Greeks.Delta))
            #self.Log(str(shortPut.Greeks.Delta))
            #self.Log(str(longPut.Greeks.Delta))

            # trade the options 
            self.Buy(longCall.Symbol, self.contracts)
            self.Sell(shortCall.Symbol, self.contracts)
            self.Sell(shortPut.Symbol, self.contracts)
            self.Buy(longPut.Symbol, self.contracts)