Overall Statistics
Total Trades
754
Average Win
0.38%
Average Loss
-0.46%
Compounding Annual Return
-2.269%
Drawdown
17.700%
Expectancy
-0.068
Net Profit
-11.850%
Sharpe Ratio
-0.425
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
0.82
Alpha
-0.048
Beta
1.367
Annual Standard Deviation
0.05
Annual Variance
0.002
Information Ratio
-0.817
Tracking Error
0.05
Treynor Ratio
-0.015
Total Fees
$0.00
# https://quantpedia.com/Screener/Details/118


from QuantConnect.Python import PythonQuandl
import numpy as np


class TimeSeriesMomentumEffect(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2013,1, 1) 
        self.SetEndDate(2018, 7, 1)  
        self.SetCash(1000000)

        self.symbols = ["CHRIS/CME_LC1", # Live Cattle Futures, Continuous Contract #1 
                        "CHRIS/CME_LN1", # Lean Hog Futures, Continuous Contract #1 
                        
                        "CHRIS/ICE_B1", # Brent Crude Futures, Continuous Contract
                        "CHRIS/ICE_G1", # Gas Oil Futures, Continuous Contract
                        "CHRIS/ICE_CT1", # Cotton No. 2 Futures, Continuous Contract
                        "CHRIS/ICE_KC1", # Coffee C Futures, Continuous Contract
                        "CHRIS/ICE_CC1", # Cocoa Futures, Continuous Contract 
                        "CHRIS/ICE_SB1", # Sugar No. 11 Futures, Continuous Contract
                        
                        "CHRIS/CME_C1", #Corn Futures, Continuous Contract #1 (C1) (Front Month)
                         "CHRIS/CME_S1", #Soybean Futures, Continuous Contract #1 (S1) (Front Month)
                         "CHRIS/CME_SM1", #Soybean Meal Futures, Continuous Contract #1 (SM1) (Front Month)
                         "CHRIS/CME_BO1", #Soybean Oil Futures, Continuous Contract #1 (BO1) (Front Month)
                         "CHRIS/CME_W1", #Wheat Futures, Continuous Contract #1 (W1) (Front Month)
                            ]   
                                
    

        
        period = 252
        self.roc = {}

        
        for symbol in self.symbols:
            self.AddData(QuandlFutures, symbol, Resolution.Daily)
            self.roc[symbol] = self.ROC(symbol, period)
            # hist = self.History([symbol], 300, Resolution.Daily).loc[symbol]
            # for i in hist.itertuples():
            #     self.roc[symbol].Update(i.Index, i.settle)
            self.RegisterIndicator(symbol, self.roc[symbol], Resolution.Daily)
        self.SetWarmup(period)
        
        
        # Rebalance the portfolio every month
        self.Schedule.On(self.DateRules.MonthStart("CHRIS/CME_S1"), self.TimeRules.AfterMarketOpen("CHRIS/CME_S1"), self.Rebalance)
               

    def OnData(self, data):
        # Update the indicator value every day
        # for symbol in self.symbols:
        #     if data.ContainsKey(symbol) and self.roc[symbol].IsReady:
        #         self.roc[symbol].Update(self.Time, data[symbol].Value)
        pass

    def Rebalance(self): 
        #choose contracts with positive momentum to long
        long_symbols = [symbol for symbol in self.roc if self.roc[symbol].Current.Value >= 0]
        #choose contracts with negative momentum to short
        short_symbols =  [symbol for symbol in self.roc if self.roc[symbol].Current.Value < 0]
        
        self.Liquidate()
        

        weights_long = {}   #contracts' weights for long
        weights_short = {}  #contracts' weights for short
        volatility = {}     #estimated volatility
        try:
            for symbol in self.symbols:
                hist = self.History(self.Symbol(symbol), 252, Resolution.Daily).loc[symbol]['value']
                log_return = np.log((hist/hist.shift()).dropna().tolist())
                volatility[symbol] = 1/np.std(log_return,ddof = 1) 
            
                #calculate the historical volatility and get its reciprocal because the weight is inversely proportional to its volatility
            
            
            for long_symbol in long_symbols:
                weights_long[long_symbol] = volatility[long_symbol]/sum(volatility.values())   #normalize the weights, making sure the sum is 1
            for short_symbol in short_symbols:
                weights_short[short_symbol] = volatility[short_symbol]/sum(volatility.values()) #normalize the weights, making sure the sum is 1
            
            #SetHoldings to trade
            for short_symbol in short_symbols:
                self.SetHoldings(short_symbol, -0.5*weights_short[short_symbol]/sum(weights_short.values()))
            for long_symbol in long_symbols:
                self.SetHoldings(long_symbol, 0.5*weights_long[long_symbol]/sum(weights_long.values())) 
        except:
            pass


class QuandlFutures(PythonQuandl):
    
    def __init__(self):
        self.ValueColumnName = "Settle"  
    #set the column name of value to "Settle", becasue the column name of desired data from Quandl is "Settle".