Overall Statistics
Total Trades
20
Average Win
0.09%
Average Loss
-1.88%
Compounding Annual Return
-4.416%
Drawdown
9.900%
Expectancy
-0.608
Net Profit
-9.332%
Sharpe Ratio
-1.042
Loss Rate
62%
Win Rate
38%
Profit-Loss Ratio
0.05
Alpha
-0.037
Beta
0.01
Annual Standard Deviation
0.035
Annual Variance
0.001
Information Ratio
-1.191
Tracking Error
0.114
Treynor Ratio
-3.7
Total Fees
$64.84
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;

namespace QuantConnect.Algorithm.MyStrategy.test1
{
	
	
	
    public class ETFSymbol
    {
        public string Symbol;

        public RateOfChangePercent ShortPerformance { get; set; }
        public RateOfChangePercent LongPerformance { get; set; }
        public StandardDeviation vol { get; set; }
        public int rank1 { get; set; }
        public int rank2 { get; set; }
        public int rank3 { get; set; }
        public int totalRank { get; set; }
        public bool isReady
        {
            get { return ShortPerformance.IsReady && LongPerformance.IsReady && vol.IsReady; }
        }

        public decimal ObjectiveScore
        {
            get
            {
  
                decimal weight1 = 0.3m; 
                decimal weight2 = 0.3m; 
                decimal weight3 = 0.4m; 

                return (weight1 * rank1 + weight2 * rank2 + weight3 * rank3);
            }
        }
        public int totalRankAdjusted { get; set; }
    }
}                        
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/


using System;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;


namespace QuantConnect.Algorithm.MyStrategy.test1
{

	// Another note, it looks like collaboration is working.
	// I clicked the 'Share' button on the left and sent the
	// invite to 'michael@quantconnect.com' and it just worked.
	
	
    public class ETFRotation20150623 : QCAlgorithm
    {
        // we use this to tell us when the month has ended
        DateTime LastRotationTime = DateTime.MinValue;
        TimeSpan RotationInterval = TimeSpan.FromDays(1); 
        bool isRiskon = false;
        bool isProtectionOn = false;
        public Identity GOOG_Close, AAPL_Close;
   
        
        
        public IndicatorBase<IndicatorDataPoint> GOOG_Over_AAPL, SMA_GOOG_Over_AAPL;
        
        public bool isTradeDay = false;

        private bool first = true;
        decimal sumOfDividends = 0m;
        string Symbol = "SPY";




        List<string> SymbolList1 = new List<string>
        {

"AA",
"AMZN",
"TWTR",
"SHY",
"TLT"

        };

        List<string> SectorSymbols = new List<string>
        {

        };


      List<string> SymbolList2 = new List<string>
       {

"SHY",
"TLT"
        };
        
        List<DateTime> LastBday = new List<DateTime> 
        { 

            new DateTime(2015, 1, 30),
            new DateTime(2015, 2, 27),
            new DateTime(2015, 3, 31),
            new DateTime(2015, 4, 30),
            new DateTime(2015, 5, 29),
            new DateTime(2015, 6, 30),
            new DateTime(2015, 7, 31),
			new DateTime(2015, 8, 31),
        };



