Overall Statistics |
Total Trades 9997 Average Win 0.00% Average Loss -0.01% Compounding Annual Return -100% Drawdown 24.200% Expectancy -0.906 Net Profit -24.189% Sharpe Ratio -11.754 Loss Rate 93% Win Rate 7% Profit-Loss Ratio 0.37 Alpha 0 Beta -2283.267 Annual Standard Deviation 1.787 Annual Variance 3.194 Information Ratio -11.757 Tracking Error 1.787 Treynor Ratio 0.009 Total Fees $18827.45 |
from datetime import timedelta class BasicTemplateFuturesAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 1) self.SetEndDate(2017, 1, 10) self.SetCash(1000000) # Subscribe and set our expiry filter for the futures chain futureES = self.AddFuture(Futures.Indices.SP500EMini) futureES.SetFilter(timedelta(0), timedelta(90)) futureNQ = self.AddFuture(Futures.Indices.NASDAQ100EMini) futureNQ.SetFilter(timedelta(0), timedelta(90)) self.frontES = None self.frontNQ = None def OnData(self,slice): for chain in slice.FutureChains: # Get contracts expiring no earlier than in 10 days -- if you want 90 days, then expand the filter in Initialize() # to more than 90 days out or else using self.Time + timedelta(90) in the lamba below won't return anything contracts = list(filter(lambda x: x.Expiry > self.Time + timedelta(10), chain.Value)) for contract in contracts: ## If it's an SP500 EMini, the contract will have the prefix 'ES'. I use the extra space in 'ES ' because ## the contract symbol will have a blank space between the prefix and the rest of the contract symbol, ## and using the ' ' will keep from accidentally including a NASDAQ contract that might contain 'ES' in the ## second part of its ticker. if ('ES ' in str(contract.Symbol)) and (self.frontES is None): self.frontES = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0] ## 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.Expiry, reverse=True)[0] ## 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: self.SetHoldings(self.frontES.Symbol , 0.2) self.SetHoldings(self.frontNQ.Symbol , -0.2) else: self.Liquidate() ## Word of caution: since self.frontES and self.frontNQ are never reset to 'None', this strategy will buy and then liquidate ## the same two contracts every minute during the entire testing period. Consider adding either time or position controls ## to help limit unnecessary/unwanted trading def OnOrderEvent(self, orderEvent): self.Log(str(orderEvent))