| Overall Statistics |
|
Total Trades 2 Average Win 3.74% Average Loss 0% Compounding Annual Return 3.741% Drawdown 3.500% Expectancy 0 Net Profit 3.738% Sharpe Ratio 0.747 Probabilistic Sharpe Ratio 37.912% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.004 Beta 0.111 Annual Standard Deviation 0.035 Annual Variance 0.001 Information Ratio -1.685 Tracking Error 0.102 Treynor Ratio 0.238 Total Fees $8.60 Estimated Strategy Capacity $49000000.00 Lowest Capacity Asset ES XPFJZVPGHL35 Portfolio Turnover 0.41% |
# region imports
from AlgorithmImports import *
# endregion
class EnergeticAsparagusCormorant(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 1, 1) # Set Start Date
self.SetEndDate(2022, 1, 1) # Set End Date
self.SetCash(500000) # Set Strategy Cash
self.future = self.AddFuture(Futures.Indices.SP500EMini, extendedMarketHours= True)
self.future.SetFilter(0, 182)
#self.future.SetFilter(lambda future_filter_universe: future_filter_universe.FrontMonth())
self.symbol = self.future.Symbol
self.Vix = self.AddFuture(Futures.Indices.VIX, extendedMarketHours= True)
self.Vix.SetFilter(0, 182)
#self.Vix.SetFilter(lambda future_filter_universe: future_filter_universe.FrontMonth())
self.Vixsymbol = self.Vix.Symbol
# ES vars
self.Longentry_ticket = None
self.Shortentry_ticket = None
self.ESstopTicket = None
self.ESprofitTicket = None
self.LongcontractSymbol = None
self.ShortcontractSymbol = None
self.Esprice = None
self.ShortEsprice = None
# VIX vars
self.Vixentry_ticket = None
self.ShortVixentry_ticket = None
self.VixstopTicket = None
self.VixprofitTicket = None
self.VixcontractSymbol = None
self.ShortVixcontractSymbol = None
self.VixPrice = None
self.ShortVixPrice = None
self.sma = SimpleMovingAverage(200)
self.RegisterIndicator(self.symbol, self.sma, Resolution.Daily)
def OnData(self, data: Slice):
if (self.Longentry_ticket is None and self.Vixentry_ticket is None) and (self.Shortentry_ticket == None and self.ShortVixentry_ticket == None):
if self.Securities[self.symbol].Price > self.sma.Current.Value:
self.BuyFuture(data)
elif self.Securities[self.symbol].Price < self.sma.Current.Value:
self.ShortFuture(data)
if self.Portfolio.Invested:
# avoids error
if self.LongcontractSymbol == None or self.VixcontractSymbol == None or self.ShortVixcontractSymbol == None or self.ShortcontractSymbol == None:
return
# will sell before an expiration or delisting:
if self.Portfolio[self.LongcontractSymbol.Symbol].IsLong:
if self.Time + timedelta(1) > self.LongcontractSymbol.Expiry:
self.Liquidate(self.LongcontractSymbol.Symbol, "Future too close to expiration.")
self.Longentry_ticket = None
if self.Portfolio[self.VixcontractSymbol.Symbol].IsLong:
if self.Time + timedelta(1) > self.VixcontractSymbol.Expiry:
self.Liquidate(self.VixcontractSymbol.Symbol, "Future too close to expiration.")
self.Vixentry_ticket = None
if self.Portfolio[self.ShortVixcontractSymbol.Symbol].IsShort:
if self.Time + timedelta(1) > self.ShortVixcontractSymbol.Expiry:
self.Liquidate(self.ShortVixcontractSymbol.Symbol, "Future too close to expiration.")
self.ShortVixentry_ticket = None
if self.Portfolio[self.ShortcontractSymbol.Symbol].IsShort:
if self.Time + timedelta(1) > self.ShortcontractSymbol.Expiry:
self.Liquidate(self.ShortcontractSymbol.Symbol, "Future too close to expiration.")
self.Shortentry_ticket = None
def BuyFuture(self, data: Slice):
# get the ES chain
chain = data.FuturesChains.get(self.symbol)
if chain:
self.LongcontractSymbol = sorted(chain, key=lambda contract: contract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.Esprice = self.Securities[self.LongcontractSymbol.Symbol].Price
self.Longentry_ticket = self.LimitOrder(self.LongcontractSymbol.Symbol, 2, self.Esprice)
# send out bracket order
self.ESprofitTicket = self.LimitOrder(self.LongcontractSymbol.Symbol, -2, self.Esprice*1.05)
self.ESstopTicket = self.StopMarketOrder(self.LongcontractSymbol.Symbol, -2, self.Esprice*0.95)
# get the Vix chain
Vixchain = data.FuturesChains.get(self.Vixsymbol)
if Vixchain:
self.VixcontractSymbol = sorted(Vixchain, key=lambda Vixcontract: Vixcontract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.VixPrice = self.Securities[self.VixcontractSymbol.Symbol].Price
self.Vixentry_ticket = self.LimitOrder(self.VixcontractSymbol.Symbol, 4, self.VixPrice)
# send out bracket order
self.VixprofitTicket = self.LimitOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*1.05)
self.VixstopTicket = self.StopMarketOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*0.95)
else:
self.Log("failed to get Vix chain")
return
def BuyVix(self, data: Slice):
# get the Vix chain
Vixchain = data.FuturesChains.get(self.Vixsymbol)
if Vixchain:
self.VixcontractSymbol = sorted(Vixchain, key=lambda Vixcontract: Vixcontract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.VixPrice = self.Securities[self.VixcontractSymbol.Symbol].Price
self.Vixentry_ticket = self.LimitOrder(self.VixcontractSymbol.Symbol, 4, self.VixPrice)
# send out bracket order
self.VixprofitTicket = self.LimitOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*1.05)
self.VixstopTicket = self.StopMarketOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*0.95)
else:
self.Log("failed to get Vix chain")
return
def ShortFuture(self, data: Slice):
chain = data.FuturesChains.get(self.symbol)
if chain:
self.ShortcontractSymbol = sorted(chain, key=lambda contract: contract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.Esprice = self.Securities[self.ShortcontractSymbol.Symbol].Price
self.Shortentry_ticket = self.LimitOrder(self.ShortcontractSymbol.Symbol, -2, self.Esprice)
# send out bracket order
self.ESprofitTicket = self.LimitOrder(self.ShortcontractSymbol.Symbol, 2, self.Esprice*0.95)
self.ESstopTicket = self.StopMarketOrder(self.ShortcontractSymbol.Symbol, 2, self.Esprice*1.05)
Vixchain = data.FuturesChains.get(self.Vixsymbol)
if Vixchain:
self.ShortVixcontractSymbol = sorted(chain, key=lambda Vixcontract: Vixcontract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.VixPrice = self.Securities[self.ShortVixcontractSymbol.Symbol].Price
self.ShortVixentry_ticket = self.LimitOrder(self.ShortVixcontractSymbol.Symbol, -4, self.VixPrice)
# send out bracket order
self.VixprofitTicket = self.LimitOrder(self.ShortVixcontractSymbol.Symbol, 4, self.VixPrice*0.95)
self.VixstopTicket = self.StopMarketOrder(self.ShortVixcontractSymbol.Symbol, 4, self.VixPrice*1.05)
else:
self.Log("failed to get Vix chain")
return
def ShortVix(self, data: Slice):
Vixchain = data.FuturesChains.get(self.Vixsymbol)
if Vixchain:
self.ShortVixcontractSymbol = sorted(chain, key=lambda Vixcontract: Vixcontract.Expiry, reverse=True)[0]
# save price and enter with limit order
self.VixPrice = self.Securities[self.ShortVixcontractSymbol.Symbol].Price
self.ShortVixentry_ticket = self.LimitOrder(self.ShortVixcontractSymbol.Symbol, -4, self.VixPrice)
# send out bracket order
self.VixprofitTicket = self.LimitOrder(self.ShortVixcontractSymbol.Symbol, 4, self.VixPrice*0.95)
self.VixstopTicket = self.StopMarketOrder(self.ShortVixcontractSymbol.Symbol, 4, self.VixPrice*1.05)
else:
self.Log("failed to get Vix chain")
return
def OnOrderEvent(self, orderEvent):
#self.Log(str(orderEvent))
# Invalid order is blocking new orders
if orderEvent.Status == OrderStatus.Invalid:
self.Longentry_ticket = None
self.Vixentry_ticket = None
self.Shortentry_ticket = None
self.ShortVixentry_ticket = None
return
if orderEvent.Status != OrderStatus.Filled:
return
# avoids error
if self.LongcontractSymbol is None or self.ShortcontractSymbol is None:
return
#if orderEvent.OrderId == self.Longentry_ticket.OrderId:
#return
# cancel the other ES order after one gets hit
if orderEvent.Symbol == self.LongcontractSymbol.Symbol:
if orderEvent.OrderId == self.ESprofitTicket.OrderId or orderEvent.OrderId == self.ESstopTicket.OrderId:
self.Transactions.CancelOpenOrders(self.LongcontractSymbol.Symbol)
self.Longentry_ticket = None
return
elif orderEvent.Symbol == self.ShortcontractSymbol.Symbol:
if orderEvent.OrderId == self.ESprofitTicket.OrderId or orderEvent.OrderId == self.ESstopTicket.OrderId:
self.Transactions.CancelOpenOrders(self.ShortcontractSymbol.Symbol)
self.Shortentry_ticket = None
return
# avoids error
if self.VixcontractSymbol is None or self.ShortVixcontractSymbol is None:
return
#if orderEvent.OrderId == self.Vixentry_ticket.OrderId:
#return
# cancel the other Vix order after one gets hit
if orderEvent.Symbol == self.VixcontractSymbol.Symbol:
if orderEvent.OrderId == self.VixstopTicket.OrderId or orderEvent.OrderId == self.VixprofitTicket.OrderId:
self.Transactions.CancelOpenOrders(self.VixcontractSymbol.Symbol)
self.Vixentry_ticket = None
return
elif orderEvent.Symbol == self.ShortVixcontractSymbol.Symbol:
if orderEvent.OrderId == self.VixstopTicket.OrderId or orderEvent.OrderId == self.VixprofitTicket.OrderId:
self.Transactions.CancelOpenOrders(self.ShortVixcontractSymbol.Symbol)
self.ShortVixentry_ticket = None
return