        // we hold computed data in these guys
        List<ETFSymbol> IndustryData = new List<ETFSymbol>();
        List<ETFSymbol> SectorData = new List<ETFSymbol>();
        List<ETFSymbol> BondData = new List<ETFSymbol>();
        List<ETFSymbol> RankedIndustryData = new List<ETFSymbol>();
        List<ETFSymbol> RankedSectorData = new List<ETFSymbol>();
        List<ETFSymbol> RankedBondData = new List<ETFSymbol>();


        
         public  List<ETFSymbol> findRanking(List<ETFSymbol> ETFList)
        {
            int n = 1;

            var rankedETFList1 = ETFList.OrderByDescending(o => o.ShortPerformance).ToList();
            foreach (ETFSymbol ETF in rankedETFList1)
            {
                ETF.rank1 = n;
                // Console.WriteLine("{0} => {1}", ETF.Symbol, ETF.ShortPerformance);
                n++;
            }

            var rankedETFList2 = rankedETFList1.OrderByDescending(o => o.LongPerformance).ToList(); ;
            n = 1;
            foreach (ETFSymbol ETF in rankedETFList2)
            {
                ETF.rank2 = n;
                //Console.WriteLine("{0} => {1}", ETF.Symbol, ETF.LongPerformance);
                n++;
            }

            var rankedETFList3 = rankedETFList2.OrderBy(o => o.vol).ToList(); ;
            n = 1;
            foreach (ETFSymbol ETF in rankedETFList3)
            {
                ETF.rank3 = n;
                //Console.WriteLine("{0} => {1}", ETF.Symbol, ETF.vol);
                n++;
            }

            var rankedETFList = rankedETFList3.OrderBy(o => o.ObjectiveScore).ToList(); ;
            n = 1;
            foreach (ETFSymbol ETF in rankedETFList)
            {
                ETF.totalRank = n;
                //Console.WriteLine("{0} => {1}", ETF.Symbol, ETF.ObjectiveScore);
                n++;
            }



            return rankedETFList;
        }

        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        public override void Initialize()
        {
            SetCash(100000);
            SetStartDate(2013, 6, 30);
            SetEndDate(2015, 8, 31);


            AddSecurity(SecurityType.Equity, "GOOG", Resolution.Minute);
            
            AddSecurity(SecurityType.Equity, "AAPL", Resolution.Minute);
;
            Securities["GOOG"].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
            
            Securities["AAPL"].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
            
            GOOG_Close = new Identity("GOOG");
            AAPL_Close = new Identity("AAPL");
            
            RegisterIndicator("GOOG", GOOG_Close, Resolution.Daily, Field.Close);
            RegisterIndicator("AAPL", AAPL_Close, Resolution.Daily, Field.Close);
            
            // needed to add security Symbol
            AddSecurity(SecurityType.Equity, Symbol, Resolution.Daily);
            var priceIndicator = Identity(Symbol);
            // FunctionalIndicator<T> requires a type parameter, this is the type of data it receives
            // Also, in order to get updates from ou 'priceIndicator' above, we need to use the .Of extension
            var totalReturnPrice = new FunctionalIndicator<IndicatorDataPoint>(Symbol + "_TotalReturn", input => input + sumOfDividends, ind => true).Of(priceIndicator);
			PlotIndicator(Symbol, priceIndicator, totalReturnPrice);
            
            GOOG_Over_AAPL = GOOG_Close.Over(AAPL_Close, "Ratio");
            SMA_GOOG_Over_AAPL = new SimpleMovingAverage("SMA_Ratio", 120).Of(GOOG_Over_AAPL);


            foreach (var symbol in SymbolList1)
            {
                
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
                var shortPerformance = ROCP(symbol, 10, Resolution.Daily); 
                var longPerformance = ROCP(symbol, 20, Resolution.Daily);
                var dailyReturn = ROCP(symbol, 1, Resolution.Daily);
                var volitality = new StandardDeviation("6Month Vol ROCP", 50).Of(dailyReturn);  

                IndustryData.Add(new ETFSymbol
                {
                    Symbol = symbol,
                    ShortPerformance = shortPerformance,
                    LongPerformance = longPerformance,
                    vol = volitality
                });
            }

            foreach (var symbol in SectorSymbols)
            {
                
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
                var shortPerformance = ROCP(symbol, 10, Resolution.Daily);
                var longPerformance = ROCP(symbol, 20, Resolution.Daily);
                var dailyReturn = ROCP(symbol, 1, Resolution.Daily);
                var volitality = new StandardDeviation("6Month Vol ROCP", 50).Of(dailyReturn); 

                SectorData.Add(new ETFSymbol
                {
                    Symbol = symbol,
                    ShortPerformance = shortPerformance,
                    LongPerformance = longPerformance,
                    vol = volitality
                });
            }

            foreach (var symbol in SymbolList2)
            {
            	
                // AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
                var shortPerformance = ROCP(symbol, 10, Resolution.Daily);               
                var longPerformance = ROCP(symbol, 20, Resolution.Daily);
                var dailyReturn = ROCP(symbol, 1, Resolution.Daily);
                var volitality = new StandardDeviation("3Month Vol ROCP", 40).Of(dailyReturn); 

                BondData.Add(new ETFSymbol
                {
                    Symbol = symbol,
                    ShortPerformance = shortPerformance,
                    LongPerformance = longPerformance,
                    vol = volitality
                });
            }
            
  


        }

