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".