namespace QuantConnect
{
public class FaberMonthlySectorRotation : QCAlgorithm
{
DateTime LastRotationTime = new DateTime(1980, 1, 1);
DateTime GoLiveDate = new DateTime(2005, 1, 1);
TimeSpan RotationInterval = TimeSpan.FromDays(30);
private Symbol spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);
SimpleMovingAverage spySma = null;
List<string> SectorEtfSymbols = new List<string>{ "XLI", "XLB", "XLE", "XLV", "XLP", "XLU", "XLF", "XLY", "XLK" };
List<SymbolData> SectorEtfs = new List<SymbolData>();
public override void Initialize()
{
SetCash(10000);
SetStartDate(2004, 1, 1);
SetEndDate(2016, 12, 31);
AddEquity(spy.ID.Symbol, Resolution.Daily);
spySma = SMA(spy, 300, Resolution.Daily);
foreach (var sym in SectorEtfSymbols)
{
Symbol symbol = QuantConnect.Symbol.Create(sym, SecurityType.Equity, Market.USA);
AddSecurity(SecurityType.Equity, sym, Resolution.Daily);
var threeMonthPerformance = MOM(symbol, 90, Resolution.Daily);
SectorEtfs.Add(new SymbolData
{
Symbol = symbol,
ThreeMonthPerformance = threeMonthPerformance
});
}
#region Charting
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
}
public void OnData(TradeBars data)
{
if (Time.Date >= GoLiveDate)
{
TradeBar spyBar = data[spy];
//Plot("SPY", "Price", data[spy].Close);
//Plot("SPY", "SMA", spySma);
//Plot("SPY", "Buying Allowed", data[spy].Close > spySma ? 1 : -1);
var delta = Time.Subtract(LastRotationTime);
if (delta > RotationInterval)
{
LastRotationTime = Time;
if (data[spy].Close > spySma)
{
List<Symbol> 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(Symbol x in topPerformers)
{
SetHoldings(x, .333);
}
}
else
{
Liquidate();
}
}
}
}
}
class SymbolData
{
public Symbol Symbol;
public Momentum ThreeMonthPerformance { get; set; }
}
}