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