Overall Statistics |
Total Trades 200 Average Win 1.78% Average Loss -0.08% Compounding Annual Return 5.447% Drawdown 9.300% Expectancy 0.175 Net Profit 5.445% Sharpe Ratio 0.434 Loss Rate 95% Win Rate 5% Profit-Loss Ratio 22.38 Alpha 0.065 Beta -0.077 Annual Standard Deviation 0.145 Annual Variance 0.021 Information Ratio 0.152 Tracking Error 0.221 Treynor Ratio -0.812 Total Fees $240.93 |
/* using the close>HMA consolidated minute bar minutes bar */ 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 HullMA : QCAlgorithm { private const string Symbol = "SPY"; public HullMovingAverage HMA; TradeBar _spyMinutes; //Initialize the data and resolution you require for your strategy: public override void Initialize() { //Start and End Date range for the backtest: SetStartDate(2015, 1, 1); SetEndDate(DateTime.Now.Date.AddDays(-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, Symbol, Resolution.Minute); HMA = new HullMovingAverage(Symbol+"_HMA_",40); var minConsolidator = new TradeBarConsolidator(TimeSpan.FromMinutes(30)); // attach our event handler. the event handler is a function that will be called each time we produce // a new consolidated piece of data. minConsolidator.DataConsolidated += OnFiveMinutes; // this call adds our daily consolidator to the manager to receive updates from the engine SubscriptionManager.AddConsolidator(Symbol, minConsolidator); RegisterIndicator(Symbol,HMA,minConsolidator,Field.Close); } private void OnFiveMinutes(object sender, TradeBar consolidated) { _spyMinutes = consolidated; //Log(consolidated.Time.ToString("o") + " >> " + Symbol + ">> LONG >> 100 >> " + Portfolio[Symbol].Quantity); // if you want code to run every five minutes then you can run it inside of here } //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) { // "TradeBars" object holds many "TradeBar" objects: it is a dictionary indexed by the symbol: // // e.g. data["MSFT"] data["GOOG"] // wait for our slow ema to fully initialize if (!HMA.IsReady) return; // only once per day //if (previous.Date == data.Time.Date) return; // define a small tolerance on our checks to avoid bouncing const decimal tolerance = 0*0.00015m; var holdings = Portfolio[Symbol].Quantity; // we only want to go long if we're currently short or flat if (holdings <= 0) { // if the fast is greater than the slow, we'll go long if (Securities[Symbol].Price > HMA ) { Log("BUY >> " + Securities[Symbol].Price + HMA); SetHoldings(Symbol, 1); } } // we only want to liquidate if we're currently long // if the fast is less than the slow we'll liquidate our long if (holdings > 0 && Securities[Symbol].Price < HMA) { Log("SELL >> " + Securities[Symbol].Price + HMA); // Liquidate(Symbol); SetHoldings(Symbol, -1); } } } public class HullMovingAverage : IndicatorBase<IndicatorDataPoint> { private readonly LinearWeightedMovingAverage _fast; private readonly LinearWeightedMovingAverage _slow; private readonly LinearWeightedMovingAverage _smooth; public HullMovingAverage(string name, int period) : base(name) { var nsquared = period*period; _fast = new LinearWeightedMovingAverage(nsquared/2); _slow = new LinearWeightedMovingAverage(nsquared); _smooth = new LinearWeightedMovingAverage(period); } public override bool IsReady { get { return _smooth.IsReady; } } protected override decimal ComputeNextValue(IndicatorDataPoint input) { _fast.Update(input); _slow.Update(input); _smooth.Update(input.Time, 2*_fast - _slow); return _smooth; } } }