| 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");
}
}
}
}
}
}