Overall Statistics
Total Trades
1651
Average Win
0.21%
Average Loss
-0.21%
Compounding Annual Return
-0.903%
Drawdown
12.000%
Expectancy
-0.026
Net Profit
-5.301%
Sharpe Ratio
-0.149
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.01
Alpha
0.042
Beta
-2.547
Annual Standard Deviation
0.051
Annual Variance
0.003
Information Ratio
-0.532
Tracking Error
0.051
Treynor Ratio
0.003
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(2019, 1, 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.rocr = {}
        for symbol in self.symbols:
            self.AddData(QuandlFutures, symbol, Resolution.Daily)
            self.rocr[symbol] = self.ROCR(symbol, period)   #Initialize ROCR indicator : ROCR is short for RateofChangeRatio
            
        self.SetWarmup(period)
        self.Schedule.On(self.DateRules.MonthStart("CHRIS/CME_S1"), self.TimeRules.AfterMarketOpen("CHRIS/CME_S1"), self.Rebalance)  # Rebalance the portfolio every month
               

    


    def Rebalance(self): 
        long_symbols = [symbol for symbol in self.rocr if self.rocr[symbol].Current.Value >= 0]      #choose contracts with positive momentum to long
        short_symbols =  [symbol for symbol in self.rocr if self.rocr[symbol].Current.Value < 0]     #choose contracts with negative momentum to short
        self.Liquidate()
        
        weights_long = {}               #contracts' weights for long
        weights_short = {}              #contracts' weights for short
        volatility_reciprocal = {}      #estimated volatility by manual calculations(numpy)

        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())          #calculate log returns of each futures
            volatility_reciprocal[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

      
        try:     #use try-except here because sometimes it casuses OverflowException 
            for long_symbol in long_symbols:
                weights_long[long_symbol] = volatility_reciprocal[long_symbol]/sum(volatility_reciprocal.values())   #normalize the weights, making sure the sum is 1
            for short_symbol in short_symbols:
                weights_short[short_symbol] = volatility_reciprocal[short_symbol]/sum(volatility_reciprocal.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".