| Overall Statistics |
|
Total Trades 324 Average Win 2.28% Average Loss -0.48% Compounding Annual Return 8.654% Drawdown 7.500% Expectancy 3.272 Net Profit 252.371% Sharpe Ratio 1.294 Loss Rate 26% Win Rate 74% Profit-Loss Ratio 4.74 Alpha 0.016 Beta 3.418 Annual Standard Deviation 0.064 Annual Variance 0.004 Information Ratio 0.991 Tracking Error 0.064 Treynor Ratio 0.024 Total Fees $28181.63 |
namespace QuantConnect
{
public class BasicTemplateAlgorithm : QCAlgorithm
{
public string[] Symbols = {"XLY","XLP","XLE","XLF","XLV","XLI","XLB","XLK","XLU","IYZ","SPY","IEF"};
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> SectorRSI = new Dictionary<string, decimal>();
public string Baseline;
RollingWindow<string> Regime;
RollingWindow<decimal> Value;
RollingWindow<decimal> Returns;
RollingWindow<decimal> TValue;
RollingWindow<decimal> TReturns;
public decimal KC;
public decimal Leverage;
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(100).Of(rsi[symbol]);
//Securities[symbol].FeeModel = new ConstantFeeTransactionModel(0);
Securities[symbol].SetLeverage(10);
var history = History(symbol, 115);
foreach (var tradeBar in history)
{
rsi[symbol].Update(tradeBar.EndTime, tradeBar.Close);
smoothedRSI[symbol].Update(tradeBar.EndTime, rsi[symbol]);
}
Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.Raw);
}
Regime = new RollingWindow<string>(2);
Value = new RollingWindow<decimal>(2);
Returns = new RollingWindow<decimal>(50);
TValue = new RollingWindow<decimal>(2);
TReturns = new RollingWindow<decimal>(50);
Leverage = 1;
}
public void OnData(Dividends data)
{
foreach (var symbol in Symbols){if (data.ContainsKey(symbol))
{
var dividend = data[symbol];
var qty = Portfolio[symbol].HoldingsValue / (Portfolio.TotalPortfolioValue - (dividend.Distribution * Portfolio[symbol].Quantity));
SetHoldings(symbol, qty, false, "Dividend Reinvestment");
}}
}
public void OnData(TradeBars data)
{
foreach (var symbol in Symbols){if (!data.ContainsKey(symbol)) return;}
foreach (var Sector in Sectors)
{
SectorRSI[Sector] = smoothedRSI[Sector];
}
/////// BASELINE /////////
if (smoothedRSI["SPY"] > smoothedRSI["IEF"]){Baseline = "SPY";} else{Baseline = "IEF";}
Regime.Add(Baseline); if (!Regime.IsReady) return;
//////// ENTRY RULES //////////////
int Positions = 4; if (KC > 0){Positions=Convert.ToInt32(Math.Ceiling(KC/.1m));}
if ((Regime[0] != Regime[1]||!Portfolio.Invested) && Regime[0] == "IEF")
{
SetHoldings("IEF", 1*Leverage, false, "Long Bonds");
foreach (var Sector in Sectors)
{
if (Portfolio[Sector].Invested){SetHoldings(Sector, 0, false, "Close " + Sector);}
}
}
if ((Regime[0] != Regime[1]||!Portfolio.Invested) && Regime[0] == "SPY")
{
foreach (var item in SectorRSI.OrderByDescending(key => key.Value).Take(Positions))
{
SetHoldings(item.Key, .1m * Leverage, false, "Open " + item.Key);
}
SetHoldings("IEF", (1-(Positions*(.1m*Leverage))), false, "Proportion Bonds");
}
//////// KELLY CRITERION //////
Value.Add(Portfolio.TotalPortfolioValue); if (!Value.IsReady) return;
var Return = (Value[0] - Value[1])/(Value[1]);
Returns.Add(Return); if (!Returns.IsReady) return;
var StrategyReturns = Returns.Average();
double sum = Returns.Sum(d => Math.Pow(Convert.ToDouble(d - StrategyReturns), 2));
var ret = Math.Sqrt((sum) / (Returns.Count()));
TValue.Add(data["IEF"].Close); if (!TValue.IsReady) return;
var TReturn = (TValue[0] - TValue[1])/(TValue[1]);
TReturns.Add(TReturn); if (!TReturns.IsReady) return;
var TreasuryReturns = TReturns.Average();
var StrategyStDev = Convert.ToDecimal(Math.Pow(ret*100,2));
if (StrategyStDev == 0) return;
KC = ((StrategyReturns - TreasuryReturns)*100)/(StrategyStDev);
var Lev = Portfolio.TotalHoldingsValue / Portfolio.TotalPortfolioValue;
Plot("Chart", "Leverage", Lev);
}
}
}