Lean  $LEAN_TAG$
MovingAverageConvergenceDivergence.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 using System;
16 
18 {
19  /// <summary>
20  /// This indicator creates two moving averages defined on a base indicator and produces the difference
21  /// between the fast and slow averages.
22  /// </summary>
24  {
25  /// <summary>
26  /// Gets the fast average indicator
27  /// </summary>
29 
30  /// <summary>
31  /// Gets the slow average indicator
32  /// </summary>
34 
35  /// <summary>
36  /// Gets the signal of the MACD
37  /// </summary>
39 
40  /// <summary>
41  /// Developed by Thomas Aspray in 1986, the MACD-Histogram measures the distance between MACD and its signal line,
42  /// is an oscillator that fluctuates above and below the zero line.
43  /// Bullish or bearish divergences in the MACD-Histogram can alert chartists to an imminent signal line crossover in MACD.
44  /// </summary>
46 
47  /// <summary>
48  /// Gets a flag indicating when this indicator is ready and fully initialized
49  /// </summary>
50  public override bool IsReady => Signal.IsReady;
51 
52  /// <summary>
53  /// Required period, in data points, for the indicator to be ready and fully initialized.
54  /// </summary>
55  public int WarmUpPeriod { get; }
56 
57  /// <summary>
58  /// Creates a new MACD with the specified parameters
59  /// </summary>
60  /// <param name="fastPeriod">The fast moving average period</param>
61  /// <param name="slowPeriod">The slow moving average period</param>
62  /// <param name="signalPeriod">The signal period</param>
63  /// <param name="type">The type of moving averages to use</param>
64  public MovingAverageConvergenceDivergence(int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential)
65  : this($"MACD({fastPeriod},{slowPeriod},{signalPeriod})", fastPeriod, slowPeriod, signalPeriod, type)
66  {
67  }
68 
69  /// <summary>
70  /// Creates a new MACD with the specified parameters
71  /// </summary>
72  /// <param name="name">The name of this indicator</param>
73  /// <param name="fastPeriod">The fast moving average period</param>
74  /// <param name="slowPeriod">The slow moving average period</param>
75  /// <param name="signalPeriod">The signal period</param>
76  /// <param name="type">The type of moving averages to use</param>
77  public MovingAverageConvergenceDivergence(string name, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType type = MovingAverageType.Exponential)
78  : base(name)
79  {
80  if (fastPeriod >= slowPeriod)
81  {
82  throw new ArgumentException("MovingAverageConvergenceDivergence: fastPeriod must be less than slowPeriod", $"{nameof(fastPeriod)}, {nameof(slowPeriod)}");
83  }
84 
85  Fast = type.AsIndicator(name + "_Fast", fastPeriod);
86  Slow = type.AsIndicator(name + "_Slow", slowPeriod);
87  Signal = type.AsIndicator(name + "_Signal", signalPeriod);
88  Histogram = new Identity(name + "_Histogram");
89  WarmUpPeriod = slowPeriod + signalPeriod - 1;
90  }
91 
92  /// <summary>
93  /// Computes the next value of this indicator from the given state
94  /// </summary>
95  /// <param name="input">The input given to the indicator</param>
96  /// <returns>A new value for this indicator</returns>
97  protected override decimal ComputeNextValue(IndicatorDataPoint input)
98  {
99  var fastReady = Fast.Update(input);
100  var slowReady = Slow.Update(input);
101 
102  var macd = Fast.Current.Value - Slow.Current.Value;
103 
104  if (fastReady && slowReady)
105  {
106  if (Signal.Update(input.Time, macd))
107  {
108  Histogram.Update(input.Time, macd - Signal.Current.Value);
109  }
110  }
111 
112  return macd;
113  }
114 
115  /// <summary>
116  /// Resets this indicator to its initial state
117  /// </summary>
118  public override void Reset()
119  {
120  Fast.Reset();
121  Slow.Reset();
122  Signal.Reset();
123  Histogram.Reset();
124  base.Reset();
125  }
126  }
127 }