Back

Hull Moving Average implementation

Hi gang,
I want to share with you this implementation of the Hull Moving Average. This MA is a LWMA of a LWMA difference.
[tex]HMA(n) = LWMA( 2 LWMA(\frac{n^{2}}{2}) - LWMA(n^{2}))[/tex]
I ended up making an indicator because I couldn’t make the composite indicators works. I tried something like:
LinearWeightedMovingAverage slowLWMA;
slowLWMA = LWMA(symbol, slowLWMAPeriod, resolution);
LinearWeightedMovingAverage fastLWMA;
fastLWMA = LWMA(symbol, fastLWMAPeriod, resolution);
LinearWeightedMovingAverage HMA = new LinearWeightedMovingAverage(HMAPeriod);
var hma = HMA.Of(fastLWMA.Times(2).Minus(slowLWMA));

Plus tons of variants until I decided to try it making it as an indicator. And, in the indicator file, I ended up making a method for the LWMA (Yeah, seems silly I know. Now @MichelH will teach us how to make the whole thing in two lines of code).
Finally with this basic strategy, I couldn’t apply a Donchian channel for a composite indicator.
But, at least, works :)
Cheers, JJ
Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



Hey @Juan!

The code you tried will work on the next deploy we do. I meant to add that feature long ago. As it stands currently, the Times (and Add, Minus, Over) functions require an indicator as input, so the value of '2' doesn't work. I'm going to add overloads today to accepts decimal values.

Here's a snippet that does work, and I've attached the updated code with the snippet :) int slow = (int) Math.Pow(period, 2);
int fast = slow/2;

// create our two 'source' indicators that feed into the hull moving average
var slowLwma = LWMA("SPY", slow);
var fastLwma = LWMA("SPY", fast);
// create an indicator that is twice the 'fastLwma' -- I'll add code to remove the
// need to specify the ConstantIndicator noise, so in the future you'll be able to say
// fastLwma.Times(2); :)
var twiceFast = fastLwma.Times(new ConstantIndicator("2", 2));
var interior = twiceFast.Minus(slowLwma);
// take the LWMA of all the other stuff
HMA = new LinearWeightedMovingAverage(period).Of(interior);


Another way to do this is through the usage of the FunctionalIndicator. The FunctionalIndicator uses functions as inputs, so it's a little more advanced. Here's some references for reading up on anonymous functions/lambda expressions in C#, any questions feel free to ask me!
https://msdn.microsoft.com/en-us/library/bb397687.aspx
https://en.wikipedia.org/wiki/Anonymous_function#C.23
http://www.codeproject.com/Tips/298963/Understand-Lambda-Expressions-in-minutes

Interestingly I got different results than your implementation of the HullMovingAverage. Is there an external data source we can compare results with? We can add the HullMovingAverage to the LEAN engine and I can write some tests against it to verify the implementation is correct :) If you can find an external data source for verification, please write up an issue here to add the HullMovingAverage.

As for the reason why channel.Of(signal) doesn't work is because the donchian channels require a trade bar input, but the 'signal' outputs an indicator data point. Maybe what we need is a way to input indicator data points as flat trade bars (OHLC = IndicatorDatePoint.Value). I've added an extension method at the bottom of main which will take an IndicatorBase and return an IndicatorBase, it basically just maps an indicator data points into OHLC so it can be consumed by the Donchian Channels. Not the prettiest but it gets the job done :)

As always Juan, thanks for sharing!!
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Michael,
The Lean engine is big and there is so much to know, thank you for being such a good guide!
Try changing Resolution resolution = Resolution.Daily; to Minute and the results get closer. However there are differences, your implementation is better!!
So, most of the difference between your backtest and the mine is because a last second change when sharing (copying from VS and pasting in the platform)... however I attached the last backtest of the last version to the post IDK why the difference.
Sorry for my newbiness but, Can simulated data be used as an external data source we can compare the results with?
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Juan,

We can use simulated data. We've done things manually in excel, but if possible I prefer to find some other established source, maybe a paper with some sample calculations, as a way of verifying the implementation.

I tried briefly searching and wasn't able to find a data table of values, so we can just make one using excel or something similar.

And yes, I changed it to Daily to check out some plots :) Forgot to change it back, looks much closer now, thanks!
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Juan Thanks for the Hull Moving Average. Very useful indicator!
0

