Overall Statistics |
Total Trades 82 Average Win 9.96% Average Loss -4.59% Compounding Annual Return -1.040% Drawdown 54.400% Expectancy -0.049 Net Profit -10.245% Sharpe Ratio 0.048 Loss Rate 70% Win Rate 30% Profit-Loss Ratio 2.17 Alpha 0.008 Beta 0.024 Annual Standard Deviation 0.187 Annual Variance 0.035 Information Ratio -0.19 Tracking Error 0.259 Treynor Ratio 0.375 Total Fees $84.44 |
namespace QuantConnect.Rotation { public class GlobalRotation : QCAlgorithm { // we'll use this to tell us when the month has ended DateTime LastRotationTime = DateTime.MinValue; TimeSpan RotationInterval = TimeSpan.FromDays(30); // these are the growth symbols we'll rotate through List<string> GrowthSymbols = new List<string> { "MDY", // US S&P mid cap 400 "EWJ", // Japan "IEV", // iShares S&P europe 350 "EEM", // iShared MSCI emerging markets "ILF", // iShares S&P latin america "EPP", // iShared MSCI Pacific ex-Japan "IYR", // US REIT "RWX", // International REIT "EDV", // Vangaurd TSY 25yr+ "IEF", // Intermediate Treasury "DBC", // Commodities "GLD" // Gold }; // these are the safety symbols we go to when things are looking bad for growth List<string> SafetySymbols = new List<string> { "SHY" // Barclays Low Duration TSY }; // we'll hold some computed data in these guys List<SymbolData> SymbolData = new List<SymbolData>(); public override void Initialize() { SetCash(10000); SetStartDate(2007, 1, 1); SetEndDate(2017, 5, 1); foreach (var symbol in GrowthSymbols.Union(SafetySymbols)) { // ideally we would use daily data AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); var oneMonthPerformance = MOM(symbol, 30, Resolution.Daily); var threeMonthPerformance = MOM(symbol, 90, Resolution.Daily); var sixMonthPerformance = MOM(symbol, 180, Resolution.Daily); var twelveMonthPerformance = MOM(symbol, 360, Resolution.Daily); SymbolData.Add(new SymbolData { Symbol = symbol, OneMonthPerformance = oneMonthPerformance, ThreeMonthPerformance = threeMonthPerformance, SixMonthPerformance = sixMonthPerformance, TwelveMonthPerformance = twelveMonthPerformance }); } } private bool first = true; public void OnData(TradeBars data) { try { // the first time we come through here we'll need to do some things such as allocation // and initializing our symbol data if (first) { first = false; LastRotationTime = data.Time; return; } var delta = Time.Subtract(LastRotationTime); if (delta > RotationInterval) { LastRotationTime = data.Time; // pick which one is best from growth and safety symbols var orderedObjScores = SymbolData.OrderByDescending(x => x.ObjectiveScore).ToList(); foreach (var orderedObjScore in orderedObjScores) { Log(">>SCORE>>" + orderedObjScore.Symbol + ">>" + orderedObjScore.ObjectiveScore); } var bestGrowth = orderedObjScores.First(); if (bestGrowth.ObjectiveScore > 0) { if (Portfolio[bestGrowth.Symbol].Quantity == 0) { Log("PREBUY>>LIQUIDATE>>"); Liquidate(); } Log(">>BUY>>" + bestGrowth.Symbol + "@" + (100 * bestGrowth.OneMonthPerformance).ToString("00.00")); SetHoldings(bestGrowth.Symbol, 1.0); } else { // if no one has a good objective score then let's hold cash this month to be safe Log(">>LIQUIDATE>>CASH"); Liquidate(); } } } catch (Exception ex) { Error("OnTradeBar: " + ex.Message + "\r\n\r\n" + ex.StackTrace); } } } class SymbolData { public string Symbol; public Momentum OneMonthPerformance { get; set; } public Momentum ThreeMonthPerformance { get; set; } public Momentum SixMonthPerformance { get; set; } public Momentum TwelveMonthPerformance { get; set; } public decimal ObjectiveScore { get { // we weight the one month performance higher decimal weight1 = 100; decimal weight2 = 100; decimal weight3 = 100; decimal weight4 = 100; return (weight1 * OneMonthPerformance + weight2 * ThreeMonthPerformance + weight3 * SixMonthPerformance + weight4 * TwelveMonthPerformance) / (weight1 + weight2 + weight3 + weight4); } } } }