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