Overall Statistics |
Total Trades 28 Average Win 2.64% Average Loss -2.01% Compounding Annual Return 21.623% Drawdown 4.500% Expectancy 0.780 Net Profit 21.604% Sharpe Ratio 1.844 Probabilistic Sharpe Ratio 79.947% Loss Rate 23% Win Rate 77% Profit-Loss Ratio 1.31 Alpha 0.023 Beta 0.632 Annual Standard Deviation 0.081 Annual Variance 0.007 Information Ratio -0.845 Tracking Error 0.058 Treynor Ratio 0.235 Total Fees $192.94 Estimated Strategy Capacity $61000000.00 Lowest Capacity Asset ES XZDYPWUWC7I9 Portfolio Turnover 3.84% |
# region imports from AlgorithmImports import * # endregion class SquareMagentaHamster(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.symbol = self.future.Symbol self.Vix = self.AddFuture(Futures.Indices.VIX, extendedMarketHours= True) self.Vix.SetFilter(0, 182) self.Vixsymbol = self.Vix.Symbol self.Longentry_ticket = None self.ESstopTicket = None self.ESprofitTicket = None self.LongcontractSymbol = None self.Esprice = None self.Vixentry_ticket = None self.VixstopTicket = None self.VixprofitTicket = None self.VixcontractSymbol = None self.VixPrice = None def OnData(self, data: Slice): if self.Longentry_ticket is None and self.Vixentry_ticket is None: self.BuyFuture(data) self.BuyVix(data) if self.Portfolio.Invested: if self.LongcontractSymbol == None or self.VixcontractSymbol == None: return 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 def BuyFuture(self, data: Slice): chain = data.FuturesChains.get(self.symbol) if chain: self.LongcontractSymbol = sorted(chain, key=lambda contract: contract.Expiry, reverse=True)[0] self.Esprice = self.Securities[self.LongcontractSymbol.Symbol].Price self.Longentry_ticket = self.LimitOrder(self.LongcontractSymbol.Symbol, 2, self.Esprice) self.ESprofitTicket = self.LimitOrder(self.LongcontractSymbol.Symbol, -2, self.Esprice*1.05) self.ESstopTicket = self.StopMarketOrder(self.LongcontractSymbol.Symbol, -2, self.Esprice*0.95) return def BuyVix(self, data: Slice): Vixchain = data.FuturesChains.get(self.Vixsymbol) if Vixchain: self.VixcontractSymbol = sorted(Vixchain, key=lambda contract: contract.Expiry, reverse=True)[0] self.VixPrice = self.Securities[self.VixcontractSymbol.Symbol].Price self.Vixentry_ticket = self.LimitOrder(self.VixcontractSymbol.Symbol, 4, self.VixPrice) self.VixprofitTicket = self.LimitOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*1.05) self.VixstopTicket = self.StopMarketOrder(self.VixcontractSymbol.Symbol, -4, self.VixPrice*0.95) 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 return if orderEvent.Status != OrderStatus.Filled: return if self.LongcontractSymbol is None: return # Otherwise, one of the exit orders was filled, so cancel the open orders if orderEvent.OrderId == self.ESprofitTicket.OrderId or orderEvent.OrderId == self.ESstopTicket.OrderId: self.Transactions.CancelOpenOrders(self.LongcontractSymbol.Symbol) self.Longentry_ticket = None return if self.VixcontractSymbol is None: return # Otherwise, one of the exit orders was filled, so cancel the open orders if orderEvent.OrderId == self.VixstopTicket.OrderId or orderEvent.OrderId == self.VixprofitTicket.OrderId: self.Transactions.CancelOpenOrders(self.VixcontractSymbol.Symbol) self.Vixentry_ticket = None return