Thanks @Gene! You're welcome!
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


I love zero lag indicators. Here is my implementation of the HMA using LWMA

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;

namespace QuantConnect.Indicators
{
///
/// Produces a Hull Moving Average as explained at http://www.alanhull.com/hull-moving-average/
/// and derived from the instructions for the Excel VBA code at http://finance4traders.blogspot.com/2009/06/how-to-calculate-hull-moving-average.html
///
public class HullMovingAverage : WindowIndicator
{
private readonly LinearWeightedMovingAverage _longWma;
private readonly LinearWeightedMovingAverage _shortWma;
private readonly RollingWindow _smooth;
private readonly LinearWeightedMovingAverage _result;
// The length of the smoothed window
// square root of period rounded to the nearest whole number

///
/// A Hull Moving Average
///
/// string - a name for the indicator
/// int - the number of periods over which to calculate the HMA - the length of the longWMA
public HullMovingAverage(string name, int period)
: base(name, period)
{
// Creates the long LWMA for the number of periods specified in the constuctor
_longWma = new LinearWeightedMovingAverage("Long", period);

// Creates the short LWMA for half the period rounded to the nearest whole number
_shortWma = new LinearWeightedMovingAverage("Short", System.Convert.ToInt32(Math.Round((double)period / 2)));

// Creates the smoother data set to which the resulting wma is applied
_smooth = new RollingWindow(period);

// number of historical periods to look at in the resulting WMA
int k = System.Convert.ToInt32((Math.Round(Math.Sqrt(period))));

// Creates the LWMA for the output. This step probably could have been skipped
_result = new LinearWeightedMovingAverage("Result", k);

}
///
/// A Hull Moving Average with the default name
///
/// int - the number of periods over which to calculate the HMA - the length of the longWMA
public HullMovingAverage(int period)
: this("HMA" + period, period)
{
}

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

///
/// Computes the next value for this indicator from the given state.
///
/// The window of data held in this indicator
/// The input value to this indicator on this time step ///
///
/// The Hull moving average is a series of nested weighted moving averages.
/// Using the LWMA custom function for calculating weighted moving averages,
/// the Hull moving average can be calculated following the steps.
///
///1.Calculate the n periodweighted moving average of a series "=WMA(price for n periods)"
///2.Calculate the n/2 period weighted moving average of a series"=WMA(price for n/2 periods)". Round n/2 to the nearest whole number
///3.Create a time series with 2*WMA from Step 2 - WMA from Step 1
///4.The HMA is the WMA of the series in Step 3. "=WMA(Step 3 outputs fo k period)"
///
protected override decimal ComputeNextValue(IReadOnlyWindow window, IndicatorDataPoint input)
{
_longWma.Update(input);
_shortWma.Update(input);
//if (!_longWma.IsReady)
// _smooth.Add(new IndicatorDataPoint(input.Time, 2 * input.Value - input.Value));
//else
_smooth.Add(new IndicatorDataPoint(input.Time, 2 * _shortWma.Current.Value - _longWma.Current.Value));
_result.Update(new IndicatorDataPoint(input.Time, _smooth[0].Value));
return _result.Current.Value;
}
}
}
2

I love zero lag indicators. Here is my implementation of the HMA using LWMA

/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;

