Overall Statistics
Total Trades
4744
Average Win
0.28%
Average Loss
-0.32%
Compounding Annual Return
34.842%
Drawdown
10.600%
Expectancy
0.051
Net Profit
105.365%
Sharpe Ratio
1.57
Loss Rate
44%
Win Rate
56%
Profit-Loss Ratio
0.88
Alpha
0.342
Beta
-0.121
Annual Standard Deviation
0.203
Annual Variance
0.041
Information Ratio
0.548
Tracking Error
0.24
Treynor Ratio
-2.633
Total Fees
$19845.08
using System;
using System.Collections.Generic;
using QuantConnect;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;


namespace QuantConnect
{
    public class EMACrossingHMA : QCAlgorithm
    {
    /* +--------------------------------------------+
     * |Control Panel - Making overfitting easier   |
     * +--------------------------------------------+*/
        int HMAPeriod = 4;                  // The Hull Moving Average period
        int slowEMAPeriod = 15;             // A Slow EMA period
        static int lookbackWindow = 45;     // Channel lookback used to estimate the uppenr and lower bands
    /* +--------------------------------------------+*/

        string symbol = "SPY";
        IndicatorBase<IndicatorDataPoint> HMA;
        ExponentialMovingAverage slowEMA;
        CompositeIndicator<IndicatorDataPoint> signal;
        Resolution resolution = Resolution.Minute;
        RollingWindow<decimal> Band = new RollingWindow<decimal>(lookbackWindow);

        // NEW: added code to map between regular and trade bar indicators
        DonchianChannel Channel = new DonchianChannel("myChannel", 10);

        public override void Initialize()
        {
            SetStartDate(2013, 1, 1);
            SetEndDate(2015, 5, 31);
            SetCash(25000);

            AddSecurity(SecurityType.Equity, symbol, resolution);

            slowEMA = EMA(symbol, slowEMAPeriod, resolution);

            // hull has two 'source' indicators, a fast and slow
            int period = HMAPeriod;
            int slow = (int) Math.Pow(period, 2);
            int fast = slow/2;

            var slowLwma = LWMA("SPY", slow);
            var fastLwma = LWMA("SPY", fast);
            var twiceFast = fastLwma.Times(new ConstantIndicator<IndicatorDataPoint>("2", 2));
            var interior = twiceFast.Minus(slowLwma);
            HMA = new LinearWeightedMovingAverage(period).Of(interior);

            //HMA = new HullMovingAverage("HMA(" + symbol + ")", HMAPeriod);   // Why is the name needed?
            Func<BaseData, decimal> selector = null;                         // I really don't know what this does, but make it work :P
            RegisterIndicator(symbol, HMA, resolution, selector);
            signal = HMA.Minus(slowEMA);
            
            // this is not very pretty, but it creates an intermediate indicator to accept the signal data
            // and then transform it into a trade bar for the Channel
            Channel.AsSimpleIndicator().Of(signal);
            

        }
        bool first = true;
        public void OnData(TradeBars data)
        {
            // I tried to use something like:
            
            // Channel.Of(signal);
            
            
            // but didn't work.
            if (!slowEMA.IsReady || !HMA.IsReady) return;
            if (Band.IsReady && Channel.IsReady)
            {
                if (first)
                {
                    // PlotIndicator will plot the indicator on each new data point, very awesome!
                    // this version, however, doesn't wait until the indicator is ready, so I added
                    // this ugly code to just wait until they're ready, and then call PlotIndicator
                    // to register for auto-plotting
                    first = false;
                    PlotIndicator("SPY_Hull", HMA);
                    PlotIndicator("SPY_Signal", Channel.UpperBand, Channel.LowerBand, signal);
                }
                
                // Estimating the upper and lower channel band.
                // Is there a better way?
                decimal upperBand = decimal.MinValue;
                decimal lowerBand = decimal.MaxValue;
                for (int i = 0; i < Band.Count; i++)
                {
                    upperBand = Math.Max(Band[i], upperBand);
                    lowerBand = Math.Min(Band[i], lowerBand);
                }

                // Defining the signals
                bool longSignal = signal < lowerBand;
                bool shortSignal = signal > upperBand;

                // If we don't hold any position
                if (!Portfolio[symbol].HoldStock)
                {
                    if (longSignal) SetHoldings(symbol, 1);
                    if (shortSignal) SetHoldings(symbol, -1);
                }
                // If we have hold some position
                else
                {
                    if (Portfolio[symbol].IsLong && shortSignal) Liquidate(symbol);
                    if (Portfolio[symbol].IsShort && longSignal) Liquidate(symbol);
                }
                Band.Add(signal);   // Update the channel.
            }
            else Band.Add(signal);  // Update the channel window until is ready.
        }
    }
    
    public static class MoreIndicatorExtensions
    {
        public static IndicatorBase<IndicatorDataPoint> AsSimpleIndicator(this IndicatorBase<TradeBar> indicator)
        {
            return new AsSimpleIndicatorAdapter(indicator);
        }


        private sealed class AsSimpleIndicatorAdapter : IndicatorBase<IndicatorDataPoint>
        {
            private readonly IndicatorBase<TradeBar> _indicator;

            public AsSimpleIndicatorAdapter(IndicatorBase<TradeBar> indicator)
                : base(indicator.Name + "_tb_adapter")
            {
                _indicator = indicator;
            }

            public override bool IsReady
            {
                get { return _indicator.IsReady; }
            }

            protected override decimal ComputeNextValue(IndicatorDataPoint input)
            {
                _indicator.Update(new TradeBar
                {
                    Symbol = input.Symbol,
                    Time = input.Time,
                    EndTime = input.EndTime,
                    Value = input.Value,
                    Close = input.Value,
                    High = input.Value,
                    Low = input.Value,
                    Open = input.Value,
                    Period = input.EndTime - input.Time,
                    Volume = 0
                });

                return _indicator.Current.Value;
            }
        }
    }
}