class TransdimensionalPrism(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 1) # Set Start Date
self.SetEndDate(2020, 4, 5)
self.SetCash(10000) # Set Strategy Cash
self.SetWarmUp(15)
#SPY DATA
spy = self.AddEquity("SPY", Resolution.Minute)
spy.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.spy = spy.Symbol
self.spycontract = None
#TQQQ DATA
tqqq = self.AddEquity("TQQQ", Resolution.Minute)
tqqq.SetDataNormalizationMode(DataNormalizationMode.Raw)
self.tqqq = tqqq.Symbol
self.tqqqcontract = None
#Scheduled Events============================================
self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 1), self.monthlyRebalance)
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 1), self.captureOpening)
#Variables needed for stoploss
self.stoplosshold = 0
self.dailyOpen: Dict[Symbol,float] = {
self.spy: 0,
}
self.weights: Dict[Symbol,float] = {
self.spy: 0.9,
}
#Underlyings and Options dictionary
self.uNos = {
#self.spy : self.spycontract,
self.tqqq : self.tqqqcontract
}
def OnData(self, data):
if not self.Portfolio[self.spy].Invested:
self.SetHoldings(self.spy, 0.9)
# DO HEDGE
self.getContract()
self.timeDC()
self.setContracts()
self.exerciseContracts()
def getContract(self):
for underlying, contract in self.uNos.items():
if contract is None:
targetStrike = (self.Securities[underlying].Price * 0.6) - (self.Securities[underlying].Price * 0.6)%5
xcontracts = self.OptionChainProvider.GetOptionContractList(underlying, self.Time)
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 270 < (x.ID.Date - self.Time).days <= 420]
if len(puts) == 0:
return None
self.AddOptionContract(puts[0], Resolution.Minute)
self.uNos[underlying] = puts[0]
x = 0
def timeDC(self):
for underlying, contract in self.uNos.items():
if contract is None:
continue
if (contract.ID.Date - self.Time).days < 180:
#self.Log("Liquidated time 180")
self.Liquidate(contract)
self.RemoveSecurity(contract)
self.uNos[underlying] = None
return
def setContracts(self):
for underlying, contract in self.uNos.items():
if contract is None:
continue
if not self.Portfolio[contract].Invested:
self.SetHoldings(contract, 0.1)
#self.Log("Set Holdings")
def exerciseContracts(self):
for underlying, contract in self.uNos.items():
if contract is None:
continue
#self.Log(self.Portfolio[contract].UnrealizedProfit)
#self.Log(self.Portfolio[contract].UnrealizedProfitPercent)
#Exercise When reach strike price
if self.Securities[underlying].Price < contract.ID.StrikePrice:
#if self.Log(self.Portfolio[contract].UnrealizedProfit) > 1000:
#self.Log("Liquidated StrikePrice")
self.Liquidate(contract)
#self.RemoveSecurity(contract)
self.RemoveOptionContract(contract)
self.uNos[underlying] = None
x=0
def monthlyRebalance(self):
# Rebalance portfolio monthly
if self.IsWarmingUp:
return
for key,value in self.weights.items():
self.SetHoldings(key,value)
def captureOpening(self):
#Grabs the daily opening price of spy for our stoploss method
if self.IsWarmingUp:
return
for key, value in self.dailyOpen.items():
if self.CurrentSlice.Bars.ContainsKey(key):
self.dailyOpen[key] = self.CurrentSlice[key].Open
self.stoplosshold = 0
def stoploss(self, data):
'''
Stoploss logic:
- If spy drops more than 5% liquidate entire equity portfolio
- Change stoplosshold value to 1, this indicates that the portfolios SL has been hit
and were going to hold until the next trading day
'''
if self.IsWarmingUp:
return
for symbol, weight in self.weights.items():
if self.Securities[symbol].Price == 0:
continue
open = self.dailyOpen[symbol]
#See if any symbol has decreased more than 5% in a given day, liquidate if true and check next one...
if ((self.Securities[symbol].Price-open)/self.Securities[symbol].Price) < -.05:
self.SetHoldings(symbol, 0)
self.stoplosshold = 1
#self.Log('HIT')
def plotting(self):
pass