Overall Statistics |
Total Trades 116 Average Win 4.48% Average Loss -4.21% Compounding Annual Return -18.568% Drawdown 56.500% Expectancy -0.266 Net Profit -46.086% Sharpe Ratio -0.059 Probabilistic Sharpe Ratio 1.360% Loss Rate 64% Win Rate 36% Profit-Loss Ratio 1.06 Alpha -0.025 Beta -0.039 Annual Standard Deviation 0.476 Annual Variance 0.227 Information Ratio -0.227 Tracking Error 0.488 Treynor Ratio 0.715 Total Fees $335.92 Estimated Strategy Capacity $72000.00 Lowest Capacity Asset CSC WQWXTW2FXGJL |
#region imports from AlgorithmImports import * #endregion class CommidityMomentumEffect(QCAlgorithm): def Initialize(self): self.SetStartDate(2015,1, 1) self.SetEndDate(2018, 1, 1) self.SetCash(100000) self.symbols = [ Futures.Dairy.CashSettledButter, Futures.Dairy.CashSettledCheese, Futures.Dairy.ClassIIIMilk, Futures.Dairy.DryWhey, Futures.Dairy.ClassIVMilk, Futures.Dairy.NonfatDryMilk, Futures.Meats.LiveCattle, Futures.Meats.FeederCattle, Futures.Meats.LeanHogs, Futures.Forestry.RandomLengthLumber ] period = 252 self.data = {} for symbol in self.symbols: future = self.AddFuture(symbol, resolution = Resolution.Daily, extendedMarketHours = True, dataNormalizationMode = DataNormalizationMode.BackwardsRatio, dataMappingMode = DataMappingMode.OpenInterest, contractDepthOffset = 0 ) future.SetLeverage(1) self.data[future.Symbol] = SymbolData(self, future, period) # Rebalance the portfolio every month self.rebalance = self.Time def OnData(self, slice): # Update the indicator value every day for symbol, symbol_data in self.data.items(): if slice.Bars.ContainsKey(symbol): symbol_data.Update(slice.Bars[symbol]) if self.rebalance <= self.Time: # sorted futures by 12-month return reversely self.sorted_roc = sorted([x for x in self.data.values() if x.IsReady], key = lambda x: x.Value, reverse=True) number_futures = int(0.25*len(self.sorted_roc)) if number_futures == 0: return self.long = [x for x in self.sorted_roc[:number_futures]] self.short = [x for x in self.sorted_roc[-number_futures:]] for symbol in self.Portfolio.Keys: # liquidate the futures which is no longer in the trading list if self.Portfolio[symbol].Invested and symbol not in [x.Mapped for x in self.long + self.short]: self.Liquidate(symbol) for long in self.long: qty = self.CalculateOrderQuantity(long.Mapped, 0.5/number_futures) self.MarketOrder(long.Mapped, qty // long.Multiplier) for short in self.short: qty = self.CalculateOrderQuantity(short.Mapped, -0.5/number_futures) self.MarketOrder(short.Mapped, qty // short.Multiplier) self.rebalance = Expiry.EndOfMonth(self.Time) class SymbolData: def __init__(self, algorithm, future, period): self._future = future self.Symbol = future.Symbol self.ROC = RateOfChange(period) # warm up indicator algorithm.WarmUpIndicator(self.Symbol, self.ROC, Resolution.Daily) @property def IsReady(self): return self.ROC.IsReady and self._future.Mapped is not None @property def Value(self): return self.ROC.Current.Value @property def Mapped(self): return self._future.Mapped @property def Multiplier(self): return self._future.SymbolProperties.ContractMultiplier def Update(self, bar): self.ROC.Update(bar.EndTime, bar.Close)