Lean  $LEAN_TAG$
KeltnerChannels.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
17 
19 {
20  /// <summary>
21  /// This indicator creates a moving average (middle band) with an upper band and lower band
22  /// fixed at k average true range multiples away from the middle band.
23  /// </summary>
25  {
26  /// <summary>
27  /// Gets the middle band of the channel
28  /// </summary>
30 
31  /// <summary>
32  /// Gets the upper band of the channel
33  /// </summary>
35 
36  /// <summary>
37  /// Gets the lower band of the channel
38  /// </summary>
40 
41  /// <summary>
42  /// Gets the average true range
43  /// </summary>
45 
46 
47  /// <summary>
48  /// Initializes a new instance of the KeltnerChannels class
49  /// </summary>
50  /// <param name="period">The period of the average true range and moving average (middle band)</param>
51  /// <param name="k">The number of multiplies specifying the distance between the middle band and upper or lower bands</param>
52  /// <param name="movingAverageType">The type of moving average to be used</param>
53  public KeltnerChannels(int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
54  : this($"KC({period},{k})", period, k, movingAverageType)
55  {
56  }
57 
58  /// <summary>
59  /// Initializes a new instance of the KeltnerChannels class
60  /// </summary>
61  /// <param name="name">The name of this indicator</param>
62  /// <param name="period">The period of the average true range and moving average (middle band)</param>
63  /// <param name="k">The number of multiples specifying the distance between the middle band and upper or lower bands</param>
64  /// <param name="movingAverageType">The type of moving average to be used</param>
65  public KeltnerChannels(string name, int period, decimal k, MovingAverageType movingAverageType = MovingAverageType.Simple)
66  : base(name)
67  {
68  WarmUpPeriod = period;
69 
70  //Initialise ATR and SMA
71  AverageTrueRange = new AverageTrueRange(name + "_AverageTrueRange", period, MovingAverageType.Simple);
72  MiddleBand = movingAverageType.AsIndicator(name + "_MiddleBand", period);
73 
74  //Compute Lower Band
75  LowerBand = new FunctionalIndicator<IBaseDataBar>(name + "_LowerBand",
76  input => MiddleBand.IsReady ? MiddleBand.Current.Value - AverageTrueRange.Current.Value * k : decimal.Zero,
77  lowerBand => MiddleBand.IsReady,
78  () => MiddleBand.Reset()
79  );
80 
81  //Compute Upper Band
82  UpperBand = new FunctionalIndicator<IBaseDataBar>(name + "_UpperBand",
83  input => MiddleBand.IsReady ? MiddleBand.Current.Value + AverageTrueRange.Current.Value * k : decimal.Zero,
84  upperBand => MiddleBand.IsReady,
85  () => MiddleBand.Reset()
86  );
87  }
88 
89  /// <summary>
90  /// Gets a flag indicating when this indicator is ready and fully initialized
91  /// </summary>
92  public override bool IsReady => MiddleBand.IsReady && UpperBand.IsReady && LowerBand.IsReady && AverageTrueRange.IsReady;
93 
94  /// <summary>
95  /// Required period, in data points, for the indicator to be ready and fully initialized.
96  /// </summary>
97  public int WarmUpPeriod { get; }
98 
99  /// <summary>
100  /// Resets this indicator to its initial state
101  /// </summary>
102  public override void Reset()
103  {
105  MiddleBand.Reset();
106  UpperBand.Reset();
107  LowerBand.Reset();
108  base.Reset();
109  }
110 
111  /// <summary>
112  /// Computes the next value for this indicator from the given state.
113  /// </summary>
114  /// <param name="input">The TradeBar to this indicator on this time step</param>
115  /// <returns>A new value for this indicator</returns>
116  protected override decimal ComputeNextValue(IBaseDataBar input)
117  {
118  AverageTrueRange.Update(input);
119 
120  var typicalPrice = (input.High + input.Low + input.Close) / 3m;
121  MiddleBand.Update(input.EndTime, typicalPrice);
122 
123  // poke the upper/lower bands, they actually don't use the input, they compute
124  // based on the ATR and the middle band
125  LowerBand.Update(input);
126  UpperBand.Update(input);
127  return MiddleBand.Current.Value;
128  }
129  }
130 }