Overall Statistics |
Total Trades 3883 Average Win 0.40% Average Loss -0.30% Compounding Annual Return 10.554% Drawdown 18.300% Expectancy 0.243 Net Profit 295.083% Sharpe Ratio 0.918 Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.34 Alpha 0.183 Beta -5.867 Annual Standard Deviation 0.094 Annual Variance 0.009 Information Ratio 0.745 Tracking Error 0.094 Treynor Ratio -0.015 Total Fees $0.00 |
namespace QuantConnect { public class BasicTemplateAlgorithm : QCAlgorithm { //List of the ETFs so we can call them in a foreach instead of one by one public string[] Symbols = {"XLY","XLP","XLE","XLF","XLV","XLI","XLB","XLK","XLU"}; //So creating a dictionary allows us to call rsi[symbol] letting us do all the symbols in Symbols at one time private Dictionary<string, RelativeStrengthIndex> rsi = new Dictionary<string, RelativeStrengthIndex>(); private Dictionary<string, ExponentialMovingAverage> smoothedRSI = new Dictionary<string, ExponentialMovingAverage>(); //This part here is for when we define SPY and TLT which we want to be static and separate from the other ETFS RelativeStrengthIndex rsi1; RelativeStrengthIndex rsi2; private ExponentialMovingAverage smoothedRSI1; private ExponentialMovingAverage smoothedRSI2; public decimal change; SimpleMovingAverage SMA1; SimpleMovingAverage SMA2; RollingWindow<decimal>Lev; public decimal x; public override void Initialize() { // backtest parameters SetStartDate(DateTime.Now-TimeSpan.FromDays(5000)); SetEndDate(DateTime.Now); // cash allocation SetCash(10000000); AddSecurity(SecurityType.Equity,"SPY",Resolution.Daily); AddSecurity(SecurityType.Equity,"TLT",Resolution.Daily); Securities["SPY"].FeeModel = new ConstantFeeTransactionModel(0); Securities["TLT"].FeeModel = new ConstantFeeTransactionModel(0); Lev = new RollingWindow<decimal>(5); SMA1 = SMA("SPY", 10); SMA2 = SMA("TLT", 10); //Declare RSI and how to smooth it rsi1=RSI("SPY", 14, MovingAverageType.Wilders, Resolution.Daily); smoothedRSI1 = new ExponentialMovingAverage(30).Of(rsi1); rsi2=RSI("TLT", 14, MovingAverageType.Wilders, Resolution.Daily); smoothedRSI2 = new ExponentialMovingAverage(30).Of(rsi2); //Create history in the algo so that it pumps 75 bars of data into the algo without having to wait 75 days to trade var history1 = History("SPY", 65); foreach (var tradeBar in history1) { rsi1.Update(tradeBar.EndTime, tradeBar.Close); smoothedRSI1.Update(tradeBar.EndTime, rsi1); } var history2 = History("TLT", 65); foreach (var tradeBar in history2) { rsi2.Update(tradeBar.EndTime, tradeBar.Close); smoothedRSI2.Update(tradeBar.EndTime, rsi2); } //This says for each etf in Symbols, do the following like add the data, rsi etc foreach (var symbol in Symbols) { AddSecurity(SecurityType.Equity,symbol,Resolution.Daily); rsi[symbol]=RSI(symbol,14, MovingAverageType.Wilders,Resolution.Daily); smoothedRSI[symbol]=new ExponentialMovingAverage(30).Of(rsi[symbol]); Securities[symbol].FeeModel = new ConstantFeeTransactionModel(0); var history = History(symbol, 65); foreach (var tradeBar in history) { rsi[symbol].Update(tradeBar.EndTime, tradeBar.Close); smoothedRSI[symbol].Update(tradeBar.EndTime, rsi[symbol]); } } change = 0; } public void OnData(TradeBars data) { //Catches any errors regarding start date if (data.ContainsKey("TLT")) { foreach (var symbol in Symbols) { //Report back higher between smoothed rsi of TLT or SPY var holder = smoothedRSI1; if (smoothedRSI1<smoothedRSI2) { holder = smoothedRSI2; } else holder = smoothedRSI1; if (symbol == "XLY") { x = .12m; } else if (symbol == "XLP") { x = .09m; } else if (symbol == "XLE") { x = .08m; } else if (symbol == "XLF") { x = .16m; } else if (symbol == "XLV") { x = .14m; } else if (symbol == "XLI") { x = .1m; } else if (symbol == "XLB") { x = .03m; } else if (symbol == "XLK") { x = .2m; } else if (symbol == "XLU") { x = .03m; } //If we are not already in the etf, our smoothed rsi is higher than the holder value, and a quick check to make sure we're not overleveraged if (!Portfolio[symbol].Invested && smoothedRSI[symbol]>holder && Portfolio.TotalHoldingsValue < Portfolio.TotalPortfolioValue*2) { SetHoldings(symbol, x, false, "Long " + symbol); change = change+1; } if (Portfolio[symbol].Invested && smoothedRSI[symbol]<holder) { SetHoldings(symbol, 0, false, "Close " + symbol + " Long"); change = change-1; } } var close_ratio = data["SPY"].Close / data["TLT"].Close; var movAvg_ratio = SMA1/SMA2; var bullRegime = close_ratio <= movAvg_ratio; var bearRegime = close_ratio > movAvg_ratio; Lev.Add(9-change); if (!Lev.IsReady) return; var DefQuantity = ((Portfolio.TotalPortfolioValue) - Portfolio.TotalAbsoluteHoldingsCost)/Portfolio.TotalPortfolioValue; if (Lev[0] != Lev[1] || Lev[0] == 0 || (Portfolio.TotalAbsoluteHoldingsCost/Portfolio.TotalPortfolioValue) < .9m) { if (bullRegime) { SetHoldings("TLT", 0, false, "Close TLT"); SetHoldings("SPY", DefQuantity, false, "SPY Open"); } if (bearRegime) { SetHoldings("SPY", 0, false, "Close SPY"); SetHoldings("TLT", DefQuantity, false, "TLT Open"); } } } } } }