Overall Statistics
Total Trades
137
Average Win
8.82%
Average Loss
-3.01%
Compounding Annual Return
11.893%
Drawdown
24.800%
Expectancy
0.389
Net Profit
125.836%
Sharpe Ratio
0.651
Loss Rate
65%
Win Rate
35%
Profit-Loss Ratio
2.93
Alpha
0.068
Beta
0.393
Annual Standard Deviation
0.161
Annual Variance
0.026
Information Ratio
0.061
Tracking Error
0.174
Treynor Ratio
0.267
Total Fees
$1522.77
using System;
using QuantConnect.Indicators;

namespace QuantConnect.Algorithm.CSharp
{
    public enum CrossingMovingAveragesSignals
    {
        Bullish = 1,
        FastCrossSlowFromAbove = -2,
        Bearish = -1,
        FastCrossSlowFromBelow = 2,
    }

    public class CrossingMovingAverages
    {
        CompositeIndicator<IndicatorDataPoint> _moving_average_difference;
        public CrossingMovingAveragesSignals Signal { get; private set; }
        private bool _isReady;
        int _lastSignal;


        public bool IsReady
        {
            get { return _isReady; }
        }


        public CrossingMovingAverages(IndicatorBase<IndicatorDataPoint> fast_moving_average, IndicatorBase<IndicatorDataPoint> slow_moving_average)
        {
            _moving_average_difference = fast_moving_average.Minus(slow_moving_average);
            _moving_average_difference.Updated += ma_Updated;
        }

        private void ma_Updated(object sender, IndicatorDataPoint updated)
        {
            if (!_isReady)
            {
                _isReady = _moving_average_difference.Right.IsReady;
                return;
            }
            var actualSignal = Math.Sign(_moving_average_difference);
            if (actualSignal == _lastSignal || _lastSignal == 0)
            {
                Signal = (CrossingMovingAveragesSignals)actualSignal;
            }
            else if (_lastSignal == -1 && actualSignal == 1)
            {
                Signal = CrossingMovingAveragesSignals.FastCrossSlowFromBelow;
            }
            else if (_lastSignal == 1 && actualSignal == -1)
            {
                Signal = CrossingMovingAveragesSignals.FastCrossSlowFromAbove;
            }

            _lastSignal = actualSignal;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Indicators;

namespace QuantConnect.Algorithm.CSharp
{
    public class HullMA:QCAlgorithm
    {
        private int hullMaPeriod = 4;
        private int slowEmaPeriod = 15;

        private ExponentialMovingAverage slowEma;
        private IndicatorBase<IndicatorDataPoint> hullMa;

        private CrossingMovingAverages MovingAverageCross;
        private Symbol symbol;

        public override void Initialize()
        {
            // Set the basic algorithm parameters.
            SetStartDate(2010, 01, 01);
            SetEndDate(2017, 03, 30);
            SetCash(100000);

            symbol = AddEquity("AAPL", Resolution.Daily).Symbol;

            // ==================================
            // Hull Moving Average implementation
            var slowLWMA = LWMA(symbol, (int) (hullMaPeriod * 1m / 2));
            var fastLWMA = LWMA(symbol, hullMaPeriod);
            var HMA = new LinearWeightedMovingAverage((int) Math.Sqrt(hullMaPeriod * 1d));
            hullMa = HMA.Of(fastLWMA.Times(2).Minus(slowLWMA));
            // ==================================

            slowEma = EMA(symbol, slowEmaPeriod);
            MovingAverageCross = new CrossingMovingAverages(hullMa, slowEma);
        }

        public override void OnData(Slice slice)
        {
            if (!slice.ContainsKey(symbol) || !MovingAverageCross.IsReady) return;
            var signal = MovingAverageCross.Signal;
            if (signal == CrossingMovingAveragesSignals.FastCrossSlowFromAbove
                || signal == CrossingMovingAveragesSignals.FastCrossSlowFromBelow)
            {
                if ((Portfolio[symbol].IsLong && signal == CrossingMovingAveragesSignals.FastCrossSlowFromAbove)
                    || (Portfolio[symbol].IsShort && signal == CrossingMovingAveragesSignals.FastCrossSlowFromBelow))
                {
                    Liquidate(symbol);
                }
                else if (!Portfolio[symbol].Invested)
                {

                    SetHoldings(symbol, 1*Math.Sign((int)signal));
                }

            }
        }

        public override void OnEndOfDay()
        {
            Plot("Hull Moving Average", "AAPL", Securities[symbol].Close);
            if (hullMa.IsReady) Plot("Hull Moving Average", "Hull Moving Average", hullMa.Current.Value);
            if (slowEma.IsReady) Plot("Hull Moving Average", "EMA", slowEma.Current.Value);
        }
    }
}