| Overall Statistics |
|
Total Trades 2 Average Win 0% Average Loss 0% Compounding Annual Return 45.152% Drawdown 40.000% Expectancy 0 Net Profit 2.300% Sharpe Ratio 2.201 Probabilistic Sharpe Ratio 50.307% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 4.215 Beta 4.002 Annual Standard Deviation 1.322 Annual Variance 1.747 Information Ratio 3.134 Tracking Error 1.032 Treynor Ratio 0.727 Total Fees $10.50 |
from QuantConnect.Securities.Option import OptionPriceModels
class TransdimensionalResistanceReplicator(QCAlgorithm):
#sell calls
def Initialize(self):
self.SetStartDate(2020, 6, 9) # Set Start Date
self.SetCash(100000) # Set Strategy Cash
self.SetEndDate(2020, 7, 1) # Set End Date
self.equityVxx = self.AddEquity("VXX", Resolution.Minute)
self.equitySpy = self.AddEquity("SPY", Resolution.Minute)
self.symbols = []
for ticker in ["VXX", "SPY"]:
option = self.AddOption(ticker)
self.symbols.append(option.Symbol)
option.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
option.PriceModel = OptionPriceModels.CrankNicolsonFD()
#vxxOptions = self.AddOption("VXX")
#vxxOptions.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
#vxxOptions.PriceModel = OptionPriceModels.CrankNicolsonFD()
#spyOptions = self.AddOption("SPY")
#spyOptions.SetFilter(TimeSpan.FromDays(15),TimeSpan.FromDays(38))
#spyOptions.PriceModel = OptionPriceModels.CrankNicolsonFD()
#cash buffer
self.Settings.FreePortfolioValuePercentage = 0.02
#dict of limit orders open
self.__openLimitOrders = []
self.SetWarmUp(30, Resolution.Daily)
def OnData(self, slice):
if self.IsWarmingUp: return
option_invested = [x.Key for x in self.Portfolio if x.Value.Invested and x.Value.Type==SecurityType.Option]
if self.HourMinuteIs(10, 00):
self.underlyingPriceVxx = self.Securities[self.equityVxx.Symbol].Price
self.underlyingPriceSpy = self.Securities[self.equitySpy.Symbol].Price
#self.Debug("Current " + str(self.Securities[self.equityVxx.Symbol]) + ", " + str(self.underlyingPriceVxx) + ", " + str(self.Securities[self.equitySpy.Symbol]) + ", " + str(self.underlyingPriceSpy) + ", at " + str(self.Time))
for symbol in self.symbols:
#checking to see if there is already an open position in the ticker
invested = [option for option in option_invested if option.Underlying == symbol.Underlying]
if len(invested) > 0: return
for chain in slice.OptionChains:
if str(chain.Key) == "?VXX":
self.optionchain = [contract for contract in chain.Value if contract.Right is 0 and contract.Strike - self.underlyingPriceVxx > 1]
if len(self.optionchain) == 0:
self.Debug("no chain options")
continue
self.sortedVxx = sorted(self.optionchain, key=lambda k : k.Expiry, reverse=False)
self.greekVxx = [contract for contract in self.sortedVxx if contract.Greeks.Delta >= .25 and contract.Greeks.Delta <= .35 ]
self.popVxx = sorted(sorted(self.greekVxx, \
key=lambda k: k.Greeks.Delta, reverse=False),
key=lambda k: k.OpenInterest, reverse=True)
#for contract in self.popVxx:
#self.Debug(str(contract.Expiry) + ", " + str(contract.Strike) + ", " + str(contract.UnderlyingSymbol) + ", " + str(contract.Right) + ", " + str(contract.Greeks.Delta) + ", " + str(contract.OpenInterest))
#generally want to buy on a wednesday.
self.liquidContract = self.popVxx[0]
#self.Debug("Selling this contract: ")
#self.Debug(str(self.liquidContract.Expiry) + ", " + str(self.liquidContract.Strike) + ", " + str(self.liquidContract.UnderlyingSymbol) + ", " + str(self.liquidContract.Right) + ", " + str(self.liquidContract.Greeks.Delta) + ", " + str(self.liquidContract.OpenInterest))
#use criterion to choose how many options to sell
quantityVxx = self.CalculateOrderQuantity(self.liquidContract.Symbol, 0.05)
#self.Debug("quantity of VXX contracts to sell " + str(-1 * (quantityVxx)) + ", at limit " + str(self.liquidContract.AskPrice) )
newTicket = self.LimitOrder(self.liquidContract.Symbol, -1 * (quantityVxx), round(self.liquidContract.AskPrice, 2))
self.__openLimitOrders.append(newTicket)
self.Debug("# limit orders " + str(len(self.__openLimitOrders)))
if len(self.__openLimitOrders) == 1:
self.openOrders = self.__openLimitOrders
#vxxOrder = self.openOrders[0]
#orderId = vxxOrder.OrderId
#newTicketId = self.newTicket.OrderId
#self.Debug("newTicket status " + str(self.newTicket.Status))
#self.Debug("order status " + str(OrderStatus.Filled))
#self.Debug("order id " + str(vxxOrder.OrderId))
#check if order got filled
#filled = self.OnOrderEvent(vxxOrder)
#self.Debug("filled : " + str(filled))
#if self.newTicket.Status == OrderStatus.Filled:
#if filled == 0:
#self.Debug("Order Filled")
#self.__openLimitOrders = []
#if it didn't get filled, do more reasonable limit
#elif vxxOrder.Status != OrderStatus.Filled:
#elif filled == 1:
#self.newLimit = round(vxxOrder.Get(OrderField.LimitPrice) - 0.01, 2)
#self.Debug("Updating limits - Price " + str(self.newLimit))
#updateSettings = UpdateOrderFields()
#updateSettings.LimitPrice = self.newLimit
#vxxOrder.Update(updateSettings)
def HourMinuteIs(self, hour, minute):
return self.Time.hour == hour and self.Time.minute == minute
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
if orderEvent.Status == OrderStatus.Filled:
self.Debug("{0}: {1}: {2}".format(self.Time, order.Type, orderEvent))