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