Overall Statistics
Total Trades
80
Average Win
1.16%
Average Loss
-0.31%
Compounding Annual Return
6.450%
Drawdown
4.500%
Expectancy
2.109
Net Profit
33.878%
Sharpe Ratio
1.972
Loss Rate
35%
Win Rate
65%
Profit-Loss Ratio
3.78
Alpha
0.074
Beta
-0.527
Annual Standard Deviation
0.032
Annual Variance
0.001
Information Ratio
1.346
Tracking Error
0.032
Treynor Ratio
-0.12
Total Fees
$265.12
namespace QuantConnect.Rotation
{
    public class GlobalRotation : QCAlgorithm
    {
    	
    
        // these are the growth symbols we'll rotate through
        List<string> GrowthSymbols = new List<string>
        {
            "BSJJ", // US S&P mid cap 400
            "HYD", // iShares S&P europe 350
            "VMBS", // iShared MSCI emerging markets
            "SRLN", // iShares S&P latin america
        };

        // these are the safety symbols we go to when things are looking bad for growth
        List<string> SafetySymbols = new List<string>
        {
            "CASHX", // Vangaurd TSY 25yr+
        //    "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(25000);
            SetStartDate(2014, 1, 1);
            SetEndDate(2018, 9, 1);

            foreach (var symbol in GrowthSymbols.Union(SafetySymbols))
            {
                // ideally we would use daily data
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                var oneMonthPerformance = MOM(symbol, 21, Resolution.Daily);
                var threeMonthPerformance = MOM(symbol, 42, Resolution.Daily);

                SymbolData.Add(new SymbolData
                {
                    Symbol = symbol,
                    OneMonthPerformance = oneMonthPerformance,
                    ThreeMonthPerformance = threeMonthPerformance
                });
            }
            Schedule.On(DateRules.Every(DayOfWeek.Monday), TimeRules.At(9, 31), () =>
            {
                OnMonday();
            });
        }

		private void OnMonday()
		{
			Log("Mon at 12pm: Fired at: " + 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();
            }
        }
    }
}

    class SymbolData
    {
        public string Symbol;

        public Momentum OneMonthPerformance { get; set; }
        public Momentum ThreeMonthPerformance { get; set; }

        public decimal ObjectiveScore
        {
            get
            {
                // we weight the one month performance higher
              //  decimal weight1 = 100;
              //  decimal weight2 = 75;

             //   return (weight1 * OneMonthPerformance + weight2 * ThreeMonthPerformance) / (weight1 + weight2);
                
                                // we weight the one month performance higher
                decimal weight1 = 49;
                decimal weight2 = 51;

                return (weight1 * OneMonthPerformance + weight2 * ThreeMonthPerformance);
            }
        }
    }