Overall Statistics
Total Trades
248
Average Win
0.14%
Average Loss
-0.19%
Compounding Annual Return
-86.052%
Drawdown
12.500%
Expectancy
-0.565
Net Profit
-12.484%
Sharpe Ratio
-7.719
Probabilistic Sharpe Ratio
0%
Loss Rate
75%
Win Rate
25%
Profit-Loss Ratio
0.74
Alpha
-0.471
Beta
-0.278
Annual Standard Deviation
0.095
Annual Variance
0.009
Information Ratio
-10.794
Tracking Error
0.154
Treynor Ratio
2.63
Total Fees
$1239.50
Estimated Strategy Capacity
$340000.00
Lowest Capacity Asset
GC VL5E74HP3EE5
class UncoupledVentralPrism(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2013, 10, 8)
        self.SetEndDate(2013, 11, 1)
        #self.SetEndDate(2017, 5, 19)
        self.SetCash(100000)

        self.tickers = ['ZW', 
                        'ZN',
                        'CL',
                        'GC'] 
        self.future_data_by_future = {}
        for ticker in self.tickers:
            future = self.AddFuture(ticker)
            future.SetFilter(lambda x: x.FrontMonth().OnlyApplyFilterAtMarketOpen())
            self.future_data_by_future[future.Symbol.ID.Symbol] = FutureData()

    def OnData(self, data):
        
        for future, future_data in self.future_data_by_future.items():
            
            if not data.ContainsKey(future_data.symbol):
                continue
            
            holding = None if future_data.symbol is None else self.Portfolio.get(future_data.symbol)
            if holding is not None:
                
                # Buy the futures' front contract when the fast EMA is above the slow one
                if future_data.fast.Current.Value > future_data.slow.Current.Value:
                    if not holding.Invested:
                        self.SetHoldings(future_data.symbol, .1)
                elif holding.Invested:
                    self.Liquidate(future_data.symbol)


    def OnSecuritiesChanged(self, changes):
        for security in changes.RemovedSecurities:
            # Remove the consolidator for the previous contract
            # and reset the indicators
            future_data = self.future_data_by_future[security.Symbol.ID.Symbol]
            if future_data.symbol is not None and future_data.consolidator is not None:
                future_data.reset(self)
                
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            self.future_data_by_future[symbol.ID.Symbol].setup(symbol, self)
        
        
class FutureData:
    symbol = None
    consolidator = None
    fast = ExponentialMovingAverage(10)
    slow = ExponentialMovingAverage(50)
    
    def setup(self, symbol, algorithm):
        
        # Only one security will be added: the new front contract
        self.symbol = symbol
        
        # Create a new consolidator and register the indicators to it
        self.consolidator = algorithm.ResolveConsolidator(symbol, Resolution.Minute)
        algorithm.RegisterIndicator(symbol, self.fast, self.consolidator)
        algorithm.RegisterIndicator(symbol, self.slow, self.consolidator)
        
        #  Warm up the indicators
        algorithm.WarmUpIndicator(symbol, self.fast, Resolution.Minute)
        algorithm.WarmUpIndicator(symbol, self.slow, Resolution.Minute)
        
    
    def reset(self, algorithm):
        algorithm.SubscriptionManager.RemoveConsolidator(self.symbol, self.consolidator)
        self.symbol = None
        self.consolidator = None
        self.fast.Reset()
        self.slow.Reset()
        
        # We don't need to call Liquidate(_symbol),
        # since its positions are liquidated because the contract has expired.