Overall Statistics
Total Trades
575
Average Win
2.00%
Average Loss
-0.99%
Compounding Annual Return
19.623%
Drawdown
24.100%
Expectancy
0.895
Net Profit
928.060%
Sharpe Ratio
0.958
Loss Rate
37%
Win Rate
63%
Profit-Loss Ratio
2.02
Alpha
0.141
Beta
0.311
Annual Standard Deviation
0.169
Annual Variance
0.028
Information Ratio
0.49
Tracking Error
0.197
Treynor Ratio
0.519
Total Fees
$1443.58
using QuantConnect.Indicators;
using System;
using System.Collections.Concurrent;

namespace QuantConnect 
{   
	// Non-barebones implementation of https://seekingalpha.com/article/4120090-horrifically-good-investment-strategy
	/*
		Little Jack Horner sat in the corner, eating his christmas pie.
		He put in his thumb and pulled out a plumb, then said:
		"What a good boy am I".
	*/
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
    	List<string> GrowthUniverse = new List<string>() {
    		"ATVI","ADBE","AKAM","ALXN","GOOG","GOOGL","AMZN",
    		"AAL","AMGN","ADI","AAPL","AMAT","ADSK","ADP","BIDU",
    		"BBBY","BIIB","BMRN","AVGO","CA","CELG","CERN","CHTR",
    		"CHKP","CSCO","CTXS","CTSH","CMCSA","COST","CSX","CTRP",
    		"DISCA","DISCK","DISH","DLTR","EBAY","EA","ENDP","EXPE",
    		"ESRX","FB","FAST","FISV","GILD","HSIC","ILMN","INCY",
    		"INTC","INTU","ISRG","JD","LRCX","LBTYA","LBTY","LVNTA",
    		"QVCA","LMCK","BATRA","BATRK","LLTC","MAR","MAT",
    		"MXIM","MU","MSFT","MDLZ","MNST","MYL","NTAP","NTES","NFLX",
    		"NCLH","NVDA","NXPI","ORLY","PCAR","PAYX","PYPL","QCOM","REGN",
    		"ROST","SBAC","STX","SIRI","SWKS","SBUX","SRCL","SYMC","TMUS",
    		"TSLA","TXN","KHC","PCLN","TSCO","TRIP","FOX","FOXA","ULTA",
    		"VRSK","VRTX","VIAB","VOD","WBA","WDC","WFM","XLNX","YHOO", 
    		"LMT", "HII", "TLT",
    		"PKG","A","BSD","BLK","CNX","EVN","ETM","GBL","GS","HT","HGT","JNPR","KFY","LII","NAC","NAN","NAD","NSL","RTEC","SKX","UPS","WCC","DSU","MUC","MUH","MUJ","MUS","CLS","CVG","DHF","EVF","FII","GIL","VVR","LHO","HZO","OME","PAA","RAS","RSG","SCS","WDR","TLI","HIX","MHD","MFL","MHN","BXP","CSU","CBI","CEA","ZNH","CIEN","FIX","CBD","DRQ","EPR","FBR","FDP","BGC","GPI","I,A","ING","KRC","MMS","MTD","NTL","RL","SLG","SAH","SRT","SRI","TSM","URI","MTN","BVN","CCJ","DVD","FDS","FFG","GEL","GES","NUS","REV","SPH","TGI","WG","CLB","DO","DST","EL","MSM","RWT","TRK","WAT","AIV","BZH","COF","CYD","ESS","FGP","FR","GBX","HIW","HNP","BTO","KEP","MAC","MLM","MAA","IIF","NOK","RCS","PLT","PKX","RS","KST","VCO","AWF","BKN","MUA","MVT","BYD","CPT","CBL","KOF","RFI","DDR","DECK","DDF","DUC","ETH","IT","TV","HHS","HR","JBL","MHO","MSD","NTZ","NFX","NTC","NMY","NOM","NNC","NPV","PCM","PMO","REG","RCL","BFS","SQM","SGY","SUI","SKT","TEI","MNP","YPF","GCH","JEQ","BLX","MYC","MCA","MYF","MFT","MIY","MYJ","MYN","MPA","MQT","MQY","ELY","CRT","PFO","KSS","MTX","NAZ","NXC","NXN","NIM","NXP","NXQ","NXR","OHI","ASGN",",OP","SMG","TCO","HQL","USPH","SBI","MMU","MYD","DTF","FCFS","PFD","HAE","HMN","MTG","MSF","NUM","NUO","NQP","NTX","RGS","WNC","SGF","COG","JOF","GF","IRL","MEN","CXE","CXH","DSM","IEX","VLT","MCR","POT","PMM","KSM","TKF","MPV","MIN","HYB","NMI","NNY","PIM","PPT","KTF","BID","TEF","GIM","TTF","USM","ZTR","MHF","CBM","CCL","FUN","CMU","LEO","DNP","MBI","MGF","MMT","NUV","HQH","EMF","TIF","BPL","GAB","GER","KBH","USA","MKL","MFM","ORCL","RVT","TWN","ZF","WTS","FEI"
    	};
    	List<string> SafeUniverse = new List<string>() {"TLT"};
    	public Dictionary<string, Indicators.RateOfChangePercent> _symbolsData = new Dictionary<string, Indicators.RateOfChangePercent>();