namespace QuantConnect.Indicators
{
///
/// Produces a Hull Moving Average as explained at http://www.alanhull.com/hull-moving-average/
/// and derived from the instructions for the Excel VBA code at http://finance4traders.blogspot.com/2009/06/how-to-calculate-hull-moving-average.html
///
public class HullMovingAverage : WindowIndicator
{
private readonly LinearWeightedMovingAverage _longWma;
private readonly LinearWeightedMovingAverage _shortWma;
private readonly RollingWindow _smooth;
private readonly LinearWeightedMovingAverage _result;
// The length of the smoothed window
// square root of period rounded to the nearest whole number

///
/// A Hull Moving Average
///
/// string - a name for the indicator
/// int - the number of periods over which to calculate the HMA - the length of the longWMA
public HullMovingAverage(string name, int period)
: base(name, period)
{
// Creates the long LWMA for the number of periods specified in the constuctor
_longWma = new LinearWeightedMovingAverage("Long", period);

// Creates the short LWMA for half the period rounded to the nearest whole number
_shortWma = new LinearWeightedMovingAverage("Short", System.Convert.ToInt32(Math.Round((double)period / 2)));

// Creates the smoother data set to which the resulting wma is applied
_smooth = new RollingWindow(period);

// number of historical periods to look at in the resulting WMA
int k = System.Convert.ToInt32((Math.Round(Math.Sqrt(period))));

// Creates the LWMA for the output. This step probably could have been skipped
_result = new LinearWeightedMovingAverage("Result", k);

}
///
/// A Hull Moving Average with the default name
///
/// int - the number of periods over which to calculate the HMA - the length of the longWMA
public HullMovingAverage(int period)
: this("HMA" + period, period)
{
}

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

///
/// Computes the next value for this indicator from the given state.
///
/// The window of data held in this indicator
/// The input value to this indicator on this time step ///
///
/// The Hull moving average is a series of nested weighted moving averages.
/// Using the LWMA custom function for calculating weighted moving averages,
/// the Hull moving average can be calculated following the steps.
///
///1.Calculate the n periodweighted moving average of a series "=WMA(price for n periods)"
///2.Calculate the n/2 period weighted moving average of a series"=WMA(price for n/2 periods)". Round n/2 to the nearest whole number
///3.Create a time series with 2*WMA from Step 2 - WMA from Step 1
///4.The HMA is the WMA of the series in Step 3. "=WMA(Step 3 outputs fo k period)"
///
protected override decimal ComputeNextValue(IReadOnlyWindow window, IndicatorDataPoint input)
{
_longWma.Update(input);
_shortWma.Update(input);
//if (!_longWma.IsReady)
// _smooth.Add(new IndicatorDataPoint(input.Time, 2 * input.Value - input.Value));
//else
_smooth.Add(new IndicatorDataPoint(input.Time, 2 * _shortWma.Current.Value - _longWma.Current.Value));
_result.Update(new IndicatorDataPoint(input.Time, _smooth[0].Value));
return _result.Current.Value;
}
}
}
1

Hey @Nicholas, nicely done!
Far better implementation than the mine, thanks for sharing.
Cheers, JJ
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@JJ Please feel free to mess with it. If you want to write tests and submit a PR go ahead. The source is in my development repo called LeanWMA at http://github.com/bizcad/LeanWMA .

(The name is left over from when I was developing the LinearWMA indicator.)

I also have an algo that tests my version of the Hull. They are in a subdirectory called MyAlgorithms and MyIndicators under the respective folders. I put my in-development work in those folders so I can just overwrite the rest of the solution with the latest version of Lean and not lose my work. I did not want to fork Lean for my crazy ideas.

I also wrote a custom Logging class that logs data in the my algos to a mylog.csv file in the build directory. I use it for sending intermediate variable data to a csv file. I find it useful for looking at the stream of bars and the output from various indicators and formulas in my algos.

Again feel free to use my code. It is all some open licence, without warranty and subject to change at my whim.
2

@Nicholas, thanks for sharing!
I saw your logging class and is very similar to what I done to debug some algorithms.
I like indicators too, so I'll try the sine trend for sure!
Cheers, JJ
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


JJ sine trend is not giving me good results. It is still a WIP. I am stoked that I am getting a positive return with the Instantaneous Trend Algorithm. I have only run it once or twice but it is my first profitable back test.

Again I have to warn you about the Sine. It is not right somehow.
0

Ok, thanks for the advice @Nicholas. I'll try it anyway, I like to meet the indicators and get a sense of how they works.
Can I ask what kind of instantaneous trend are you testing?
These days I'm working with some stoploss stuff, but after that I'll try to implement MAMA. If is the same indicator, maybe we can work as a team in the development.
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


The instantaneous trend is Ehlers (of MAMA fame) from Cybernetic Analysis for Stocks and Futures. MAMA is from his earlier work Rocket Science for Traders. The Sine Wave is in both books, but the implementation is different.

After a couple of attempts, I have not had much luck with the InPhase/Quadature and Homodyme Discriminator yet. I decided to go back an get solid on the more basic indicators: CyberCycle (the inverse of the InstantTrend), CenterGravity and RVI.

It is nice to find a kindred spirit. I might be interested in teaming up. nick@bizcad.com
2

Great!
I sent you a mail.
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed