| Overall Statistics |
|
Total Trades 27 Average Win 7.98% Average Loss -5.85% Compounding Annual Return 3.478% Drawdown 25.000% Expectancy 0.330 Net Profit 78.896% Sharpe Ratio 0.369 Loss Rate 44% Win Rate 56% Profit-Loss Ratio 1.37 Alpha 0.04 Beta -0.002 Annual Standard Deviation 0.109 Annual Variance 0.012 Information Ratio -0.185 Tracking Error 0.228 Treynor Ratio -21.537 Total Fees $33.36 |
namespace QuantConnect
{
/*
* QuantConnect University: Full Basic Template:
*
* The underlying QCAlgorithm class is full of helper methods which enable you to use QuantConnect.
* We have explained some of these here, but the full algorithm can be found at:
* https://github.com/QuantConnect/QCAlgorithm/blob/master/QuantConnect.Algorithm/QCAlgorithm.cs
*/
public class BasicTemplateAlgorithm : QCAlgorithm
{
private AnnualizedExponentialSlope adjustedSlope;
//Initialize the data and resolution you require for your strategy:
public override void Initialize()
{
//Start and End Date range for the backtest:
SetStartDate(1998, 1, 1);
SetEndDate(2015, 1, 1);
//Cash allocation
SetCash(25000);
//Add as many securities as you like. All the data will be passed into the event handler:
AddSecurity(SecurityType.Equity, "SPY", Resolution.Daily);
adjustedSlope = new AnnualizedExponentialSlope(90);
RegisterIndicator("SPY", adjustedSlope, Resolution.Daily, Field.Close);
PlotIndicator("AdjSlope", true, adjustedSlope);
}
//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)
{
if (!adjustedSlope.IsReady) return;
var quantity = Portfolio["SPY"].Quantity;
if (quantity <= 0 && adjustedSlope > 20)
{
SetHoldings("SPY", .75);
}
if (quantity >= 0 && adjustedSlope < -2.5m)
{
if (adjustedSlope < -10)
{
SetHoldings("SPY", -.5);
}
else
{
SetHoldings("SPY", 0);
}
}
}
}
}using MathNet.Numerics;
namespace QuantConnect
{
public class AnnualizedExponentialSlope : WindowIndicator<IndicatorDataPoint>
{
public AnnualizedExponentialSlope(int period)
: base("AdjustedSlope" + period, period)
{
}
public AnnualizedExponentialSlope(string name, int period)
: base(name, period)
{
}
protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
{
if (window.Count < 3) return 0m;
var xVals = new double[window.Count];
var yVals = new double[window.Count];
// load input data for regression
for (int i = 0; i < window.Count; i++)
{
xVals[i] = i;
// we want the log of our y values
yVals[i] = Math.Log((double)window[window.Count - i - 1].Value);
}
//http://numerics.mathdotnet.com/Regression.html
// solves y=a + b*x via linear regression
var fit = Fit.Line(xVals, yVals);
var intercept = fit.Item1;
var slope = fit.Item2;
// compute rsquared
var rsquared = GoodnessOfFit.RSquared(xVals.Select(x => intercept + slope*x), yVals);
// anything this small can be viewed as flat
if (double.IsNaN(slope) || Math.Abs(slope) < 1e-25) return 0m;
// trading days per year for us equities
const int dayCount = 252;
// annualize dy/dt
var annualSlope = ((Math.Pow(Math.Exp(slope), dayCount)) - 1) * 100;
// scale with rsquared
annualSlope = annualSlope * rsquared;
return (decimal) annualSlope;
}
}
}