Overall Statistics |
Total Trades 396 Average Win 25.18% Average Loss -8.71% Compounding Annual Return -51.829% Drawdown 60.200% Expectancy 0.749 Net Profit -51.800% Sharpe Ratio -0.749 Loss Rate 55% Win Rate 45% Profit-Loss Ratio 2.89 Alpha -1.131 Beta 44.784 Annual Standard Deviation 0.562 Annual Variance 0.316 Information Ratio -0.777 Tracking Error 0.562 Treynor Ratio -0.009 Total Fees $732.60 |
from datetime import timedelta import decimal class BasicTemplateFuturesAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 6, 15) self.SetEndDate(2019, 6, 15) self.SetCash(25000) slowperiod = 1720 self.SetWarmUp(slowperiod) futureES = self.AddFuture(Futures.Indices.SP500EMini) futureES.SetFilter(timedelta(0), timedelta(182)) futureNQ = self.AddFuture(Futures.Indices.NASDAQ100EMini) futureNQ.SetFilter(timedelta(0), timedelta(182)) self.frontES = None self.frontNQ = None #Add the spread plot and mark the long/short spread point spreadPlot = Chart("Spread Plot") spreadPlot.AddSeries(Series("currentspread", SeriesType.Line, 0)) spreadPlot.AddSeries(Series("Long Spread Trade", SeriesType.Scatter, 0)) spreadPlot.AddSeries(Series("Short Spread Trade", SeriesType.Scatter, 0)) spreadPlot.AddSeries(Series("ESNQ SMA", SeriesType.Line, 0)) self.AddChart(spreadPlot) def OnData(self,slice): if (self.frontES is not None) and (self.Time > self.frontES.Expiry): self.frontES = None if (self.frontNQ is not None) and (self.Time > self.frontNQ.Expiry): self.frontNQ = None for chain in slice.FutureChains: contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(45), chain.Value)) for contract in contracts: if ('ES ' in str(contract.Symbol)) and (self.frontES is None): self.frontES = sorted(contracts, key=lambda x: x.OpenInterest, reverse=False)[0] #True is lowest to highest self.Consolidate(contract.Symbol, timedelta(minutes=240), self.twoforty) self.essma = self.SMA(self.frontES.Symbol, 400, Resolution.Minute) ## Same as above but for NASDAQ -- Also, be sure to wrap the Symbol object in str() when comparing it to a character string or else ## the comparison will fail since they won't be of the same type if ('NQ ' in str(contract.Symbol)) and (self.frontNQ is None): self.frontNQ = sorted(contracts, key=lambda x: x.OpenInterest, reverse=False)[0]#True is lowest to highest self.nqsma = self.SMA(self.frontNQ.Symbol, 400, Resolution.Minute) self.esnqsma = IndicatorExtensions.Minus(self.nqsma, self.essma) def OnOrderEvent(self, orderEvent): #self.Log(str(orderEvent)) pass def twoforty(self, consolidated): ''' This is our event handler for our 45 minute consolidated defined using the Consolidate method''' self.consolidated45Minute = True #self.Log(f"{consolidated.EndTime} >> twoforty >> {consolidated.Close}") currentspread = (self.Securities[self.frontNQ.Symbol].Price - self.Securities[self.frontES.Symbol].Price) tolerance = decimal.Decimal(18.25) ## Check to make sure both self.frontES and self.frontNQ are contracts that can be traded if (self.frontES is not None) and (self.frontNQ is not None): if not self.Portfolio.Invested and currentspread <= (self.esnqsma.Current.Value - tolerance): self.MarketOrder(self.frontES.Symbol , -1) self.MarketOrder(self.frontNQ.Symbol , 1) self.Plot("Spread Plot", "Long Spread Trade", currentspread) #self.Log("We are Long, Total Margin Used is: " + str(self.Portfolio.TotalAbsoluteHoldingsCost)) #self.Log("currentspread is less than esnq tolerance: " + str(currentspread) + " < " + str(self.esnqsma.Current.Value - tolerance)) #self.Log("What contracts are available??" + str(self.frontES) + " and " + str(self.frontNQ)) self.Notify.Sms("+test", "LONG, Paper Forex"); if not self.Portfolio.Invested and currentspread >= (self.esnqsma.Current.Value + tolerance): self.MarketOrder(self.frontES.Symbol , 1) self.MarketOrder(self.frontNQ.Symbol , -1) self.Notify.Sms("+test", "Liquidate, Paper Forex"); self.Plot("Spread Plot", "Short Spread Trade", currentspread) #self.Log("We are Short, Total Margin Used is: " + str(self.Portfolio.TotalAbsoluteHoldingsCost)) #self.Log("currentspread is greater than esnq tolerance: " + str(currentspread) + " > " + str(self.esnqsma.Current.Value + tolerance)) #self.Log("Did we purchase any contracts??" + str(self.frontES.Symbol) + " and " + str(self.frontNQ.Symbol)) if self.Portfolio.Invested: if (self.esnqsma.Current.Value + 2.00) >= currentspread >= (self.esnqsma.Current.Value - 2.00): self.Liquidate() self.Plot("Spread Plot", "ESNQ SMA", self.esnqsma.Current.Value) self.Plot("Spread Plot", "currentspread", currentspread) def OnEndOfDay(self): #self.Log("Settled Cash is: " + str(self.Portfolio.Cash)) #self.Log("Total Margin Used is: " + str(self.Portfolio.TotalAbsoluteHoldingsCost)) #self.Log("Total Units held is: " + str(self.Portfolio.TotalHoldingsValue)) morning = "05:00:00.000000" afternoon = "11:30:00.000000" time = str(self.Time) #if not morning < time < afternoon: # self.Log(str((datetime.now().time()))) pass