    	int MaxGrowthCount = 10;
    	bool ShouldRebalance = true;
    	int Lookback = 22*3;

        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {
            //Start and End Date range for the backtest:
            SetStartDate(2005, 2, 10);
            SetEndDate(DateTime.Now.Date.AddDays(-1));
            SetWarmup(Lookback+1);
            //Cash allocation
            SetCash(25000);
            UniverseSettings.Resolution = Resolution.Daily;
   
   			foreach(var sec in GrowthUniverse)
   			{
   				AddSecurity(SecurityType.Equity, sec, Resolution.Daily);
		    	_symbolsData[sec] = ROCP(sec, Lookback, Resolution.Daily);
   			}
        
        	foreach(var sec in SafeUniverse)
				AddSecurity(SecurityType.Equity, sec, Resolution.Daily);
        	
        }
        
		string prevMonth = "";
        public void OnData(TradeBars data) 
        {   
            string month = Time.ToString("MMM");
			if(!Portfolio.HoldStock){
				Liquidate();
				Console.WriteLine("Going growth - Initial");
				var leastVolatile = (from _symbol in data.Keys
									where _symbolsData[_symbol] > 0
									orderby _symbolsData[_symbol] descending
									select _symbol).Take(MaxGrowthCount);
					
				foreach(var entry in leastVolatile)
					SetHoldings(entry, (decimal)0.78/leastVolatile.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.68)/leastVolatile.Count()));
				
				// Buy 30% Safe
				foreach(var entry in SafeUniverse)
					SetHoldings(entry, (decimal)0.19/SafeUniverse.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.29)/SafeUniverse.Count()));
				
			}
            if(month == "Nov" && prevMonth != "Nov"){
            	Liquidate();
            	Console.WriteLine("Going growth");
				var leastVolatile = (from _symbol in data.Keys
									where _symbolsData[_symbol] > 0
									orderby _symbolsData[_symbol] descending
									select _symbol).Take(MaxGrowthCount);


				foreach(var entry in leastVolatile)
					SetHoldings(entry, (decimal)0.78/leastVolatile.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.68)/leastVolatile.Count()));
				
				// Buy 30% Safe
				foreach(var entry in SafeUniverse)
					SetHoldings(entry, (decimal)0.19/SafeUniverse.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.29)/SafeUniverse.Count()));
				
            }
            if(month == "May" && prevMonth != "May"){
            	Liquidate();
            	Console.WriteLine("Going safe");
            	
            	var leastVolatile = (from _symbol in data.Keys
									where _symbolsData[_symbol] > 0
									orderby _symbolsData[_symbol]
									select _symbol).Take(MaxGrowthCount);
									

				foreach(var entry in leastVolatile)
					SetHoldings(entry, (decimal)0.29/leastVolatile.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.68)/leastVolatile.Count()));
				
				// Buy 30% Safe
				foreach(var entry in SafeUniverse)
					SetHoldings(entry, (decimal)0.68/SafeUniverse.Count());
					//Order(entry,  Math.Floor((Portfolio.Cash*(decimal)0.29)/SafeUniverse.Count()));
				
            }
            prevMonth = month;

        }
    }
}