Overall Statistics
Total Trades
246
Average Win
0.93%
Average Loss
-1.00%
Compounding Annual Return
7.906%
Drawdown
17.300%
Expectancy
0.346
Net Profit
70.364%
Sharpe Ratio
0.65
Loss Rate
30%
Win Rate
70%
Profit-Loss Ratio
0.93
Alpha
-0.001
Beta
0.648
Annual Standard Deviation
0.129
Annual Variance
0.017
Information Ratio
-0.479
Tracking Error
0.098
Treynor Ratio
0.13
Total Fees
$247.43
public class FaberMonthlySectorRotation : QCAlgorithm
{
    #region Properties
    bool extraCharting = false;
    bool webIde = true;
    int currentMonth = -1;
    DateTime lastProcessedDate = DateTime.MinValue;

    private Symbol spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
    private Symbol dummy = QuantConnect.Symbol.Create("IBM", SecurityType.Equity, Market.USA);
    SimpleMovingAverage spySma = null;

    //QuantConnect.ToolBox.exe "XLI,XLB,XLE,XLV,XLP,XLU,XLF,XLY,XLK,SPY" Daily 19980101 20161231
    List<string> SectorEtfSymbols = new List<string> { "XLI", "XLB", "XLE", "XLV", "XLP", "XLU", "XLF", "XLY", "XLK" };
    List<SymbolData> SectorEtfs = new List<SymbolData>(); 
    #endregion

    #region Initialize
    public override void Initialize()
    {
        SetCash(10000);
        SetStartDate(2010, 1, 1);
        SetEndDate(2016, 12, 31);

        if (webIde) AddEquity(dummy.ID.Symbol, Resolution.Minute);
        AddEquity(spy.ID.Symbol, Resolution.Minute);
        spySma = SMA(spy, 200, Resolution.Daily);

        var history = History(spy, 201, Resolution.Daily);

        foreach (TradeBar tradeBar in history)
        {
            spySma.Update(tradeBar.EndTime, tradeBar.Close);
        }

        SetBenchmark(spy);

        foreach (var sym in SectorEtfSymbols)
        {
            //Symbol symbol = QuantConnect.Symbol.Create(sym, SecurityType.Equity, Market.USA);

            AddSecurity(SecurityType.Equity, sym, Resolution.Minute);
            var threeMonthPerformance = MOM(sym, 60, Resolution.Daily);

            history = History(sym, 61, Resolution.Daily);

            foreach (TradeBar tradeBar in history)
            {
                threeMonthPerformance.Update(tradeBar.EndTime, tradeBar.Close);
            }

            SectorEtfs.Add(new SymbolData
            {
                Symbol = sym,
                ThreeMonthPerformance = threeMonthPerformance
            });
        }

        Schedule.On(DateRules.EveryDay("SPY"), TimeRules.AfterMarketOpen(spy, 1), () =>
        {
            Allocate();
        });

        #region Charting
        if (extraCharting)
        {
            Chart stockPlot = new Chart("SPY");

            Series spyPriceSeries = new Series("Price", SeriesType.Line, 0);
            stockPlot.AddSeries(spyPriceSeries);

            Series spySmaSeries = new Series("SMA", SeriesType.Line, 0);
            stockPlot.AddSeries(spySmaSeries);

            Series buyingAllowedSeries = new Series("Buying Allowed", SeriesType.Line, 1);
            stockPlot.AddSeries(buyingAllowedSeries);

            AddChart(stockPlot);
        }
        #endregion
    } 
    #endregion

    public void Allocate()
    {
        //TradeBar spyBar = data[spy];

        //if (extraCharting)
        //{
        //    Plot("SPY", "Price", data[spy].Close);
        //    Plot("SPY", "SMA", spySma);
        //    Plot("SPY", "Buying Allowed", data[spy].Close > spySma ? 1 : -1);
        //}

        if (currentMonth != Time.Month)
        {
        	Log(String.Format("Allocate: {0}", Time.ToShortDateString()));
        	
            TradeBar spyLast = History(spy, 1, Resolution.Daily).Last();

            currentMonth = Time.Month;

            if (spyLast.Close > spySma)
            {
                List<String> topPerformers = this.SectorEtfs.OrderByDescending(x => x.ThreeMonthPerformance).Select(x => x.Symbol).Take(3).ToList();

                foreach (Symbol x in Portfolio.Keys)
                {
                    if (Portfolio[x].Invested && !topPerformers.Contains(x))
                    {
                        Liquidate(x);
                    }
                }

                foreach (String x in topPerformers)
                {
                    SetHoldings(x, .333);
                }
            }
            else
            {
                Liquidate();
            }
        }
    }

    #region OnData
    public void OnData(TradeBars data)
    {
        //if (data.ContainsKey(dummy)) RemoveSecurity(dummy);
    }
    #endregion

    #region InitPerformanceChart
    public void InitPerformanceChart()
    {
        Chart chart = new Chart("Performance");

        Series spySeries = new Series("SPY", SeriesType.Line, 0);
        chart.AddSeries(spySeries);

        Series portfolioSeries = new Series("Portfolio", SeriesType.Line, 0);
        chart.AddSeries(portfolioSeries);

        Series exposure = new Series("Exposure", SeriesType.Line, 1);
        chart.AddSeries(exposure);

        AddChart(chart);
    }
    #endregion

    #region PlotPerformanceChart
    public void PlotPerformanceChart(TradeBar spyBar)
    {
        Plot("Performance", "SPY", spyBar.Close);
    }
    #endregion
}

class SymbolData
{
    public String Symbol;
    public Momentum ThreeMonthPerformance { get; set; }
}