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