Lean  $LEAN_TAG$
CommodityChannelIndex.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  /// Represents the traditional commodity channel index (CCI)
22  ///
23  /// CCI = (Typical Price - 20-period SMA of TP) / (.015 * Mean Deviation)
24  /// Typical Price (TP) = (High + Low + Close)/3
25  /// Constant = 0.015
26  ///
27  /// There are four steps to calculating the Mean Deviation, first, subtract
28  /// the most recent 20-period average of the typical price from each period's
29  /// typical price. Second, take the absolute values of these numbers. Third,
30  /// sum the absolute values. Fourth, divide by the total number of periods (20).
31  /// </summary>
33  {
34  /// <summary>
35  /// This constant is used to ensure that CCI values fall between +100 and -100, 70% to 80% of the time
36  /// </summary>
37  private const decimal K = 0.015m;
38 
39  /// <summary>
40  /// Gets the type of moving average
41  /// </summary>
43 
44  /// <summary>
45  /// Keep track of the simple moving average of the typical price
46  /// </summary>
48 
49  /// <summary>
50  /// Keep track of the mean absolute deviation of the typical price
51  /// </summary>
53 
54  /// <summary>
55  /// Initializes a new instance of the CommodityChannelIndex class
56  /// </summary>
57  /// <param name="period">The period of the standard deviation and moving average (middle band)</param>
58  /// <param name="movingAverageType">The type of moving average to be used</param>
59  public CommodityChannelIndex(int period, MovingAverageType movingAverageType = MovingAverageType.Simple)
60  : this($"CCI({period})", period, movingAverageType)
61  {
62  }
63 
64  /// <summary>
65  /// Initializes a new instance of the CommodityChannelIndex class
66  /// </summary>
67  /// <param name="name">The name of this indicator</param>
68  /// <param name="period">The period of the standard deviation and moving average (middle band)</param>
69  /// <param name="movingAverageType">The type of moving average to be used</param>
70  public CommodityChannelIndex(string name, int period, MovingAverageType movingAverageType = MovingAverageType.Simple)
71  : base(name)
72  {
73  WarmUpPeriod = period;
74  MovingAverageType = movingAverageType;
75  TypicalPriceAverage = movingAverageType.AsIndicator(name + "_TypicalPriceAvg", period);
76  TypicalPriceMeanDeviation = new MeanAbsoluteDeviation(name + "_TypicalPriceMAD", period);
77  }
78 
79  /// <summary>
80  /// Gets a flag indicating when this indicator is ready and fully initialized
81  /// </summary>
82  public override bool IsReady => TypicalPriceAverage.IsReady && TypicalPriceMeanDeviation.IsReady;
83 
84  /// <summary>
85  /// Required period, in data points, for the indicator to be ready and fully initialized.
86  /// </summary>
87  public int WarmUpPeriod { get; }
88 
89  /// <summary>
90  /// Computes the next value of this indicator from the given state
91  /// </summary>
92  /// <param name="input">The input given to the indicator</param>
93  /// <returns>A new value for this indicator</returns>
94  protected override decimal ComputeNextValue(IBaseDataBar input)
95  {
96  var typicalPrice = (input.High + input.Low + input.Close) / 3.0m;
97 
98  TypicalPriceAverage.Update(input.Time, typicalPrice);
99  TypicalPriceMeanDeviation.Update(input.Time, typicalPrice);
100 
101  // compare this to zero, since if the mean deviation is very small we can get
102  // precision errors due to non-floating point math
103  var weightedMeanDeviation = K * TypicalPriceMeanDeviation.Current.Value;
104  if (weightedMeanDeviation == 0.0m)
105  {
106  return 0.0m;
107  }
108 
109  return (typicalPrice - TypicalPriceAverage.Current.Value) / weightedMeanDeviation;
110  }
111 
112  /// <summary>
113  /// Resets this indicator to its initial state
114  /// </summary>
115  public override void Reset()
116  {
117  TypicalPriceAverage.Reset();
119  base.Reset();
120  }
121  }
122 }