Overall Statistics
Total Trades
383
Average Win
1.05%
Average Loss
-0.13%
Compounding Annual Return
6.302%
Drawdown
14.400%
Expectancy
3.998
Net Profit
151.943%
Sharpe Ratio
0.636
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
8.36
Alpha
0.113
Beta
-3.637
Annual Standard Deviation
0.084
Annual Variance
0.007
Information Ratio
0.442
Tracking Error
0.084
Treynor Ratio
-0.015
Total Fees
$0.00
namespace QuantConnect 
{   
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
    	public string[] Symbols = {"XLY","XLP","XLE","XLF","XLV","XLI","XLB","XLK","XLU","IYZ","SPY","IEF","TLT"};
    	public string[] Sectors = {"XLY","XLP","XLE","XLF","XLV","XLI","XLB","XLK","XLU","IYZ"};
    	
    	private Dictionary<string, RelativeStrengthIndex> rsi = new Dictionary<string, RelativeStrengthIndex>();
    	private Dictionary<string, SimpleMovingAverage> smoothedRSI = new Dictionary<string, SimpleMovingAverage>();
    	private Dictionary<string, decimal> Weight = new Dictionary<string, decimal>();
    	
    	public string Baseline;
    	RollingWindow<string> Regime;
    	public decimal MaxWeight;
    	RollingWindow<decimal> Profit;
    	RollingWindow<decimal> ProfitWins;
    	RollingWindow<decimal> ProfitLosses;
    	RollingWindow<decimal> WLCount;
    	
    	public decimal Kelly;
    	public int Counter;
    	
    	public decimal B;
    	public decimal P;
    	
    	RollingWindow<decimal> SpyClose;
    	RollingWindow<decimal> Holdings;
 
        public override void Initialize() 
        {
            SetStartDate(2003, 1, 1);
            SetEndDate(DateTime.Now);
            SetCash(10000000);
            
			foreach (var symbol in Symbols)
			{
				AddSecurity(SecurityType.Equity,symbol,Resolution.Daily);
            	rsi[symbol]=RSI(symbol, 14, MovingAverageType.Wilders);
            	smoothedRSI[symbol]=new SimpleMovingAverage(120).Of(rsi[symbol]);
            	
            	Securities[symbol].FeeModel = new ConstantFeeTransactionModel(0);
            	Securities[symbol].SetLeverage(5);
            
            	var history = History(symbol, 135);
            	foreach (var tradeBar in history)
            	{
            		rsi[symbol].Update(tradeBar.EndTime, tradeBar.Close);
            		smoothedRSI[symbol].Update(tradeBar.EndTime, rsi[symbol]);
        	 	}
			}
			
			Weight.Add("XLY", .12m); Weight.Add("XLP", .09m); Weight.Add("XLE", .08m); Weight.Add("XLF", .16m); Weight.Add("XLV", .14m);
			Weight.Add("XLI", .1m); Weight.Add("XLB", .03m); Weight.Add("XLK", .2m); Weight.Add("XLU", .03m); Weight.Add("IYZ", .02m);
			
			Regime = new RollingWindow<string>(2);
			Profit = new RollingWindow<decimal>(2);
			
			ProfitWins = new RollingWindow<decimal>(41);
        	ProfitLosses = new RollingWindow<decimal>(41);
        	WLCount = new RollingWindow<decimal>(41);
        	SpyClose = new RollingWindow<decimal>(31);
        	Holdings = new RollingWindow<decimal>(2);
        }
        public void OnData(TradeBars data) 
        {
        	foreach (var symbol in Symbols){if (!data.ContainsKey(symbol)) return;}
        	
        	if (smoothedRSI["SPY"] > smoothedRSI["IEF"]){Baseline = "SPY";} else{Baseline = "IEF";}
        	Regime.Add(Baseline); if (!Regime.IsReady) return;
        	
        	
        	//////// Calculating How Many Sectors Will Be Opened ////////
       
        	foreach (var Sector in Sectors)
        	{	
        		if (!Portfolio[Sector].Invested && smoothedRSI[Sector] > smoothedRSI[Baseline])
        		{
        			MaxWeight = MaxWeight + Weight[Sector]*2;
        		}
        		if (Portfolio[Sector].Invested && smoothedRSI[Sector] < smoothedRSI[Baseline])
        		{
        			MaxWeight = MaxWeight - Weight[Sector]*2;
        		}
        	}
        	
        	
        	//////// Opening Positions in the Sectors so that Allocation will be (100% of Total Value) * Kelly Criterion ////////
        	
        	foreach (var Sector in Sectors)
        	{
        		if (!Portfolio[Sector].Invested && smoothedRSI[Sector] > smoothedRSI[Baseline])
        		{
        			var x = Weight[Sector]/MaxWeight;
        			if (Kelly != 0){x = (Kelly);}
        			SetHoldings(Sector, .01m, false, "Odds are " + Math.Round(B,2) + " and Win % is " + Math.Round(P*100,2));
        		}
        		if (Portfolio[Sector].Invested && smoothedRSI[Sector] < smoothedRSI[Baseline])
        		{
        			SetHoldings(Sector, 0, false, "Close " + Sector);
        			
        			Profit.Add(Portfolio[Sector].LastTradeProfit); if(!Profit.IsReady) return;
        	
        			var Return = Profit[0];
        	
        			if (Return > 0)
        			{
        				ProfitWins.Add(Return);
        				++Counter;
        			}
        			if (Return <= 0)
        			{
        				ProfitLosses.Add(Math.Abs(Return));
        			}
        			WLCount.Add(Counter);
        		}
        	}
        	
        	
        	///////// Opening Positions in the Benchmark so that Allocation will be (100% of Total Value) * Kelly Criterion //////
        	
        	if (Regime[0] != Regime[1])
        	{
        		SetHoldings(Regime[1], 0, false, "Close " + Regime[1]);
        		var x = 1.0m;
        		if (Kelly != 0){x = (Kelly);}
        		SetHoldings(Regime[0], x, false, "Open " + Regime[0]);
        	}
        	
        	
        	////////// KELLY CRITERION CALCULATIONS //////////////
        	
        	if (!(ProfitWins.IsReady && ProfitLosses.IsReady && WLCount.IsReady)) return;
        	
        	P = (WLCount[0] - WLCount[40])/40;
        	B = ProfitWins.Average();
        	if (ProfitLosses.Average()!=0)
        	{
        		B = (ProfitWins.Average()) / (ProfitLosses.Average());
        	}
        	if (B != 0)
        	{
        		Kelly = (P - ((1-P)/(B)));
        	}
        	
        	Plot("Chart", "Kelly Criterion", Kelly);
        }
    }
}