# region imports
from AlgorithmImports import *
from QuantConnect.Securities.Option import OptionPriceModels
# endregion
class CalmVioletWhale(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2022, 11, 1) # Set Start Date
self.SetEndDate(datetime.now())
self.SetCash(100000) # Set Strategy Cash
self.equity = self.AddEquity("SPY", Resolution.Minute)
self.symbol = self.equity.Symbol
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.equity.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.SetBenchmark(self.symbol)
option = self.AddOption("SPY", Resolution.Hour)
# Strikes in the filter need to be made dynamic, a % on current price
option.SetFilter(-75, 75, timedelta(45), timedelta(65))
option.PriceModel = OptionPriceModels.BjerksundStensland()
self.targetdelta = 0.2
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose("SPY", 10), self.OpenCondor)
def OnData(self, data: Slice):
pass
def OpenCondor(self):
def RoundBaseFive(x, base=5):
return base * round(x/base)
longPut = None
shortPut = None
shortCall = None
longCall = None
for i in self.CurrentSlice.OptionChains:
chain = [x for x in i.Value]
# If no option chain, return
if (self.CurrentSlice.OptionChains.Count == 0):
return
# Sort option chain by expiration, choose furthest date
expiry = sorted(chain, key = lambda x: x.Expiry)[-1].Expiry
self.Log(str("Chosen expiry") + str(expiry))
# filter calls and puts
call = [i for i in chain if i.Right == OptionRight.Call and i.Expiry == expiry]
put = [i for i in chain if i.Right == OptionRight.Put and i.Expiry == expiry]
# sort calls by delta
call_sorted = sorted(call, key = lambda x: x.Greeks.Delta)
# get strike of contract with target delta
call_delta = min(call_sorted, key = lambda x: abs(self.targetdelta - x.Greeks.Delta)).Strike
self.Log(str("Call Strike Chosen: ") + str(call_delta))
# round to nearest base 5 to get a more liquid strike
call_strike = RoundBaseFive(call_delta)
self.Log(str("Call Strike Rounded: ") + str(call_strike))
self.Log(str("Underlying Price") + str(self.Securities[self.symbol].Price))
shortCall = sorted(call_sorted, key = lambda x: x.Strike == call_strike)[0]
self.Sell(shortCall.Symbol, 1)
# most concerning is incorrect expiration chosen. Some Call strikes are below underlying..