Overall Statistics
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))