Overall Statistics |
Total Trades 13 Average Win 47.54% Average Loss -12.35% Compounding Annual Return 47.026% Drawdown 54.900% Expectancy 3.042 Net Profit 650.744% Sharpe Ratio 0.993 Loss Rate 17% Win Rate 83% Profit-Loss Ratio 3.85 Alpha 0.401 Beta -0.052 Annual Standard Deviation 0.399 Annual Variance 0.159 Information Ratio 0.712 Tracking Error 0.415 Treynor Ratio -7.679 Total Fees $3482.64 |
//Copyright Warren Harding 2016, granted to the public domain. //Use entirely at your own risk. //Custom algorithm development: warrencharding@yahoo.com. // // Modified by John Roc to trade multiple pairs equally weighted in portfolio // Changes: // 1. Upto 10 ETF pairs in order // 2. Independent Standard Deviation parameters for each pairs // 3. DataNormalizationMode set to raw to get unadjusted prices // //Do not remove this copyright notice. namespace QuantConnect { public class LevETFs : QCAlgorithm { //StandardDeviation std1, std2, std3, std4, std5; decimal _tolerance = .02m; int indicatorPeriod=360; //int di_indicatorPeriod=120; double portfolio_weight=1.0; Resolution resolution=Resolution.Minute; //string[] etf = { "TQQQ", "UPRO" }; //string[] invetf = { "SQQQ", "SPXU" }; string[] etf = {"TQQQ"}; string[] invetf = {"SQQQ"}; //decimal myStdDevConst = 1.75m; decimal[] myStdDevConst = new decimal[] {1.2m,1.75m}; decimal[] diplus = new decimal[10]; decimal[] diminus = new decimal[10]; // Note that the size of the array is limited to handle 10 pairs StandardDeviation[] std = new StandardDeviation[10]; AverageDirectionalIndex[] _adx = new AverageDirectionalIndex[10]; public override void Initialize() { IEnumerable<TradeBar>[] history = new IEnumerable<TradeBar>[10]; // distribute weight queally among ETF pairs portfolio_weight = 1.0/(etf.Length); // backtest parameters //SetStartDate(2009, 10, 05); SetStartDate(2012, 8, 5); //SetEndDate(2017, 03, 31); // cash allocation SetCash(1000000); for (int i=0 ; i< etf.Length; i++) { AddEquity(etf[i], resolution,Market.USA,true,1m,false); AddEquity(invetf[i], resolution,Market.USA,true,1m,false); // need to use raw normalized mode to avoid look ahead bias and prices before inverse splits Securities[etf[i]].SetDataNormalizationMode(DataNormalizationMode.Raw); Securities[invetf[i]].SetDataNormalizationMode(DataNormalizationMode.Raw); std[i] = STD(etf[i], indicatorPeriod, resolution); _adx[i] = ADX(etf[i], indicatorPeriod, resolution); history[i] = History(etf[i], indicatorPeriod, resolution); foreach (var tradeBar in history[i]) { std[i].Update(tradeBar.EndTime, tradeBar.Close); } } //SetWarmUp(indicatorPeriod); } public override void OnData(Slice data) { //if (IsWarmingUp) return; for(int x=0; x < etf.Length; x++ ){ diplus[x] = _adx[x].PositiveDirectionalIndex; diminus[x] = _adx[x].NegativeDirectionalIndex; // if stddev UNDER threshold and DI+ GREATER than DI- ( indicating slow uptrend) // 1. close position shortETF if exists, // 2. go long longETF, if not long already if (std[x] < myStdDevConst[x]){ if(diplus[x] > diminus[x] * (1 + _tolerance)){ if(Securities[invetf[x]].Invested) SetHoldings(invetf[x], 0); //Liquidate(invetf[x]); if(Securities[etf[x]].Invested == false) SetHoldings(etf[x], portfolio_weight); Error(Time.ToString() + "|" + myStdDevConst[x].ToString() + "|" + std[x].ToString() + "|" + etf[x] + "|" + portfolio_weight.ToString()); } else{ // seems redundant to have both conditions result in the same result, // but we can change to have cash if needed if(Securities[invetf[x]].Invested) SetHoldings(invetf[x], 0); //Liquidate(invetf[x]); if(Securities[etf[x]].Invested == false) SetHoldings(etf[x], portfolio_weight); Error(Time.ToString() + "|" + myStdDevConst[x].ToString() + "|" + std[x].ToString() + "|" + etf[x] + "|" + portfolio_weight.ToString()); } } else { if(diplus[x] > diminus[x] * (1 + _tolerance)){ if(Securities[invetf[x]].Invested) SetHoldings(invetf[x], 0); //Liquidate(invetf[x]); if(Securities[etf[x]].Invested == false) SetHoldings(etf[x], portfolio_weight); Error(Time.ToString() + "|" + myStdDevConst[x].ToString() + "|" + std[x].ToString() + "|" + etf[x] + "|" + portfolio_weight.ToString()); } else{ if(Securities[etf[x]].Invested) SetHoldings(etf[x], 0); //Liquidate(etf[x]); if(Securities[invetf[x]].Invested == false) SetHoldings(invetf[x], portfolio_weight); Error(Time.ToString() + "|" + myStdDevConst[x].ToString() + "|" + std[x].ToString() + "|" + invetf[x] + "|" + portfolio_weight.ToString()); } } } } } }