Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
0.916%
Drawdown
2.300%
Expectancy
0
Net Profit
0.916%
Sharpe Ratio
0.371
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
-0.01
Beta
0.99
Annual Standard Deviation
0.024
Annual Variance
0.001
Information Ratio
-0.416
Tracking Error
0.024
Treynor Ratio
0.009
Total Fees
$2.44
namespace QuantConnect.Rotation
{
    public class GlobalRotation : QCAlgorithm
    {
    	
    	/* Should we include Money market fund in rotation for growth? If money market
    	has highest momentum it would rotate into it?*/
    	
        // 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
            "SRLN", // iShares S&P latin america
            "VMBS", // 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
       
        public override void Initialize()
        {
        	
       		List<string> allSymbols = GrowthSymbols.Union(SafetySymbols).ToList();
        	Dictionary<string, SymbolData> allSymbolData = new Dictionary<string, SymbolData>();

        	SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
        //	Portfolio.MarginCallModel = MarginCallModel.Null;
        	double leverage = 1.0;
            SetCash(25000);
            SetStartDate(2018, 1, 1);
            SetEndDate(2019, 1, 1);

            foreach (var symbol in allSymbols) {
    AddSecurity(SecurityType.Equity, symbol, Resolution.Daily);
    var oneMonthPerformance = MOMP(symbol, 21, Resolution.Daily);
    var threeMonthPerformance = MOMP(symbol, 42, Resolution.Daily);

    allSymbolData.Add(symbol, new SymbolData
    {
        Symbol = symbol,
        oneMonthPerformanceMOMP = oneMonthPerformance,
        threeMonthPerformanceMOMP = threeMonthPerformance
    });
}
            	
            	Schedule.On(DateRules.Every(DayOfWeek.Monday), TimeRules.At(9, 29), () =>
            {
                
IEnumerable<SymbolData> oneMonthOrderedByMOMP = 
  allSymbolData
            .OrderByDescending(x => x.Value.oneMonthPerformanceMOMP)
            .Select(x => x.Value)
            .AsEnumerable();
            

// assign it's one month rank to the original object in allSymbolData
int oneMonthCounter = 0;
foreach(var item in oneMonthOrderedByMOMP) {
  oneMonthCounter++;
  allSymbolData[item.Symbol].oneMonthRank = oneMonthCounter;
};


// get the order based on three month
IEnumerable<SymbolData> threeMonthOrderedByMOMP = 
  allSymbolData
            .OrderByDescending(x => x.Value.threeMonthPerformanceMOMP)
            .Select(x => x.Value)
            .AsEnumerable();

// assign it's three month rank to the original object in allSymbolData
int threeMonthCounter = 0;
foreach(var item in threeMonthOrderedByMOMP) {
  threeMonthCounter++;
  allSymbolData[item.Symbol].threeMonthRank = threeMonthCounter;
};

// get the new order based on the allSymbolData object's with their shiny new one/threemonth calculated score
Dictionary<string, SymbolData> orderedSymbols = allSymbolData.OrderByDescending(x => x.Value.calculateTotalScore()).ToDictionary();
// bank
var bestGrowth = orderedSymbols.First().Value;

                    if (bestGrowth.calculateTotalScore() > 0)
                    {
                        if (Portfolio[bestGrowth.Symbol].Quantity == 0)
                        {
                            Log("PREBUY>>LIQUIDATE>>");
                            Liquidate();
                        }
                        Log(">>BUY>>" + bestGrowth.Symbol + "@" + (100 * bestGrowth.calculateOneMonthPerformance()).ToString("00.00"));
                        SetHoldings(bestGrowth.Symbol, leverage);
                    }
                    else
                    {
                        // if no one has a good objective score then let's hold cash this month to be safe
                        Log(">>LIQUIDATE>>CASH");
                        Liquidate();
                    }
            });
            
        }

        public void OnData(TradeBars data)
        {
            	
        }
            

	} 

  class SymbolData {
  	
  public string Symbol = "";
  public decimal oneMonthWeight = 51;
  public decimal threeMonthWeight = 49;
  
  public decimal oneMonthPerformanceMOMP = 0.0M;
  public decimal threeMonthPerformanceMOMP = 0.0M;

  public int oneMonthRank = 0;
  public int threeMonthRank = 0;

  public decimal calculateOneMonthPerformance() {
    return (oneMonthWeight * oneMonthRank / oneMonthWeight);
  }

  public decimal calculateThreeMonthPerformance() {
    return (threeMonthWeight * threeMonthRank / threeMonthWeight);
  }

  public decimal calculateTotalScore() {
    return calculateOneMonthPerformance() + calculateThreeMonthPerformance();
  }
}
	
}