Overall Statistics
Total Trades
593
Average Win
0.72%
Average Loss
-0.7%
Compounding Annual Return
6.903%
Drawdown
18.800%
Expectancy
0.285
Net Profit
211.264%
Sharpe Ratio
0.705
Loss Rate
37%
Win Rate
63%
Profit-Loss Ratio
1.03
Alpha
0.048
Beta
0.294
Annual Standard Deviation
0.102
Annual Variance
0.01
Information Ratio
-0.064
Tracking Error
0.166
Treynor Ratio
0.245
Total Fees
$1315.83
namespace QuantConnect 
{   
    /*
    *   QuantConnect University: Futures Example
    *
    *   QuantConnect allows importing generic data sources! This example demonstrates importing a futures
    *   data from the popular open data source Quandl.
    *
    *   QuantConnect has a special deal with Quandl giving you access to Stevens Continuous Futurs (SCF) for free. 
    *   If you'd like to download SCF for local backtesting, you can download it through Quandl.com.
    */
    public class DualMomentumSectorRotation : QCAlgorithm
    {
        // we'll use this to tell us when the month has ended
        DateTime LastRotationTime = DateTime.MinValue;
        TimeSpan RotationInterval = TimeSpan.FromDays(30);
        
       
        
        List<string> GEMSymbols = new List<string>
        {
            "SPY",
            "BIL",
            "AGG"
        };
        
        // these are the growth symbols we'll rotate through
        List<string> SectorSymbols = new List<string>
        {
            "XLV", //healthcare
            "XLK", //technology
            "XLI", //industrial
            "XLU", //utilities
            "XLF", //financials
            "XLY", //consumerdisc
            "XLP", //consumerstap
            "XLB", //basic materials
            "XLE", // energy
            "PSR", //real estate
            "IYZ" // communications
        };
        
        // we'll hold some computed data in these guys
        List<SymbolData> SectorSymbolData = new List<SymbolData>();
        Dictionary<string, SymbolData> GEMSymbolData = new Dictionary<string, SymbolData>();
        List<string> strongSectors = new List<string>();
        
        // Indicators
        //Momentum _momSPY;
        //Momentum _momACWI;
        //Momentum _momTbill;
        //DateTime sampledToday = DateTime.Now;
        
        

        
        public override void Initialize()
        {
            SetStartDate(1998, 1, 1);
            SetEndDate(2015, 1, 1); 
            SetCash(25000);
            
            foreach (var symbol in SectorSymbols)
            {
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
                Securities[symbol].SetLeverage(1);
                var momentum = MOM(symbol, 252, Resolution.Daily);
                
                SectorSymbolData.Add(new SymbolData
                {
                    Symbol = symbol,
                    MomScore = momentum
                });
            }
            
            foreach (var symbol in GEMSymbols)
            {
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
                Securities[symbol].SetLeverage(1);
                var momentum = MOM(symbol, 252, Resolution.Daily);
                
                GEMSymbolData.Add(symbol, new SymbolData
                {
                    Symbol = symbol,
                    MomScore = momentum
                });
            }
        }
           
        private bool first = true;

        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data) 
        {
            var _momSPY = GEMSymbolData["SPY"].MomScore;
            var _momTbill = GEMSymbolData["BIL"].MomScore;
            var Bonds = GEMSymbolData["AGG"].Symbol;
            
            decimal holdingPercent = 1m;
            
          if (!_momSPY.IsReady)
            {
                if (Portfolio["SPY"].Quantity == 0) 
                {
                    SetHoldings("SPY", holdingPercent);
                }
            }  
            
            if (first)
            {
                
                first = false;
                LastRotationTime = data.Time;
                return;
            }
            
            var delta = data.Time.Subtract(LastRotationTime);
            
           
            if (delta > RotationInterval)
            {
                // Easy rebalance for backtest
	            foreach(string symbol in Securities.Keys)
	            {
	                Log("Liquidating " + Portfolio[symbol].Quantity + "of " + symbol);
	                Liquidate(symbol);
	            }
	            
                LastRotationTime = data.Time;
                
                var orderedMomScores = SectorSymbolData.OrderByDescending(x => x.MomScore.Current.Value).ToList();
                int numberOfSectors = 4;
                
                for (int i = 0; i < numberOfSectors; i++)
                {
                    strongSectors.Add(orderedMomScores[i].Symbol);
                    Log("Strong Symbol #" + i + "is " + orderedMomScores[i].Symbol);
                }
                
                
                foreach (var x in orderedMomScores)
                {
                    Log(">>SCORE>>" + x.Symbol + ">>" + x.MomScore);
                }
                
                if (_momSPY < 0)
                {
                    SetHoldings(Bonds, holdingPercent);
                    Log("Holding Percent is " + holdingPercent);
                    Log("Set Holdings to " + Portfolio[Bonds].Quantity + "of " + Bonds);
                } else 
                {
                    foreach (var etf in strongSectors)
                    {
                       SetHoldings(etf, holdingPercent * (1m / numberOfSectors));
                       Log("Count of strongSectors is " + numberOfSectors);
                    } 
                } 
                
                strongSectors.Clear();
            }
        }
    }
    class SymbolData
    {
        public string Symbol;
        public Momentum MomScore { get; set; }
    }
}