		// this is where dividend events are fired within the algorithm
		public void OnData(Dividends data)
		{
			if (data.ContainsKey(Symbol))
			{
				sumOfDividends += data[Symbol].Distribution;
			}
		}


        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        /// <param name="data">TradeBars IDictionary object with your stock data</param>
        public void OnData(TradeBars data)
        {
            try
            {
                
                
                
                if (first)
                {
                    first = false;
                    LastRotationTime = data.Time;
                    return;
                }
                
                                    if (data.Time.Hour == 16 && data.Time.Minute == 00)
                    {
                     
                        
                if(2015 == data.Time.Year && 8 == data.Time.Month && 31 == data.Time.Day)
                {
                	Debug("Time: " + Time.Year.ToString() + "/" + Time.Month.ToString() + "/" +Time.Day.ToString() +": " + Portfolio.TotalPortfolioValue.ToString());
                }

                    }

                if (isRiskon && GOOG_Over_AAPL < SMA_GOOG_Over_AAPL && !isProtectionOn)
                {
						RankedBondData = findRanking(BondData);
                        foreach (ETFSymbol ETF in RankedBondData)
                        {
                            if (!data.ContainsKey(ETF.Symbol))
                            {
                                ETF.totalRank = 10000;
                            }
                        }
                        RankedBondData = RankedBondData.OrderBy(o => o.totalRank).ToList(); 
                        int n = 1;
                        foreach (ETFSymbol ETF in RankedBondData)
                        {
                            ETF.totalRankAdjusted = n;
                            
                            n++;
                        }                        
                        int threshhold1 = BondData.Find(x => x.Symbol == "SHY").totalRankAdjusted;
                        int threshhold2 = BondData.Find(x => x.Symbol == "TLT").totalRankAdjusted;
                        
                        foreach (ETFSymbol ETF in IndustryData.Union(SectorData))
                        {
                            Liquidate(ETF.Symbol);
                        }
                                                    if (threshhold1 < threshhold2)
                            {
                            	 MarketOnCloseOrder("SHY", (int)(Portfolio.Cash/ Securities["SHY"].Close - Portfolio["SHY"].Quantity));
                            }
                            if (threshhold1 > threshhold2)
                            {
                            	 MarketOnCloseOrder("TLT", (int)(Portfolio.Cash/ Securities["TLT"].Close - Portfolio["TLT"].Quantity));
                            }
                    isProtectionOn = true;
                }

                

                
                isTradeDay = false;
                foreach (DateTime tradeDay in LastBday)
                {

                    if (tradeDay.Year == data.Time.Year && tradeDay.Month == data.Time.Month && tradeDay.Day == data.Time.Day)
                    {
                        isTradeDay = true;
                        break;
                    }
                    
                }
                

                
                if (!isTradeDay)
                {
                    return;
                }


                
                var delta = data.Time.Subtract(LastRotationTime);
                
                if (delta <= RotationInterval)
                {
                    return;
                }
                
                if ( data.Time.Hour == 15 && data.Time.Minute >= 49)
                {
            
                    LastRotationTime = data.Time;
                    
   
                    
                                    if (data.Time.Hour == 16 && data.Time.Minute == 0)
                {
                    


                }                    

Debug( "Time: "+Time.Year.ToString() + "/" + Time.Month.ToString() + "/" +Time.Day.ToString() + ":" + Portfolio.TotalPortfolioValue.ToString() + ", Cash: " + Portfolio.Cash.ToString());


                    if ( GOOG_Over_AAPL > SMA_GOOG_Over_AAPL)  
                    {
         
                        isRiskon = true;
                        isProtectionOn = false;
                        RankedIndustryData = findRanking(IndustryData);
                        foreach (ETFSymbol ETF in RankedIndustryData)
                        {
                            if (!data.ContainsKey(ETF.Symbol))
                            {
                                ETF.totalRank = 10000;
                            }
                        }
                        RankedIndustryData = RankedIndustryData.OrderBy(o => o.totalRank).ToList(); 
                        int n = 1;
                        foreach (ETFSymbol ETF in RankedIndustryData)
                        {
                            ETF.totalRankAdjusted = n;
                            
                            n++;
                        }                        
                        
                        foreach (ETFSymbol ETF in BondData)
                        {
                            Liquidate(ETF.Symbol);
                        }
                        decimal TotalPortfolioValue = Portfolio.TotalPortfolioValue;
                        foreach (ETFSymbol ETF in RankedIndustryData)
                        { 
                            if (ETF.totalRankAdjusted <= 3) 
                            {
                                MarketOnCloseOrder(ETF.Symbol, (int)(TotalPortfolioValue /10/ Securities[ETF.Symbol].Close - Portfolio[ETF.Symbol].Quantity));
                                //Order(ETF.Symbol, (int)(TotalPortfolioValue / 10/ Securities[ETF.Symbol].Close - Portfolio[ETF.Symbol].Quantity), OrderType.Market);
                            }
                            else
                            {
                                Liquidate(ETF.Symbol);
                            }
                           
                                                   
                        }
   
                    }
                    else 
                    {
        
                        isRiskon = false;
                        isProtectionOn = false;
                        RankedBondData = findRanking(BondData);
                        foreach (ETFSymbol ETF in RankedBondData)
                        {
                            if (!data.ContainsKey(ETF.Symbol))
                            {
                                ETF.totalRank = 10000;
                            }
                        }
                        RankedBondData = RankedBondData.OrderBy(o => o.totalRank).ToList(); 
                        int n = 1;
                        foreach (ETFSymbol ETF in RankedBondData)
                        {
                            ETF.totalRankAdjusted = n;
                            
                            n++;
                        }                        
                        int threshhold1 = BondData.Find(x => x.Symbol == "SHY").totalRankAdjusted; 
                        int threshhold2 = BondData.Find(x => x.Symbol == "TLT").totalRankAdjusted; 
                        
                        foreach (ETFSymbol ETF in IndustryData.Union(SectorData))
                        {
                            Liquidate(ETF.Symbol);
                        }
                        decimal TotalPortfolioValue = Portfolio.TotalPortfolioValue;
                        foreach (ETFSymbol ETF in RankedBondData) // JJB trade time after 3:55, makert on close
                        {
                            
                            if (ETF.totalRankAdjusted <= 10 && ETF.totalRankAdjusted < Math.Min(threshhold1,threshhold2))
                            {
                                
                                MarketOnCloseOrder(ETF.Symbol, (int)(TotalPortfolioValue /10/ Securities[ETF.Symbol].Close - Portfolio[ETF.Symbol].Quantity));
                                
                                
                                
                            }
                            else
                            {
                                Liquidate(ETF.Symbol);
                            }
                        }
                        if (Math.Min(threshhold1,threshhold2)<=10)
                        {
                            if (threshhold1 < threshhold2)
                            {
                            	 MarketOnCloseOrder("SHY", (int)(Portfolio.Cash/ Securities["SHY"].Close - Portfolio["SHY"].Quantity));
                            }
                            if (threshhold1 > threshhold2)
                            {
                            	 MarketOnCloseOrder("TLT", (int)(Portfolio.Cash/ Securities["TLT"].Close - Portfolio["TLT"].Quantity));
                            }
             
                        }
                        foreach (ETFSymbol ETF in RankedBondData)
                        {
                           
                        }
                        
                    }
                    

                }
            }
            catch (Exception ex)
            {
                Error("OnTradeBar: " + ex.Message + "\r\n\r\n" + ex.StackTrace);
            }
        }
    }


}