Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Hurst Bands

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Hurst Bands

    I am looking at implementing a new indicator based on the Cycle Envelopes from JM Hursts "The Magic of Stock Transaction Timing"
    In truth, the bands can be approximated fairly well by utilising the Keltner Channel with offsets. My current settings are:

    1st Band
    Offset Multiplier 1.5
    Period 10
    Displacement -5

    2nd Band
    Offset Multiplier 2.5
    Period 30
    Displacement -15

    This draws fairly nice channels, but lacks the smoothness of a hand drawn envelope and also does not allow for projection to the current bar. Generally, the projection would be drawn by hand and follow an average of the cycles timing. This is where I am at a loss as to how to code this...
    Has anybody tackled this so far?
    I have seen that Omnitrader have recently released a plug in for it, but I am not convinced. A nice looking set of tools has been developed for Esignal and the info can be found here:



    They point out that they are using double-smoothed averages for the envelopes with "linear projection" for the extension of the band to the current bar.

    I am not sure if there is already a double-smoothed average that I could use to modify the Keltner bands as a start? Really, the big quetion is how to extend the bands to now taking into account an average of the previous highs/lows for the period and following the already visible curve.

    Any ideas or advice would be great

    #2
    Hi yimbot,

    Thanks for your post, great book you reference there.

    There is a lot of stuff on the subject, because shifted back MA's look to sweet...what may work best for trading, is to code a shifted back MA and extrapolate using normal trendlines.

    Linear prediction is a great concept and you find lots of algorithms in Numerical Recipes and I think also Ehlers published some on that topic.

    I saw some people using Polynomial regression, too - but the noise can make it hard to justify the coding efforts.

    For another Keltner base, I would suggest looking into the Triangular MA in NinjaTrader - http://www.ninjatrader-support.com/H...ngularTMA.html
    BertrandNinjaTrader Customer Service

    Comment


      #3
      Originally posted by NinjaTrader_Bertrand View Post

      For another Keltner base, I would suggest looking into the Triangular MA in NinjaTrader - http://www.ninjatrader-support.com/H...ngularTMA.html
      Thanks Bertrand,

      I set up the code to use the TMA and it is a beautiful thing - thanks for the tip!

      To date, I have as you suggest just been using parallel trend lines for the projections and the fibonacci time tool set to multiples of 100% to try and get an average of the time cycles with. Obviously if I can project it with the indicator it would be much nicer, but am honestly way out of my depth.

      Thanks again.

      Comment


        #4
        For anyone following this thread who may be interested in the code, here it is:
        (Please forgive my poor modification of the original NT code - very lazy)

        //
        // Copyright (C) 2006, NinjaTrader LLC <www.ninjatrader.com>.
        // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
        //

        #region Using declarations
        using System;
        using System.Diagnostics;
        using System.Drawing;
        using System.Drawing.Drawing2D;
        using System.ComponentModel;
        using System.Xml.Serialization;
        using NinjaTrader.Data;
        using NinjaTrader.Gui.Chart;
        #endregion

        // This namespace holds all indicators and is required. Do not change it.
        namespace NinjaTrader.Indicator
        {
        /// <summary>
        ///
        /// </summary>
        [Description("The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.")]
        public class HurstEnvelope : Indicator
        {
        #region Variables
        private int period = 10;
        private double offsetMultiplier = 1.5;
        private DataSeries diff;
        #endregion

        /// <summary>
        /// This method is used to configure the indicator and is called once before any bar data is loaded.
        /// </summary>
        protected override void Initialize()
        {
        Add(new Plot(Color.Transparent, "Midline"));
        Add(new Plot(Color.Gray, "Upper"));
        Add(new Plot(Color.Gray, "Lower"));

        diff = new DataSeries(this);

        Overlay = true;
        PriceTypeSupported = false;
        }

        /// <summary>
        /// Called on each bar update event (incoming tick).
        /// </summary>
        protected override void OnBarUpdate()
        {
        diff.Set(High[0] - Low[0]);

        double middle = TMA(Median, Period)[0];
        double offset = TMA(diff, Period)[0] * offsetMultiplier;

        double upper = middle + offset;
        double lower = middle - offset;

        Midline.Set(middle);
        Upper.Set(upper);
        Lower.Set(lower);
        }

        #region Properties
        /// <summary>
        /// </summary>
        [Description("Numbers of bars used for calculations")]
        [Category("Parameters")]
        public int Period
        {
        get { return period; }
        set { period = Math.Max(1, value); }
        }

        /// <summary>
        /// </summary>
        [Description("How much to expand the upper and lower band from the normal offset")]
        [Category("Parameters")]
        [Gui.Design.DisplayNameAttribute("Offset multiplier")]
        public double OffsetMultiplier
        {
        get { return offsetMultiplier; }
        set { offsetMultiplier = Math.Max(0.01, value); }
        }

        /// <summary>
        /// </summary>
        [Browsable(false)]
        [XmlIgnore()]
        public DataSeries Midline
        {
        get { return Values[0]; }
        }

        /// <summary>
        /// </summary>
        [Browsable(false)]
        [XmlIgnore()]
        public DataSeries Upper
        {
        get { return Values[1]; }
        }

        /// <summary>
        /// </summary>
        [Browsable(false)]
        [XmlIgnore()]
        public DataSeries Lower
        {
        get { return Values[2]; }
        }
        #endregion
        }
        }

        #region NinjaScript generated code. Neither change nor remove.
        // This namespace holds all indicators and is required. Do not change it.
        namespace NinjaTrader.Indicator
        {
        public partial class Indicator : IndicatorBase
        {
        private HurstEnvelope[] cacheHurstEnvelope = null;

        private static HurstEnvelope checkHurstEnvelope = new HurstEnvelope();

        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        public HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
        {
        return HurstEnvelope(Input, offsetMultiplier, period);
        }

        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        public HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
        {
        checkHurstEnvelope.OffsetMultiplier = offsetMultiplier;
        offsetMultiplier = checkHurstEnvelope.OffsetMultiplier;
        checkHurstEnvelope.Period = period;
        period = checkHurstEnvelope.Period;

        if (cacheHurstEnvelope != null)
        for (int idx = 0; idx < cacheHurstEnvelope.Length; idx++)
        if (Math.Abs(cacheHurstEnvelope[idx].OffsetMultiplier - offsetMultiplier) <= double.Epsilon && cacheHurstEnvelope[idx].Period == period && cacheHurstEnvelope[idx].EqualsInput(input))
        return cacheHurstEnvelope[idx];

        HurstEnvelope indicator = new HurstEnvelope();
        indicator.BarsRequired = BarsRequired;
        indicator.CalculateOnBarClose = CalculateOnBarClose;
        indicator.Input = input;
        indicator.OffsetMultiplier = offsetMultiplier;
        indicator.Period = period;
        indicator.SetUp();

        HurstEnvelope[] tmp = new HurstEnvelope[cacheHurstEnvelope == null ? 1 : cacheHurstEnvelope.Length + 1];
        if (cacheHurstEnvelope != null)
        cacheHurstEnvelope.CopyTo(tmp, 0);
        tmp[tmp.Length - 1] = indicator;
        cacheHurstEnvelope = tmp;
        Indicators.Add(indicator);

        return indicator;
        }

        }
        }

        // This namespace holds all market analyzer column definitions and is required. Do not change it.
        namespace NinjaTrader.MarketAnalyzer
        {
        public partial class Column : ColumnBase
        {
        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        [Gui.Design.WizardCondition("Indicator")]
        public Indicator.HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
        {
        return _indicator.HurstEnvelope(Input, offsetMultiplier, period);
        }

        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        public Indicator.HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
        {
        return _indicator.HurstEnvelope(input, offsetMultiplier, period);
        }

        }
        }

        // This namespace holds all strategies and is required. Do not change it.
        namespace NinjaTrader.Strategy
        {
        public partial class Strategy : StrategyBase
        {
        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        [Gui.Design.WizardCondition("Indicator")]
        public Indicator.HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
        {
        return _indicator.HurstEnvelope(Input, offsetMultiplier, period);
        }

        /// <summary>
        /// The Hurst Envelope is a similar indicator to Bollinger Bands. Here the midline is a standard moving average with the upper and lower bands offset by the SMA of the difference between the high and low of the previous bars. The offset multiplier as well as the SMA period is configurable.
        /// </summary>
        /// <returns></returns>
        public Indicator.HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
        {
        if (InInitialize && input == null)
        throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");

        return _indicator.HurstEnvelope(input, offsetMultiplier, period);
        }

        }
        }
        #endregion
        Attached Files

        Comment


          #5
          Thanks for the code and the screenshot, I feel our forum members will appreciate input on this interesting techniques.
          BertrandNinjaTrader Customer Service

          Comment


            #6
            Here is a compiled version of the code posted below.
            Attached Files

            Comment


              #7
              I wonder if someone may assist with a coding error here.
              My aim is to draw a line between the current value of the displaced Hurst Envelope and the current value of a non-displaced Keltner Channel which is half the period of the Hurst Envelope but the same Offset multiplier.

              So to clarify, at the end of the code for the Hurst Indicator above, I want to just draw a straight line between:
              a) the current value of HurstEnvelope(Offset, Period, Displacement)
              b) the current value of KeltnerChannel(Offset, (Period/2), no Displacement)

              The code I have is as follows which compiles ok, but plots nothing at all. If I comment out the DrawLine Lines of code, the indicator once again displays. So I am not sure where the error is. All comments appreciated.



              //
              //

              #region Using declarations
              using System;
              using System.Diagnostics;
              using System.Drawing;
              using System.Drawing.Drawing2D;
              using System.ComponentModel;
              using System.Xml.Serialization;
              using NinjaTrader.Data;
              using NinjaTrader.Gui.Chart;
              #endregion

              // This namespace holds all indicators and is required. Do not change it.
              namespace NinjaTrader.Indicator
              {
              /// <summary>
              ///
              /// </summary>
              [Description("The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'")]
              public class HurstEnvelope : Indicator
              {
              #region Variables
              private int period = 10;
              private double offsetMultiplier = 1.5;
              private DataSeries diff;
              #endregion

              /// <summary>
              /// This method is used to configure the indicator and is called once before any bar data is loaded.
              /// </summary>
              protected override void Initialize()
              {
              Add(new Plot(Color.Transparent, "Midline"));
              Add(new Plot(Color.Gray, "Upper"));
              Add(new Plot(Color.Gray, "Lower"));

              diff = new DataSeries(this);

              Overlay = true;
              PriceTypeSupported = false;
              }

              /// <summary>
              /// Called on each bar update event (incoming tick).
              /// </summary>
              protected override void OnBarUpdate()
              {
              diff.Set(High[0] - Low[0]);

              double middle = TMA(Median, Period)[0];
              double offset = TMA(diff, Period)[0] * offsetMultiplier;

              double upper = middle + offset;
              double lower = middle - offset;

              KeltnerChannel env = KeltnerChannel(Median, offsetMultiplier, (period/2));


              Midline.Set(middle);
              Upper.Set(upper);
              Lower.Set(lower);


              ///DrawLine(CurrentBar.ToString()+"UPPER", true, (period/2), upper, 0, env.Upper[0], Color.Cyan, DashStyle.Dot, 1);
              ///DrawLine(CurrentBar.ToString()+"LOWER", true, (period/2), lower, 0, env.Lower[0], Color.Cyan, DashStyle.Dot, 1);

              }

              #region Properties
              /// <summary>
              /// </summary>
              [Description("Numbers of bars used for calculations")]
              [Category("Parameters")]
              public int Period
              {
              get { return period; }
              set { period = Math.Max(1, value); }
              }

              /// <summary>
              /// </summary>
              [Description("How much to expand the upper and lower band from the normal offset")]
              [Category("Parameters")]
              [Gui.Design.DisplayNameAttribute("Offset multiplier")]
              public double OffsetMultiplier
              {
              get { return offsetMultiplier; }
              set { offsetMultiplier = Math.Max(0.01, value); }
              }

              /// <summary>
              /// </summary>
              [Browsable(false)]
              [XmlIgnore()]
              public DataSeries Midline
              {
              get { return Values[0]; }
              }

              /// <summary>
              /// </summary>
              [Browsable(false)]
              [XmlIgnore()]
              public DataSeries Upper
              {
              get { return Values[1]; }
              }

              /// <summary>
              /// </summary>
              [Browsable(false)]
              [XmlIgnore()]
              public DataSeries Lower
              {
              get { return Values[2]; }
              }
              #endregion
              }
              }

              #region NinjaScript generated code. Neither change nor remove.
              // This namespace holds all indicators and is required. Do not change it.
              namespace NinjaTrader.Indicator
              {
              public partial class Indicator : IndicatorBase
              {
              private HurstEnvelope[] cacheHurstEnvelope = null;

              private static HurstEnvelope checkHurstEnvelope = new HurstEnvelope();

              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              public HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
              {
              return HurstEnvelope(Input, offsetMultiplier, period);
              }

              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              public HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
              {
              checkHurstEnvelope.OffsetMultiplier = offsetMultiplier;
              offsetMultiplier = checkHurstEnvelope.OffsetMultiplier;
              checkHurstEnvelope.Period = period;
              period = checkHurstEnvelope.Period;

              if (cacheHurstEnvelope != null)
              for (int idx = 0; idx < cacheHurstEnvelope.Length; idx++)
              if (Math.Abs(cacheHurstEnvelope[idx].OffsetMultiplier - offsetMultiplier) <= double.Epsilon && cacheHurstEnvelope[idx].Period == period && cacheHurstEnvelope[idx].EqualsInput(input))
              return cacheHurstEnvelope[idx];

              HurstEnvelope indicator = new HurstEnvelope();
              indicator.BarsRequired = BarsRequired;
              indicator.CalculateOnBarClose = CalculateOnBarClose;
              indicator.Input = input;
              indicator.OffsetMultiplier = offsetMultiplier;
              indicator.Period = period;
              indicator.SetUp();

              HurstEnvelope[] tmp = new HurstEnvelope[cacheHurstEnvelope == null ? 1 : cacheHurstEnvelope.Length + 1];
              if (cacheHurstEnvelope != null)
              cacheHurstEnvelope.CopyTo(tmp, 0);
              tmp[tmp.Length - 1] = indicator;
              cacheHurstEnvelope = tmp;
              Indicators.Add(indicator);

              return indicator;
              }

              }
              }

              // This namespace holds all market analyzer column definitions and is required. Do not change it.
              namespace NinjaTrader.MarketAnalyzer
              {
              public partial class Column : ColumnBase
              {
              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              [Gui.Design.WizardCondition("Indicator")]
              public Indicator.HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
              {
              return _indicator.HurstEnvelope(Input, offsetMultiplier, period);
              }

              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              public Indicator.HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
              {
              return _indicator.HurstEnvelope(input, offsetMultiplier, period);
              }

              }
              }

              // This namespace holds all strategies and is required. Do not change it.
              namespace NinjaTrader.Strategy
              {
              public partial class Strategy : StrategyBase
              {
              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              [Gui.Design.WizardCondition("Indicator")]
              public Indicator.HurstEnvelope HurstEnvelope(double offsetMultiplier, int period)
              {
              return _indicator.HurstEnvelope(Input, offsetMultiplier, period);
              }

              /// <summary>
              /// The Hurst Envelope is described in J.M Hursts 'The Profit Magic of Stock Transaction Timing'
              /// </summary>
              /// <returns></returns>
              public Indicator.HurstEnvelope HurstEnvelope(Data.IDataSeries input, double offsetMultiplier, int period)
              {
              if (InInitialize && input == null)
              throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");

              return _indicator.HurstEnvelope(input, offsetMultiplier, period);
              }

              }
              }
              #endregion
              Last edited by yimbot; 12-11-2008, 06:23 AM.

              Comment


                #8
                Hi yimbot,

                Please add this check at the start of your OnBarUpdate() -

                Code:
                [SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]if[/COLOR][/SIZE][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][SIZE=2] (CurrentBar < Period)
                [/SIZE][/SIZE][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff][SIZE=2][COLOR=#0000ff]return[/COLOR][/SIZE][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2][SIZE=2];[/SIZE][/SIZE]
                [SIZE=2][SIZE=2][/SIZE][/SIZE]


                This should work then, also please see this tip - http://www.ninjatrader-support2.com/...ead.php?t=3170
                BertrandNinjaTrader Customer Service

                Comment


                  #9
                  Originally posted by yimbot View Post
                  I wonder if someone may assist with a coding error here.
                  My aim is to draw a line between the current value of the displaced Hurst Envelope and the current value of a non-displaced Keltner Channel which is half the period of the Hurst Envelope but the same Offset multiplier.

                  So to clarify, at the end of the code for the Hurst Indicator above, I want to just draw a straight line between:
                  a) the current value of HurstEnvelope(Offset, Period, Displacement)
                  b) the current value of KeltnerChannel(Offset, (Period/2), no Displacement)
                  Alternatively, even just drawing a ray from the HurstEnvelope 1 bar ago through the current HurstEnvelope that projects into the future (preferably only as far as the current bar) would still be useful and dynamic. This may be easier to code...

                  Comment


                    #10
                    Thanks once again for your help Bertrand. That worked nicely

                    The indicator now has some level of projection and although not very sophisticated, it does provide some level of assistance.

                    I have attached this code for anyone interested.
                    Attached Files

                    Comment


                      #11
                      You are welcome yimbot, great it works!
                      BertrandNinjaTrader Customer Service

                      Comment


                        #12
                        Here is a screenshot on the 5min Euro with the indicator displayed, also shows a couple of trades taken...
                        Attached Files

                        Comment


                          #13
                          Got the following exception while trying to import the indicator, any ideas?

                          Thanks
                          Attached Files

                          Comment


                            #14
                            Hi ryker,
                            Which NinjaTrader version are you using? The .ntns format is not supported anymore, make sure you are on NinjaTrader 6.5.1000.8 (check under Help > About)
                            BertrandNinjaTrader Customer Service

                            Comment


                              #15
                              Right, I'm using .7, I'll update my NT and see if it works afterwards.

                              Thanks

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by bmartz, 03-12-2024, 06:12 AM
                              4 responses
                              31 views
                              0 likes
                              Last Post bmartz
                              by bmartz
                               
                              Started by Aviram Y, Today, 05:29 AM
                              4 responses
                              12 views
                              0 likes
                              Last Post Aviram Y  
                              Started by algospoke, 04-17-2024, 06:40 PM
                              3 responses
                              28 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Started by gentlebenthebear, Today, 01:30 AM
                              1 response
                              8 views
                              0 likes
                              Last Post NinjaTrader_Jesse  
                              Started by cls71, Today, 04:45 AM
                              1 response
                              7 views
                              0 likes
                              Last Post NinjaTrader_ChelseaB  
                              Working...
                              X