| Overall Statistics |
|
Total Trades 593 Average Win 0.72% Average Loss -0.7% Compounding Annual Return 6.903% Drawdown 18.800% Expectancy 0.285 Net Profit 211.264% Sharpe Ratio 0.705 Loss Rate 37% Win Rate 63% Profit-Loss Ratio 1.03 Alpha 0.048 Beta 0.294 Annual Standard Deviation 0.102 Annual Variance 0.01 Information Ratio -0.064 Tracking Error 0.166 Treynor Ratio 0.245 Total Fees $1315.83 |
namespace QuantConnect
{
/*
* QuantConnect University: Futures Example
*
* QuantConnect allows importing generic data sources! This example demonstrates importing a futures
* data from the popular open data source Quandl.
*
* QuantConnect has a special deal with Quandl giving you access to Stevens Continuous Futurs (SCF) for free.
* If you'd like to download SCF for local backtesting, you can download it through Quandl.com.
*/
public class DualMomentumSectorRotation : QCAlgorithm
{
// we'll use this to tell us when the month has ended
DateTime LastRotationTime = DateTime.MinValue;
TimeSpan RotationInterval = TimeSpan.FromDays(30);
List<string> GEMSymbols = new List<string>
{
"SPY",
"BIL",
"AGG"
};
// these are the growth symbols we'll rotate through
List<string> SectorSymbols = new List<string>
{
"XLV", //healthcare
"XLK", //technology
"XLI", //industrial
"XLU", //utilities
"XLF", //financials
"XLY", //consumerdisc
"XLP", //consumerstap
"XLB", //basic materials
"XLE", // energy
"PSR", //real estate
"IYZ" // communications
};
// we'll hold some computed data in these guys
List<SymbolData> SectorSymbolData = new List<SymbolData>();
Dictionary<string, SymbolData> GEMSymbolData = new Dictionary<string, SymbolData>();
List<string> strongSectors = new List<string>();
// Indicators
//Momentum _momSPY;
//Momentum _momACWI;
//Momentum _momTbill;
//DateTime sampledToday = DateTime.Now;
public override void Initialize()
{
SetStartDate(1998, 1, 1);
SetEndDate(2015, 1, 1);
SetCash(25000);
foreach (var symbol in SectorSymbols)
{
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
Securities[symbol].SetLeverage(1);
var momentum = MOM(symbol, 252, Resolution.Daily);
SectorSymbolData.Add(new SymbolData
{
Symbol = symbol,
MomScore = momentum
});
}
foreach (var symbol in GEMSymbols)
{
AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
Securities[symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);
Securities[symbol].SetLeverage(1);
var momentum = MOM(symbol, 252, Resolution.Daily);
GEMSymbolData.Add(symbol, new SymbolData
{
Symbol = symbol,
MomScore = momentum
});
}
}
private bool first = true;
//Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
public void OnData(TradeBars data)
{
var _momSPY = GEMSymbolData["SPY"].MomScore;
var _momTbill = GEMSymbolData["BIL"].MomScore;
var Bonds = GEMSymbolData["AGG"].Symbol;
decimal holdingPercent = 1m;
if (!_momSPY.IsReady)
{
if (Portfolio["SPY"].Quantity == 0)
{
SetHoldings("SPY", holdingPercent);
}
}
if (first)
{
first = false;
LastRotationTime = data.Time;
return;
}
var delta = data.Time.Subtract(LastRotationTime);
if (delta > RotationInterval)
{
// Easy rebalance for backtest
foreach(string symbol in Securities.Keys)
{
Log("Liquidating " + Portfolio[symbol].Quantity + "of " + symbol);
Liquidate(symbol);
}
LastRotationTime = data.Time;
var orderedMomScores = SectorSymbolData.OrderByDescending(x => x.MomScore.Current.Value).ToList();
int numberOfSectors = 4;
for (int i = 0; i < numberOfSectors; i++)
{
strongSectors.Add(orderedMomScores[i].Symbol);
Log("Strong Symbol #" + i + "is " + orderedMomScores[i].Symbol);
}
foreach (var x in orderedMomScores)
{
Log(">>SCORE>>" + x.Symbol + ">>" + x.MomScore);
}
if (_momSPY < 0)
{
SetHoldings(Bonds, holdingPercent);
Log("Holding Percent is " + holdingPercent);
Log("Set Holdings to " + Portfolio[Bonds].Quantity + "of " + Bonds);
} else
{
foreach (var etf in strongSectors)
{
SetHoldings(etf, holdingPercent * (1m / numberOfSectors));
Log("Count of strongSectors is " + numberOfSectors);
}
}
strongSectors.Clear();
}
}
}
class SymbolData
{
public string Symbol;
public Momentum MomScore { get; set; }
}
}